我了解该系统。TimeZone类以及DateTime的许多用法。ToString()方法。我还没有找到一种将DateTime转换为字符串的方法,该字符串除了包含时间和日期信息外,还包含三个字母的时区缩写(事实上,与StackOverflow的相对时间显示工具提示的工作方式大致相同)。
为了让每个人都能很容易地遵循和使用一个示例,让我们继续使用StackOverflow示例。如果查看显示在相对时间上的工具提示,它会显示完整日期、时间(包括十二小时格式的秒)、AM/PM名称,然后是三个字母的时区缩写(在这种情况下,为协调世界时)。我意识到使用内置的方法可以很容易地获得GMT或UTC,但我真正想要的是本地的时间—在这种情况下,在web服务器上。
如果我们的web服务器运行的是Windows server 2k3,并且它的时区设置为CST(或者,在夏令时恢复之前,是CDT吗?),我希望我们的ASP。NET web应用程序显示相对于该时区的DateTimes,并格式化为在末尾显示"CST"。我意识到我可以很容易地对其进行硬编码,但为了健壮性,我真的更喜欢基于运行代码的操作系统环境设置的服务器的解决方案。
现在,除了使用以下代码的时区缩写外,我什么都有:
myDateTime.ToString("MM/dd/yyyy hh:mm:ss tt")
哪个显示:
2008年7月10日下午03:40:31
我只想让它说:
2008年7月10日下午03:40:31
我可以使用系统。时区。CurrentTimeZone并使用它来正确显示"中央夏令时",但是。。。为了简洁起见,这有点太长了。我是不是一直在写一个字符串操作例程来去掉空白和任何非大写字母?虽然这可能会奏效,但对我来说,这似乎是一个令人难以置信的破解…
在谷歌上搜索并环顾四周,并没有产生任何适用于我特定问题的内容。
下面是我为解决这个问题而制作的快速破解方法。
public static String TimeZoneName(DateTime dt)
{
String sName = TimeZone.CurrentTimeZone.IsDaylightSavingTime(dt)
? TimeZone.CurrentTimeZone.DaylightName
: TimeZone.CurrentTimeZone.StandardName;
String sNewName = "";
String[] sSplit = sName.Split(new char[]{' '});
foreach (String s in sSplit)
if (s.Length >= 1)
sNewName += s.Substring(0, 1);
return sNewName;
}
有一个免费提供的库TZ4NET,其中提供了这些缩写。之前。NET 3.5,这也是在时区之间转换的唯一替代方案之一。
如果你不想要一个单独的库,你当然可以使用TimeZoneInfo类生成一个合理缩写的映射,然后把它们提供给你的用户。
使用nodatime。
以下函数采用UTC时间的DateTime
,并使用缩写的本地系统时区对其进行格式化。在缩写时区的字符串格式中使用x
。在此处查找自定义格式。
public static string ConvertToFormattedLocalTimeWithTimezone(DateTime dateTimeUtc)
{
var tz = DateTimeZoneProviders.Tzdb.GetSystemDefault(); // Get the system's time zone
var zdt = new ZonedDateTime(Instant.FromDateTimeUtc(dateTimeUtc), tz);
return zdt.ToString("MM'/'dd'/'yyyy' 'hh':'mm':'ss' 'tt' 'x", CultureInfo.InvariantCulture);
}
我会创建一个查找表,将时区名称转换为其缩写。如果没有找到匹配项,您可以返回完整的区域名称。
请参阅时区缩写。
如果从DaylightName/StandardName中提取缩写,最好使用StringBuilder构建字符串,因为字符串是不可变的。
public static string ToCurrentTimeZoneString(this DateTime date)
{
string name = TimeZone.CurrentTimeZone.IsDaylightSavingTime(date) ?
TimeZone.CurrentTimeZone.DaylightName :
TimeZone.CurrentTimeZone.StandardName;
return name;
}
public static string ToCurrentTimeZoneShortString(this DateTime date)
{
StringBuilder result = new StringBuilder();
foreach (string value in date.ToCurrentTimeZoneString().Split(' '))
{
if (value.IsNotNullOrEmptyWithTrim())
{
result.Append(char.ToUpper(value[0]));
}
}
return result.ToString();
}
当然,对于跨国公司来说,包含KeyValuePair的数组可能是最好的。如果你想在紧迫的截止日期前缩短几分钟,而你在一家美国公司,这是可行的。
这取决于您需要的健壮性级别。
无论哪种方式,你都可能需要某种破解。一个简单的方法是用空格分隔字符串,然后连接每个单词的第一个字母。即
string[] words = tzname.Split(" ".ToCharArray());
string tzabbr = "";
foreach (string word in words)
tzabbr += word[0];
这不会适用于地球上的每个时区,但对大多数时区都有效。如果你需要它更健壮,那么你可能需要创建一个地图,将时区名称映射到它们的缩写。
好吧,已经4年了(将近一周),是时候让LINQ参与讨论了。。。
把克里格和鲍勃的想法放在一起。。。
public static String TimeZoneName2(DateTime dt)
{
var return ToCurrentTimeZoneShortString(dt)
.Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries);
return sSplit.Aggregate("", (st,w)=> st +=w[0]);
}
除非您相信TimeZone永远不会返回具有两个连续空格的字符串:
public static String TimeZoneName3(DateTime dt)
{
return ToCurrentTimeZoneShortString(dt).Split(' ')
.Aggregate("", (st,w)=> st +=w[0]);
}
如果您正在使用<=。Net 3.0,然后下载TZ4Net并使用Olson时区。CurrentTimeZone。标准>的缩写。Net 3.0使用NodaTime或其他。时区名称不符合任何约定,在这些约定中,您可以依靠简单的字符串操作来从首字母缩略词构造缩写。错误的5%的时间仍然是错误的。