javascriptblazor-server-side

JavaScript new Date() returning server time offset in Blazor Server app


I have a Blazor Server app that needs to know the local time zone for its work (it's a scheduling app that uses the DxScheduler). The strategy is to obtain the local time offset from the user's browser, using the JavaScript new Date() object and sending the offset back to C# code for manipulation.

Through extensive testing, I've verified that the C# transformations work as expected. However, the JavaScript call is returning the server's time zone offset, not the client's. I've verified this by changing the time zone of the server and observing that the output of the code changes predictably in relation to the change in server time zone.

My hypothesis is that the JavaScript is being sandboxed by the Blazor environment, much as I understand Node.js does, which begs the question of how one unsandboxes the JS code.

Here is the JavaScript code, which resides in its own .js file in the /wwwroot folder:

function getTimeZoneOffset() {
    var dateString = new Date();
    var offset = dateString.getTimezoneOffset();
    return offset;
}

Here is the C# code that consumes that script, currently residing in App.razor:

public async Task<string> CAllJS()
{
    var offset = await JSRuntime.InvokeAsync<string>("getTimeZoneOffset");
    return offset;
}

public async Task<TimeZoneInfo> GetUserTimeZone()
{
    string jsNumberOfMinutesOffset = await CAllJS(); // sending the above offset
    var timeZones = TimeZoneInfo.GetSystemTimeZones();
    var numberOfMinutes = Int32.Parse(jsNumberOfMinutesOffset) * (-1);
    var timeSpan = TimeSpan.FromMinutes(numberOfMinutes);
    var userTimeZone = timeZones.Where(tz => tz.BaseUtcOffset == timeSpan).FirstOrDefault() ?? timeZones.First();

    return userTimeZone;
}

This is about as much separation as I can think of - the caller of GetUserTImeZone() assigns the return value to a static property of a static class, so it can be accessed anywhere it's needed. Yet, I'm still getting the server's time zone offset.

Thoughts?


Solution

  • It turns out that the crux of my problem was that my C# code couldn't find my JavaScript file, in the the first place. I ended up changing approach entirely by rewriting the JavaScript and using the TimeZoneConverter NuGet package, as so:

        public async Task<TimeZoneInfo> GetTimeZoneInfoAsync()
        {
            var timeZone = await JSRuntime.InvokeAsync<string>("getTimeZone");
            string systemTimeZoneId = TZConvert.IanaToWindows(timeZone);
            var tz = TimeZoneInfo.FindSystemTimeZoneById(systemTimeZoneId);
            return tz;
        }
    

    The JavaScript file resides in the wwwroot folder of the Blazor project:

    function getTimeZone() {
        var timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
        return timeZone;
    }
    

    Works perfectly!