在配置了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种类,希望可以减少一些额外的怪癖。
答案 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);
如果isDaylight
是true
,则应使用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)}";
}
}