Подтвердить что ты не робот

Где спецификатор формата DateTime 'Z'?

[ Обновление: спецификаторы форматирования - это не то же самое, что и строки формата; спецификатор формата является частью строки пользовательского формата, где строка формата является "запасом" и не предоставляет настройки. Моя проблема связана с спецификаторами, а не форматами]

Я пытаюсь выполнить конверсии DateTime roundtrip с строкой формата, которая использует спецификатор формата zzz, который, как я знаю, привязан к локальному времени. Итак, если я попытаюсь обойти поездку с датой даты UTC, она выдает исключение DateTimeInvalidLocalFormat, которое должно быть с этим текстом:

A UTC DateTime преобразуется в текст в формате, который является правильным только для локальных времен. Это может произойти при вызове DateTime.ToString с использованием спецификатора формата "z", который будет включать в себя локальное смещение часового пояса на выходе. В этом случае либо используйте спецификатор формата "Z" , который обозначает время UTC, либо используйте строку формата "o", которая является рекомендуемым способом сохранения DateTime в тексте. Это также может произойти при передаче DateTime для сериализации XmlConvert или DataSet. Если вы используете XmlConvert.ToString, перейдите в XmlDateTimeSerializationMode.RoundtripKind, чтобы сериализовать правильно. Если вы используете DataSet, установите DateTimeMode в объекте DataColumn в DataSetDateTime.Utc.

Основываясь на этом предположении, все, что мне нужно сделать, чтобы заставить мой код работать, это заменить "zzz" на "ZZZ", чтобы я мог стоять в формате UTC. Проблема заключается в том, что "Z" нигде не встречается в документации, и любая комбинация формата "Z" , которую я пытаюсь, то есть "Z" , "ZZ", "ZZZ", всегда просто преобразует экземпляр DateTime с теми, которые обрабатываются Z как литералы.

Кто-то забыл реализовать "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);
4b9b3361

Ответ 1

Может быть, спецификатор формата "K" будет полезен. Это единственный, который, по-видимому, упоминает использование капитала "Z".

"Z" - это уникальный случай для DateTimes. Литерал "Z" на самом деле является частью стандартного стандарта ISO 8601 для времени UTC. Когда "Z" (Zulu) привязано к концу времени, это указывает, что это время UTC, так что буквальный Z является частью времени. Вероятно, это создает несколько проблем для библиотеки формата даты в .NET, поскольку она фактически является литералом, а не спецификатором формата.

Ответ 2

Когда вы используете 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

Правильное решение - использовать тип данных DateTimeOffset вместо DateTime. Он доступен в sql Server начиная с версии 2008 и в.Net-среде, начиная с версии 3.5

Ответ 3

Даты закрытия раунда по строкам всегда были больны... но документы указывают, что спецификатор "o" - это тот, который используется для круглого отключения, которое фиксирует состояние UTC. При анализе результат обычно будет иметь вид == Utc, если оригинал был 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 );

Ответ 4

Эта страница в MSDN перечисляет стандартные строки формата DateTime, не содержащие строки с использованием "Z".

Обновление: вам нужно убедиться, что остальная строка даты также соответствует правильному шаблону (вы не представили пример того, что вы его отправляете, поэтому трудно сказать, делали вы это или нет). Для работы формата UTC он должен выглядеть следующим образом:

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

Ответ 5

Label1.Text = dt.ToString("dd MMM yyyy | hh:mm | ff | zzz | zz | z");

выведет:

07 Mai 2009 | 08:16 | 13 | +02:00 | +02 | +2

Я в Дании, мой офсет с GMT +2 часа, ведьма верна.

если вам нужно получить СООБЩЕНИЕ КЛИЕНТА, я рекомендую вам проверить маленький трюк, который я сделал, Страница находится на сервере в Великобритании, где GMT ​​+ 00: 00, и, как вы можете видеть, вы получите местное GMT ​​Offset.


Относительно вашего комментария, я сделал:

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

и я получаю следующее:

07 Mai 2009 | 08:24 | 14 | +02:00 | +02 | +2
07 Mai 2009 | 06:24 | 14 | ZZZ | ZZ | Z 

Я не получаю исключение, просто... он ничего не делает с капиталом Z: (

Извините, но я что-то упускаю?


Внимательно прочитайте MSDN на Пользовательские строки формата даты и времени

нет поддержки верхнего регистра "Z".

Ответ 6

Я имел дело с DateTimeOffset и, к сожалению, "o" печатает "+0000", а не "Z".

Итак, я закончил с:

dateTimeOffset.UtcDateTime.ToString("o")