在为PST配置的计算机上给定本地DateTime值(当夏令时开始时,该值将在3月10日隐式更改为PDT),如何获得包括适当时区的字符串-例如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自定义格式字符串页面显示了在输出中显式硬编码"PST"的示例,这在半年和/或本地TZ更改时都是错误的。计算机和人都在移动,所以对TZ值进行硬编码根本"不合适"。
最好,这可以通过仅格式化字符串来完成,允许提供DateTime值,直到呈现/到字符串阶段-尽管似乎没有"ZZZ"格式。我指定了"本地"DateTime Kind,希望能减少一些额外的怪癖。。
由于DateTime
实例不保存时区信息,因此无法使用自定义日期和时间格式字符串来保存时区信息。"zzz"
说明符用于UTC偏移值,带有"K"
说明符的DateTime.Kind
也不反映时区缩写。两者对你的案子都没用。
然而,有一个名为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
属性,如果你想获得当前的语言代码,你可以顺便使用CultureInfo.CurrentCulture.Name
属性。
var tz = TZNames.GetAbbreviationsForTimeZone(TimeZoneInfo.Local.Id, CultureInfo.CurrentCulture.Name);
但在此之前,您应该检查您的本地时间是否为夏令时,以选择要附加格式化字符串的缩写。
DateTime now = DateTime.Now;
bool isDaylight = TimeZoneInfo.Local.IsDaylightSavingTime(now);
如果isDaylight
是true
,则应使用TimeZoneValues.Daylight
属性的结果,否则应使用第一个代码部分的TimeZoneValues.Standard
属性。
最后,您需要在DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss)
字符串的末尾附加其中一个缩写。
马特在包裹页面上的重要提示;
时区缩写有时不一致必须为每个时区正确定位。在大多数情况下,您应该仅对最终用户显示输出使用缩写。不要在分析输入时尝试使用缩写。
马特评论中的第二个重要注释;
是什么让你认为时区缩写实际上是为世界上每一个时区和每一种语言?甚至,那么你认为一个时区缩写就足以识别时间区提示-这两个问题都是无定形的。考虑"CST"或"IST"-每个人在世界上都有三四个他们可能属于的地方。还有许多许多其他情况。。。
TimeZoneInfo
应该能够在这里提供帮助:https://learn.microsoft.com/en-us/dotnet/api/system.timezoneinfo.standardname?view=netframework-4.7.2
看起来TimeZoneInfo
给出的是全名("太平洋标准时间"/"太平洋夏令时"),而不是缩写("PST"/"PDT")。如果这是一个问题,你仍然需要找到短名称的来源。这里有一些关于如何做到这一点的想法:时区缩写
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)}";
}
}