program tip

DateTime 'Z'형식 지정자는 어디에 있습니까?

radiobox 2020. 12. 31. 08:09
반응형

DateTime 'Z'형식 지정자는 어디에 있습니까?


[ 업데이트 : 형식 지정자는 형식 문자열과 동일하지 않습니다. 형식 지정자는 사용자 지정 형식 문자열의 일부이며 형식 문자열은 'stock'이며 사용자 지정을 제공하지 않습니다. 내 문제는 형식이 아닌 지정자에 있습니다 ]

현지 시간에 바인딩되어있는 'zzz'형식 지정자를 사용하는 형식 문자열로 왕복 DateTime 변환을 수행하려고했습니다. 따라서 UTC 날짜 시간으로 왕복을 시도하면 다음 텍스트와 함께 DateTimeInvalidLocalFormat 예외가 발생합니다.

UTC DateTime은 현지 시간에만 올바른 형식의 텍스트로 변환됩니다. 이는 출력에 현지 시간대 오프셋을 포함하는 'z'형식 지정자를 사용하여 DateTime.ToString을 호출 할 때 발생할 수 있습니다. 이 경우 UTC 시간을 지정하는 'Z'형식 지정자를 사용하거나 텍스트에서 DateTime을 유지하는 데 권장되는 방법 인 'o'형식 문자열을 사용하십시오. XmlConvert 또는 DataSet에서 serialize 할 DateTime을 전달할 때도 발생할 수 있습니다. XmlConvert.ToString을 사용하는 경우 XmlDateTimeSerializationMode.RoundtripKind를 전달하여 올바르게 직렬화합니다. DataSet을 사용하는 경우 DataColumn 개체의 DateTimeMode를 DataSetDateTime.Utc로 설정합니다.

이 제안에 따라 코드가 작동하도록하려면 'zzz'를 'ZZZ'로 바꾸면 UTC 형식으로 서있을 수 있습니다. 문제는 문서의 어디에도 'Z'가없고 내가 시도하는 'Z'형식 조합 (예 : 'Z', 'ZZ', 'ZZZ')은 항상 리터럴처럼 처리 된 Z로 DateTime 인스턴스를 변환한다는 것입니다. .

누군가 예외 메시지 작성자에게 알리지 않고 'Z'를 구현하는 것을 잊었습니까? 아니면 해킹없이 "+0000"으로 유효한 현지 시간 오프셋을 바꾸는 방법을 놓치고 있습니까?

코드 예 :

// 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);

아마도 "K"형식 지정자가 유용 할 것입니다. 이것은 대문자 "Z"의 사용을 언급하는 유일한 것입니다.

"Z"는 DateTimes의 고유 한 경우입니다. 리터럴 "Z"는 실제로 UTC 시간에 대한 ISO 8601 datetime 표준의 일부입니다. "Z"(Zulu)가 시간 끝에 붙어 있으면 시간이 UTC임을 나타내므로 실제로 Z는 시간의 일부입니다. .NET의 날짜 형식 라이브러리에 몇 가지 문제가 발생할 수 있습니다. 형식 지정자가 아니라 실제로는 리터럴이기 때문입니다.


DateTime을 사용하면 변수 안에 날짜와 시간을 저장할 수 있습니다.

날짜는 현지 시간 또는 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

그렇다면 시간대를 포함하여 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 및 dt2에는 날짜 및 시간 정보 만 포함됩니다. dt1 및 dt2에는 시간대 오프셋이 포함되지 않습니다.

그렇다면 "+2"가 dt1 및 dt2 변수에 포함되지 않은 경우 어디에서 왔습니까?

기계 시계 설정에서 나옵니다.

컴파일러는 'zzz'형식을 사용할 때 "DATE ​​+ TIME"(dt1 및 dt2에 저장 됨) + "TIMEZONE OFFSET"(이는 dt1 및 dt2에 포함되지 않음 )을 결합한 문자열을 작성 한다고 알려줍니다. DateTyme 유형) 이며 코드를 실행하는 서버 시스템의 오프셋을 사용합니다.

컴파일러는 "경고 : 코드의 출력은 기계 클럭 오프셋에 따라 다릅니다."라고 말합니다.

런던 (+1 UTC)에 위치한 서버에서이 코드를 실행하면 결과가 완전히 달라집니다. " +2 " 대신 " +1 "을 씁니다.

...
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

올바른 해결책은 DateTime 대신 DateTimeOffset 데이터 유형을 사용하는 것입니다. 2008 버전부터 SQL Server 및 3.5 버전부터 .Net 프레임 워크에서 사용할 수 있습니다.


문자열을 통한 날짜 왕복은 항상 고통 스러웠지만 '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 );

MSDN 의이 페이지 는 'Z'를 사용하는 문자열을 제외하고 표준 DateTime 형식 문자열을 나열합니다.

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:

// yyyy'-'MM'-'dd HH':'mm':'ss'Z'
DateTime utcTime = DateTime.Parse("2009-05-07 08:17:25Z");

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.

if you need to get the CLIENT Offset, I recommend that you check a little trick that 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.


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 :(

I'm sorry, but am I missing something?


Reading carefully the MSDN on Custom Date and Time Format Strings

there is no support for uppercase 'Z'.


I was dealing with DateTimeOffset and unfortunately the "o" prints out "+0000" not "Z".

So I ended up with:

dateTimeOffset.UtcDateTime.ToString("o")

ReferenceURL : https://stackoverflow.com/questions/833102/wheres-the-datetime-z-format-specifier

반응형