如何将服务器时间转换为本地时间并处理夏令时



我在Godaddy上托管我的网站(asp.net webforms, .net 4.5, SQL Server 2012),他们(服务器)使用Mountain Standard Time (-7UTC时间相比),这是从未改变观察夏令时

如果我输入

Response.Write("UTC Time: " + DateTime.UtcNow.ToString() + "<br/>");
Response.Write("Server Time: " + DateTime.Now.ToString() + "<br/>");
Response.Write("Server DateTimeOffset: " + DateTimeOffset.Now.ToString() + "<br/>");

显示如下:

UTC Time: 9/18/2015 5:14:09 PM
Server Time: 9/18/2015 10:14:09 AM
Server DateTimeOffset: 9/18/2015 10:14:09 AM -07:00

但是我的用户位于佐治亚州亚特兰大,确实遵守夏令时,并且根据timeanddate.com,他们在夏季使用EDT,在冬季使用EST

如何获得正确的用户当前时间?假设用户打开我的web应用程序并点击Show my time按钮,它会显示一个正确的当前用户的时间?

  1. 永远不要依赖服务器的时区设置。因此,在ASP中不应该使用DateTime.Now 。网络应用程序。

    避免DateTime.Now还有许多其他原因。阅读:针对DateTime.Now的案例

  2. 无论如何,服务器的本地时间永远不能保证是您网站用户的本地时间。如果是,那只是巧合。

  3. 获取用户当前时区时间的最简单方法是通过JavaScript:

    var now = new Date();
    

    虽然这是基于用户的时钟,这可能是或不正确的设置。为了保证时间,您必须使用服务器时钟的UTC时间,并应用用户的时区。

    您可以考虑的一种方法是将服务器的UTC时间发送到客户端,然后将其加载到客户端的JavaScript中,以将其投影到他们的时区:

    // C#
    string serverUtcTime = DateTime.UtcNow.ToString("o");  // "2015-09-18T17:53:15.6988370Z"
    // JS
    var now = new Date("2015-09-18T17:53:15.6988370Z");
    
  4. 实际上检测用户的时区是一个难题,目前还没有解决方案。有些人可能会推荐new Date().getTimezoneOffset(),但这只会给您当前的数字偏移量,而不是时区。夏令时可以改变偏移量,许多时区使用类似的偏移量。在夏令时转换附近的历史日期也有一些复杂的情况,这将对您不利。

    像jsTimeZoneDetect这样的脚本可以猜测您的IANA时区ID,例如东部时间的America/New_York,但它们不是100%准确的。如果您需要服务器上用户的时区,那么最终应该在应用程序的某个地方询问用户的时区。
  5. 在。net中,您可以使用野田时间与IANA时区一起工作。没有Noda时间,. net有TimeZoneInfo类,但它只能工作在Windows时区

  6. 如果您知道的某些用户在亚特兰大,GA(这是在美国东部时区),那么您可以这样做:

    DateTime utc = DateTime.UtcNow;
    TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
    DateTime eastern = TimeZoneInfo.ConvertTimeFromUtc(utc, tz); 
    

    或者,带有Noda时间和IANA时区id:

    Instant now = SystemClock.Instance.Now;
    DateTimeZone tz = DateTimeZoneProviders.Tzdb["America/New_York"];
    ZonedDateTime eastern = now.InZone(tz);
    

可以使用TimeZoneInfo。ConvertTime从一个时区转换到另一个时区。然而,如果您只是转换为EST或EDT,它将始终显示该值。如果您希望始终为客户端显示正确的时间,则需要使用Javascript将客户端浏览器的本地时区存储在cookie中,然后使用该值作为要转换到的时区。

从服务器获取UtcTime并使用TimeZoneInfo进行转换可能会更精简一些。ConvertTimeFromUtc,如果您希望做这些的话。基本相同的过程。

看一下这个例子。这很简单。

[Test, TestCase(1), TestCase(9)]
    public void Test(int month)
    {
        var serverTime = new DateTime(2015, month, 18, 10, 14, 09);
        // No Daylight saving in Russia
        var serverTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");
        // Daylight saving in Atlanta
        var localTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Atlantic Standard Time");
        // check if ConvertTime take care of daylight saving
        var localTime = TimeZoneInfo.ConvertTime(serverTime, serverTimeZone, localTimeZone);
        // it does
        if (localTimeZone.IsDaylightSavingTime(localTime))
            Assert.AreEqual(string.Format("{0}/18/15 04:14 AM", month), localTime.ToString("M/dd/yy hh:mm tt", System.Globalization.CultureInfo.InvariantCulture));
        else
            Assert.AreEqual(string.Format("{0}/18/15 03:14 AM", month), localTime.ToString("M/dd/yy hh:mm tt", System.Globalization.CultureInfo.InvariantCulture));
    }

相关内容

  • 没有找到相关文章