Blazor服务器端:如何读出用户/浏览器而不是服务器的本地时间仅使用c#

问题描述

我创建了一个页面,在该页面上为用户显示天气数据(我通过api调用获取数据)。我有来自api调用的数据的UTC时间戳。

我的问题是,如果我通过ToLocalTime()转换UTC时间,则会显示服务器的本地时间,而不是用户浏览器的本地时间。

有没有一种方法可以显示用户的“时间”:仅使用C#和Blazor的UTCTime.ToUserTimeZone()?

我对JS等的知识是零,或者那是唯一的方法。我在Google上搜索并找到了很多答案,在这些答案中,我必须实现JavaScript才能“获取用户本地化信息。

感谢您的帮助和时间

解决方法

您可以更简单地从 JS 读取本地和 UTC 时间并接收 .NET DateTime 类型

  • 当地时间:new Date().toISOString();
  • UTC 时间:new Date().toUTCString();

还要注意 .NET 5 JS Interop 中的变化很大。请查看新的 IJSRuntime Interface 以及 JS Isolation 文档。

通过使用 .NET 5 JS 隔离(调用 JS 函数非常相似但略有变化,请参阅上面的文档):

export function localDate() {
  return new Date().toISOString();
}
export function utcDate() {
  return new Date().toUTCString();
}
,

没有javascript不可能获得用户时间。
如果使用Blazor服务器端,则C#代码在服务器上运行。 但是您可以调用javascript函数。
参见https://docs.microsoft.com/en-us/aspnet/core/blazor/call-javascript-from-dotnet?view=aspnetcore-3.1

这是一个获取用户日期和时间偏移量的JavaScript(将脚本标签添加到_Host.cshtml的header元素中):

<script>
    window.localDate = () => {
        var ldCurrentDate = new Date();
        return ldCurrentDate.getFullYear() +
            "-" + String(ldCurrentDate.getMonth() + 1).padStart(2,'0') +
            "-" + String(ldCurrentDate.getDate()).padStart(2,'0') +
            "T" +
            String(ldCurrentDate.getHours()).padStart(2,'0') +
            ":" + String(ldCurrentDate.getMinutes()).padStart(2,'0') +
            ":" + String(ldCurrentDate.getSeconds()).padStart(2,'0');
    };
    window.utcDate = () => {
        var ldCurrentDate = new Date();
        return ldCurrentDate.getUTCFullYear() +
            "-" + String(ldCurrentDate.getUTCMonth() + 1).padStart(2,'0') +
            "-" + String(ldCurrentDate.getUTCDate()).padStart(2,'0') +
            "T" +
            String(ldCurrentDate.getUTCHours()).padStart(2,'0') +
            ":" + String(ldCurrentDate.getUTCMinutes()).padStart(2,'0') +
            ":" + String(ldCurrentDate.getUTCSeconds()).padStart(2,'0');
    };
    window.timeZoneOffset = () => {
        return new Date().getTimezoneOffset() / 60;
    };
</script>

从C#调用:

@page "/dates"
@inject IJSRuntime JSRuntime;

<button type="button" @onclick="GetDates">
    Get Dates
</button>

<p>
    <span>
        User Date: @string.Format("{0:G}",this.UserDate)
    </span>
</p>
<p>
    <span>
        Utc Date: @string.Format("{0:G}",this.UTCDate)
    </span>
</p>
<p>
    <span>
        TimeZoneOffset: @string.Format("{0}",this.TimeZoneOffset)
    </span>
</p>
<p>
    <span>
        ServerDate: @string.Format("{0:G}",this.ServerDate)
    </span>
</p>


@code {

    private DateTime UserDate { get; set; }
    private DateTime UTCDate { get; set; }
    private DateTime ServerDate { get; set; }
    private int TimeZoneOffset { get; set; }


    private async Task GetDates()
    {
        this.ServerDate = DateTime.Now;
        this.UserDate = await JSRuntime.InvokeAsync<DateTime>("localDate");
        this.UTCDate = await JSRuntime.InvokeAsync<DateTime>("utcDate");
        this.TimeZoneOffset = await JSRuntime.InvokeAsync<int>("timeZoneOffset");
    }
}
,

我遇到了类似的问题并创建了一个名为 Blazor Time 的库来解决它。

要安装 BlazorTime,请运行 Install-Package BlazorTime

然后将 <script src="_content/BlazorTime/blazorTime.js"></script> 添加到您的主机或索引文件

之后,您可以使用 <ToLocal> 标记以用户本地时间显示值

<p>
  @*UTC to browser time*@
  <ToLocal DateTime="testUtcTime" Format="ddd mmm dd yyyy HH:MM:ss"></ToLocal>
</p>

<p>
  @*server time to browser time*@
  <ToLocal DateTime="testServerTime" Format="default"></ToLocal>
</p>

<p>
  @*display as iso example 2021-05-10*@
  <ToLocal DateTime="testUtcTime" Format="yyyy-mm-dd"></ToLocal>
</p>

<p>
  @*display as time example 2pm*@
  <ToLocal DateTime="testUtcTime" Format="htt"></ToLocal>
</p>

<button @onclick="Update">Update Time</button>

@code {
  private DateTime testUtcTime = DateTime.UtcNow;
  private DateTime testServerTime = DateTime.Now;

  private void Update()
  {
    testUtcTime = DateTime.UtcNow;
    testServerTime = DateTime.Now;
  }
}