DEV Community

loading...

[Workaround] How to resolve local time zone on Blazor SPA (v.0.5.x)?

jsakamoto
Microsoft MVP for Visual Studio and Development Tech. (prefer C#, .NET Core, ASP.NET Core, Azure Web Apps, TypeScript, and Blazor WebAssembly App!)
・4 min read

Introduction: What's "Blazor"?

"Blazor" is a Single Page Web Application (a.k.a "SPA") framework.

Blazor allows you to running C# code and .NET Standard 2.0 native assembly (.dll) on a top of modern web browser, without any .NET server processes.

If you are new to Blazor, I recommend watching this YouTube video.

NDC Oslo 2017 - "Web Apps can’t really do that, can they? - Steve Sanderson"

The video was about prototype of Blazor, and the current version when I wrote this post was v.0.5.x, which had some breaking changes. But that video is useful to understanding the concept and pros/cons of "Blazor".

Problem: Blazor SPA has no time zone information ...!

I feel Blazor is a great framework for C# developers.

However, Blazor is still an experimental project at the moment.

Recently I found one of the cases showing that a Blazor is still an experimental project.

Amazingly, count of time zone information on Blazor application is "0"!

Therefore, "TimeZoneInfo.Local" always returns the UTC time zone, " DateTime.Now" always returns the UTC time, regardless of the local setting of the browser or OS.

fig.1

What can we do if we need to access local time or any time zone information?

Quick Solution: Use "Toolbelt.Blazor.TimeZoneKit" NuGet package.

You can resolve this issue by installing "Toolbelt.Blazor.TimeZoneKit" NuGet package on your Blazor application project as follows.

Step.1 - Install the NuGet package, like follows.

> dotnet add package Toolbelt.Blazor.TimeZoneKit
Enter fullscreen mode Exit fullscreen mode

Step.2 - call "UseLocalTimeZone()" extension method that is provided by the package, in "Configure()" method of the startup class.

...
using Toolbelt.Blazor.TimeZoneKit;

public class Startup
{
    ...
    public void Configure(IBlazorApplicationBuilder app)
    {
        app.UseLocalTimeZone();
    ...
Enter fullscreen mode Exit fullscreen mode

That's all!

fig.2

How does it setup the system time zone information?

There is no magic.

"Toolbelt.Blazor.TimeZoneKit" just contains all of the .NET system time zone information in it's assembly (.dll) file.

(see: "TimeZoneKit.CreateSystemTimeZones.cs")

"UseLocalTimeZone()" extension method override private field of "TimeZoneInfo" by reflection technology to setup the system time zone information on the application runtime.

How does it get the local time zone of the browser?

Recently, most web browsers support "Intl.DateTimeFormat().resolvedOptions().timeZone" JavaScript code.

That JavaScript code returns local time zone name.

Blazor provides a way of interoperability of C# code and JavaScript code, so "UseLocalTimeZone()" extension method can calls the JavaScript code that to get local timezone name.

fig.3

However, the interope code from C# to JavaScript is asynchronous.

If "UseLocalTimeZone()" extension method can't complete setting up of local time zone synchronously during its execution time, it will cause terrible bags.

fig.4

However, because it causes a deadlock, we can not wait synchronously for task results.

fig.5

To avoid this problem, "UseLocalTimeZone()" extension method invokes the JavaScript code that calls back C# code.

Since the interope code from JavaScript to C# is synchronously, the loca time zone setup process will complete until "UseLocalTimeZone()" extension method is returned ;)

fig.6

How to convert IANA time zone name to .NET time zone id?

The JavaScript code "Intl.DateTimeFormat().resolvedOptions().timeZone" returns the time zone name, but it's not the .NET time zone id.

The local time zone name of JavaScript is called "IANA time zone name".

In order to convert IANA time zone name to .NET time zone id, "Toolbelt.Blazor.TimeZoneKit" contains the mapping information from IANA time zone name to .NET time zone id, in it's assembly (.dll) file.

(see: "TimeZoneKit.IANAtoTZIdMap.cs")

Note

  • WARNING - The library accesses private members of System.TimeZoneInfo using the "Reflection" .NET API, so it may break in future .NET runtime (mono.wasm) release.
  • In my test case, the library increased the size of a Blazor browser application content by 154 KB. (by 20KB gzip transfer.)

Conclusion

The future release of Blazor will be supported local time zone, I think.

See also:

DateTime always displays as UTC #15776

DateTime values always display as UTC time, rather than local time even when explicitly forcing .ToLocalTime().

This:

Console.WriteLine(DateTime.Now.ToLocalTime().ToString("HH:mm"));
Enter fullscreen mode Exit fullscreen mode

displays UTC time.

"Toolbelt.Blazor.TimeZoneKit" NuGet package will help you until Blazor support time zones.

Let's look forward to the new release of Blazor!

Happy coding with Blazor :)

Discussion (1)

Collapse
dustout profile image
Dustin

Another option would be to use Blazor Time

github.com/dustout/BlazorTime