/// <inheritdoc />
        public async Task InvokeAsync(HttpContext httpContext, RequestDelegate next)
        {
            if (httpContext == null)
            {
                throw new ArgumentNullException(nameof(httpContext));
            }

            if (next == null)
            {
                throw new ArgumentNullException(nameof(next));
            }

            var requestTimeZone = this.options.DefaultRequestTimeZone;
            IRequestTimeZoneProvider winningProvider = null;

            if (this.options.RequestTimeZoneProviders != null)
            {
                foreach (var provider in this.options.RequestTimeZoneProviders)
                {
                    var providerTimeZoneResult = await provider
                                                 .DetermineProviderTimeZoneResult(httpContext);

                    if (providerTimeZoneResult == null)
                    {
                        continue;
                    }

                    try
                    {
                        var result = new RequestTimeZone(providerTimeZoneResult.TimeZoneName);

                        if (result.TimeZone != null)
                        {
                            requestTimeZone = result;
                            winningProvider = provider;
                            break;
                        }
                    }
                    catch (InvalidTimeZoneException ex)
                    {
                        this.logger.LogWarning(ex, $"Invalid TimeZone Id: {providerTimeZoneResult.TimeZoneName}");
                    }
                    catch (TimeZoneNotFoundException ex)
                    {
                        this.logger.LogWarning(ex, $"TimeZone Not Found: {providerTimeZoneResult.TimeZoneName}");
                    }
                }
            }

            httpContext.Features
            .Set <IRequestTimeZoneFeature>(new RequestTimeZoneFeature(requestTimeZone, winningProvider));

            httpContext.Response.Headers[RequestTimeZoneHeaderProvider.Headerkey] = requestTimeZone.TimeZone.Id;

            DateTimeInfo.TimeZone = new ThreadLocal <TimeZoneInfo>(() => requestTimeZone.TimeZone);

            await next(httpContext);
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="requestTimeZone">The <see cref="RequestTimeZone"/>.</param>
 /// <param name="provider">The <see cref="IRequestTimeZoneProvider"/>.</param>
 public RequestTimeZoneFeature(RequestTimeZone requestTimeZone, IRequestTimeZoneProvider provider = null)
 {
     this.RequestTimeZone = requestTimeZone ?? throw new ArgumentNullException(nameof(requestTimeZone));
     this.Provider        = provider;
 }