C# DateTime 'Z' 格式说明符在哪里?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/833102/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Where's the DateTime 'Z' format specifier?
提问by Daniel Crenna
[Update: Format specifiers are not the same thing as format strings; a format specifier is a piece of a custom format string, where a format string is 'stock' and doesn't provide customization. My problem is with specifiers not formats]
[更新:格式说明符与格式字符串不同;格式说明符是一段自定义格式字符串,其中格式字符串是 'stock' 并且不提供自定义。我的问题是说明符而不是格式]
I've been trying to perform roundtrip DateTime conversions with a format string that uses 'zzz' format specifier, which I know is bound to local time. So, if I attempt to round trip with a UTC date time it throws a DateTimeInvalidLocalFormat exception, which it should, with this text:
我一直在尝试使用使用“zzz”格式说明符的格式字符串执行往返日期时间转换,我知道它绑定到本地时间。因此,如果我尝试使用 UTC 日期时间往返,它会抛出一个 DateTimeInvalidLocalFormat 异常,它应该使用以下文本:
A UTC DateTime is being converted to text in a format that is only correct for local times. This can happen when calling DateTime.ToString using the 'z' format specifier, which will include a local time zone offset in the output. In that case, either use the 'Z' format specifier, which designates a UTC time, or use the 'o' format string, which is the recommended way to persist a DateTime in text. This can also occur when passing a DateTime to be serialized by XmlConvert or DataSet. If using XmlConvert.ToString, pass in XmlDateTimeSerializationMode.RoundtripKind to serialize correctly. If using DataSet, set the DateTimeMode on the DataColumn object to DataSetDateTime.Utc.
UTC 日期时间正在转换为仅适用于本地时间的格式的文本。使用“z”格式说明符调用 DateTime.ToString 时可能会发生这种情况,该说明符将在输出中包含本地时区偏移量。在这种情况下,请使用指定 UTC 时间的“Z”格式说明符,或使用“o”格式字符串,这是在文本中保留 DateTime 的推荐方法。当传递要由 XmlConvert 或 DataSet 序列化的 DateTime 时,也会发生这种情况。如果使用 XmlConvert.ToString,请传入 XmlDateTimeSerializationMode.RoundtripKind 以正确序列化。如果使用 DataSet,请将 DataColumn 对象上的 DateTimeMode 设置为 DataSetDateTime.Utc。
Based on this suggestion, all I need to do to get my code to work is to replace 'zzz' with 'ZZZ' so I can stand in a UTC format. The problem is, 'Z' isn't found anywhere in the documentation and any 'Z' format combination I try, i.e. 'Z', 'ZZ', 'ZZZ', always just converts the DateTime instance with those Z's treated like literals.
根据这个建议,我需要做的就是让我的代码正常工作,就是用 'ZZZ' 替换 'zzz',这样我就可以使用 UTC 格式了。问题是,在文档中的任何地方都找不到“Z”,我尝试过的任何“Z”格式组合,即“Z”、“ZZ”、“ZZZ”,始终只是将 DateTime 实例转换为将那些 Z 视为文字.
Did someone forget to implement 'Z' without telling the exception message author, or am I missing how to swap out a valid local time offset with "+0000" without hacking?
是否有人忘记在没有告诉异常消息作者的情况下实现“Z”,或者我是否错过了如何用“+0000”换出有效的本地时间偏移而不进行黑客攻击?
Code Example:
代码示例:
// This is the format with 'zzzzz' representing local time offset
const string format = "ddd MMM dd HH:mm:ss zzzzz yyyy";
// create a UTC time
const string expected = "Fri Dec 19 17:24:18 +0000 2008";
var time = new DateTime(2008, 12, 19, 17, 24, 18, 0, DateTimeKind.Utc);
// If you're using a debugger this will rightfully throw an exception
// with .NET 3.5 SP1 because 'z' is for local time only; however, the exception
// asks me to use the 'Z' specifier for UTC times, but it doesn't exist, so it
// just spits out 'Z' as a literal.
var actual = time.ToString(format, CultureInfo.InvariantCulture);
Assert.AreEqual(expected, actual);
采纳答案by Andy White
Maybe the "K" format specifier would be of some use. This is the only one that seems to mention the use of capital "Z".
也许“K”格式说明符会有用。这是唯一一个似乎提到使用大写“Z”的地方。
"Z" is kind of a unique case for DateTimes. The literal "Z" is actually part of the ISO 8601 datetime standard for UTC times. When "Z" (Zulu) is tacked on the end of a time, it indicates that that time is UTC, so really the literal Z is part of the time. This probably creates a few problems for the date format library in .NET, since it's actually a literal, rather than a format specifier.
“Z”是 DateTimes 的一种独特情况。文字“Z”实际上是 UTC 时间的 ISO 8601 日期时间标准的一部分。当时间末尾加上“Z”(祖鲁语)时,表示该时间是 UTC,因此文字 Z 确实是时间的一部分。这可能会给 .NET 中的日期格式库带来一些问题,因为它实际上是一个文字,而不是格式说明符。
回答by Fredrik M?rk
This pageon MSDN lists standard DateTime format strings, uncluding strings using the 'Z'.
MSDN 上的此页面列出了标准日期时间格式字符串,不包括使用“Z”的字符串。
Update: you will need to make sure that the rest of the date string follows the correct pattern as well (you have not supplied an example of what you send it, so it's hard to say whether you did or not). For the UTC format to work it should look like this:
更新:您需要确保日期字符串的其余部分也遵循正确的模式(您没有提供发送内容的示例,因此很难说您是否做了)。要使 UTC 格式正常工作,它应该如下所示:
// yyyy'-'MM'-'dd HH':'mm':'ss'Z'
DateTime utcTime = DateTime.Parse("2009-05-07 08:17:25Z");
回答by balexandre
Label1.Text = dt.ToString("dd MMM yyyy | hh:mm | ff | zzz | zz | z");
will output:
将输出:
07 Mai 2009 | 08:16 | 13 | +02:00 | +02 | +2
I'm in Denmark, my Offset from GMT is +2 hours, witch is correct.
我在丹麦,我的 GMT 偏移量是 +2 小时,女巫是正确的。
if you need to get the CLIENT Offset, I recommend that you check a little trickthat I did. The Page is in a Server in UK where GMT is +00:00 and, as you can see you will get your local GMT Offset.
如果您需要获得CLIENT Offset,我建议您检查我所做的一个小技巧。该页面位于英国的服务器中,格林威治标准时间为 +00:00,如您所见,您将获得当地的格林威治标准时间偏移量。
Regarding you comment, I did:
关于你的评论,我做了:
DateTime dt1 = DateTime.Now;
DateTime dt2 = dt1.ToUniversalTime();
Label1.Text = dt1.ToString("dd MMM yyyy | hh:mm | ff | zzz | zz | z");
Label2.Text = dt2.ToString("dd MMM yyyy | hh:mm | FF | ZZZ | ZZ | Z");
and I get this:
我明白了:
07 Mai 2009 | 08:24 | 14 | +02:00 | +02 | +2
07 Mai 2009 | 06:24 | 14 | ZZZ | ZZ | Z
I get no Exception, just ... it does nothing with capital Z :(
我没有例外,只是......它对大写 Z 没有任何作用:(
I'm sorry, but am I missing something?
我很抱歉,但我错过了什么吗?
Reading carefully the MSDN on Custom Date and Time Format Strings
仔细阅读有关自定义日期和时间格式字符串的 MSDN
there is no support for uppercase 'Z'.
不支持大写“Z”。
回答by Paul Alexander
Round tripping dates through strings has always been a pain...but the docs to indicate that the 'o' specifier is the one to use for round tripping which captures the UTC state. When parsed the result will usually have Kind == Utc if the original was UTC. I've found that the best thing to do is always normalize dates to either UTC or local prior to serializing then instruct the parser on which normalization you've chosen.
通过字符串往返日期一直很痛苦......但是文档表明'o'说明符是用于捕获UTC状态的往返行程的说明符。如果原始是 UTC,则解析结果通常会具有 Kind == Utc。我发现最好的做法是在序列化之前将日期标准化为 UTC 或本地,然后指示解析器您选择的标准化。
DateTime now = DateTime.Now;
DateTime utcNow = now.ToUniversalTime();
string nowStr = now.ToString( "o" );
string utcNowStr = utcNow.ToString( "o" );
now = DateTime.Parse( nowStr );
utcNow = DateTime.Parse( nowStr, null, DateTimeStyles.AdjustToUniversal );
Debug.Assert( now == utcNow );
回答by Marco Staffoli
When you use DateTime you are able to store a date and a time inside a variable.
使用 DateTime 时,您可以在变量中存储日期和时间。
The date can be a local time or a UTC time, it depend on you.
日期可以是当地时间或 UTC 时间,这取决于您。
For example, I'm in Italy (+2 UTC)
例如,我在意大利(+2 UTC)
var dt1 = new DateTime(2011, 6, 27, 12, 0, 0); // store 2011-06-27 12:00:00
var dt2 = dt1.ToUniversalTime() // store 2011-06-27 10:00:00
So, what happen when I print dt1 and dt2 including the timezone?
那么,当我打印 dt1 和 dt2 包括时区时会发生什么?
dt1.ToString("MM/dd/yyyy hh:mm:ss z")
// Compiler alert...
// Output: 06/27/2011 12:00:00 +2
dt2.ToString("MM/dd/yyyy hh:mm:ss z")
// Compiler alert...
// Output: 06/27/2011 10:00:00 +2
dt1 and dt2 contain only a date and a time information. dt1 and dt2 don't contain the timezone offset.
dt1 和 dt2 仅包含日期和时间信息。dt1 和 dt2 不包含时区偏移量。
So where the "+2" come from if it's not contained in the dt1 and dt2 variable?
那么如果“+2”不包含在 dt1 和 dt2 变量中,它从哪里来?
It come from your machine clock setting.
它来自您的机器时钟设置。
The compiler is telling you that when you use the 'zzz' format you are writing a string that combine "DATE + TIME" (that are store in dt1 and dt2) + "TIMEZONE OFFSET" (that is not contained in dt1 and dt2 because they are DateTyme type)and it will use the offset of the server machine that it's executing the code.
编译器告诉您,当您使用“zzz”格式时,您正在编写一个字符串,该字符串组合了“DATE + TIME”(存储在 dt1 和 dt2 中)+ “TIMEZONE OFFSET”(未包含在 dt1 和 dt2 中,因为它们是 DateTyme 类型),它将使用它正在执行代码的服务器机器的偏移量。
The compiler tell you "Warning: the output of your code is dependent on the machine clock offset"
编译器告诉你“警告:你的代码的输出取决于机器时钟偏移”
If i run this code on a server that is positioned in London (+1 UTC) the result will be completly different: instead of "+2" it will write "+1"
如果我在位于伦敦(+1 UTC)的服务器上运行此代码,结果将完全不同:它会写成“ +1”而不是“ +2”
...
dt1.ToString("MM/dd/yyyy hh:mm:ss z")
// Output: 06/27/2011 12:00:00 +1
dt2.ToString("MM/dd/yyyy hh:mm:ss z")
// Output: 06/27/2011 10:00:00 +1
The right solution is to use DateTimeOffset data type in place of DateTime. It's available in sql Server starting from the 2008 version and in the .Net framework starting from the 3.5 version
正确的解决方案是使用 DateTimeOffset 数据类型代替 DateTime。它从 2008 版本开始在 sql Server 中可用,在 .Net 框架中从 3.5 版本开始
回答by Kugel
I was dealing with DateTimeOffset
and unfortunately the "o" prints out "+0000" not "Z".
我正在处理,DateTimeOffset
不幸的是“o”打印出“+0000”而不是“Z”。
So I ended up with:
所以我结束了:
dateTimeOffset.UtcDateTime.ToString("o")