根据一年中的时间,使用适当的本地DST时区(例如PST或PDT)格式化Local DateTime。

时间:2019-02-09 21:20:32

标签: c# .net datetime localization timezone

在配置了PST的计算机上给定一个 Local DateTime值(它将在3月10日DST启动时隐式更改为PDT),如何获取包含适当的 timezone的字符串-例如PST / PDT,不抵消! -在输出中?

DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ???")

期望的输出字符串,例如:

"2019-02-09 13:04:22 PST"  // right after lunch today
"2019-04-09 13:04:22 PDT"  // right after lunch in two months

MSDN DateTime Custom Format Strings页面显示了将“ PST”明确硬编码到输出中的示例,这在半年和/或更改本地TZ时将是错误的。计算机和人员在移动,因此硬编码TZ值根本“不合适”。

最好使用格式字符串 just 来完成此操作,允许提供DateTime值,直到呈现/到字符串阶段为止-尽管似乎没有'ZZZ'格式。我已指定“本地” DateTime种类,希望可以减少一些额外的怪癖。

2 个答案:

答案 0 :(得分:2)

由于DateTime实例不保存时区信息,因此无法使用自定义日期和时间格式字符串来实现。 "zzz" specifier表示UTC Offset的值,DateTime.Kind"K" specifier都不反映时区缩写。两者对您的情况都没有用。

但是,有一个名为TimeZoneNames的nuget程序包,它由时区怪胎Matt Johnson编写,您可以获取时区名称的缩写(同时支持IANA和Windows时区标识符)

var tz = TZNames.GetAbbreviationsForTimeZone("Pacific Standard Time", "en-US");
Console.WriteLine(tz.Standard); // PST
Console.WriteLine(tz.Daylight); // PDT

如果要通过编程方式获取Windows时区标识符,则可以使用TimeZoneInfo.Local.Id property,如果要获取当前的语言代码,则可以使用CultureInfo.CurrentCulture.Name property

var tz = TZNames.GetAbbreviationsForTimeZone(TimeZoneInfo.Local.Id, CultureInfo.CurrentCulture.Name);

但是在此之前,您应该检查当地时间是否为夏令时,以选择附加缩写的字符串。

DateTime now = DateTime.Now;
bool isDaylight = TimeZoneInfo.Local.IsDaylightSavingTime(now);

如果isDaylighttrue,则应使用TimeZoneValues.Daylight属性的结果,否则应使用第一个代码部分的TimeZoneValues.Standard属性。

最后,您需要在DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss)字符串的末尾附加一个缩写。

有关包裹页面上Matt的重要说明;

  

时区缩写有时不一致,并且不是   必须在每个时区都正确定位。绝大多数情况下,   您应仅将缩写用于最终用户显示输出。不要   尝试在解析输入时使用缩写。

Matt's comment中的第二个重要说明;

  

是什么让您认为时区缩写实际上存在于   世界上每个时区和每种语言?即使如此,是什么使   您认为时区缩写足以识别时间   区?提示-这两个问题都是不确定的。考虑“ CST”或“ IST”-   每个人在世界上可能都属于三个或四个位置。   还有很多很多其他情况...

答案 1 :(得分:1)

TimeZoneInfo应该可以在这里提供帮助:https://docs.microsoft.com/en-us/dotnet/api/system.timezoneinfo.standardname?view=netframework-4.7.2

看起来TimeZoneInfo给出了全名(“太平洋标准时间” /“太平洋夏令时间”)而不是缩写(“ PST” /“ PDT”)。这是一个问题,您仍然需要找到短名称的来源。这里有一些有关如何执行此操作的想法:Timezone Abbreviations

using System;
using Xunit;

namespace Q54610867
{
    public class TimeZoneTests
    {
        // I'm on Mac/Unix. If you're on Windows, change the ID to "Pacific Standard Time"
        // See: https://github.com/dotnet/corefx/issues/2538
        readonly TimeZoneInfo pacificStandardTime = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");

        [Fact]
        public void Today()
        {
            var today = new DateTime(2019, 2, 9, 13, 4, 22, DateTimeKind.Local);

            Assert.Equal("2019-02-09 13:04:22 Pacific Standard Time", ToStringWithTz(today, pacificStandardTime));
        }

        [Fact]
        public void future()
        {
            var future = new DateTime(2019, 4, 9, 13, 4, 22, DateTimeKind.Local);

            Assert.Equal("2019-04-09 13:04:22 Pacific Daylight Time", ToStringWithTz(future, pacificStandardTime));
        }

        static string ToStringWithTz(DateTime dateTime, TimeZoneInfo tz)
            => $"{dateTime.ToString("yyyy-MM-dd HH:mm:ss")} {(tz.IsDaylightSavingTime(dateTime) ? tz.DaylightName : tz.StandardName)}";
    }
}