Я испытываю ту же проблему в течение последних нескольких дней.
Я использую Angular 7 для внешнего интерфейса и .Net Core Web API для внутреннего интерфейса.
Веб-API возвращает дату и время в полезной нагрузке JSON клиенту в виде строк в следующем формате:
2020-04-23T01:00:00
Объектная модель TypeScript/JavaScript сохраняет тип данных строки даты как строковый тип.
Когда bsDatepicker и timepicker подключены в соответствии с приведенным ниже примером кода (в данном случае с использованием двухсторонней привязки модели), тип строки даты в модели изменяется со строкового типа на тип даты JavaScript.
<input name="AppliesEndDate{{index}}" type="text" class="form-control form-control-sm" bsDatepicker [(ngModel)]="costCentre.appliesEndDate" [disabled]="costCentre.totalActiveAssignments!==0" />
<timepicker [(ngModel)]="costCentre.appliesEndDate" [showMeridian]="showMeridian" [disabled]="costCentre.totalActiveAssignments!==0" [minuteStep]="1"></timepicker>
Когда модель отправляется обратно на сервер веб-API через HTTP POST или PUT, тип данных Date в объектной модели сериализуется обратно в строку в виде даты в формате UTC, что обозначается суффиксом Z:
2020-04-23T00:00:00.000Z
Из этого можно сделать вывод, что это происходит на стороне клиента и не имеет прямого отношения к Angular. Возможно, это больше связано с тем, как JavaScript преобразует типы Date в строки.
Возьмите эти примеры. Я намеренно выбрал две даты. Один вне британского летнего времени (GMT+0000), а другой внутри британского летнего времени (GMT+0100).
var date1 = new Date('2019-02-01T14:14:00');
var date2 = new Date('2019-05-01T14:14:00');
Пт, 01 февраля 2019 г., 14:14:00 GMT+0000 (время по Гринвичу)
Ср, 01 мая 2019 г., 14:14:00 GMT+0100 (британское летнее время)
Выполнение приведенных ниже операторов для преобразования в строку ISO:
console.log('toISOString ' + date1.toISOString());
console.log('toISOString ' + date2.toISOString());
Дает следующие результаты:
toISOString 2019-02-01T14:14:00.000Z
toISOString 2019-05-01T13:14:00.000Z
Обе даты конвертируются в формат UTC. Обратите внимание, что во втором примере время 13:14, а не 14:14. На самом деле это правильно, так как 05.01.2019 находится внутри BST, то есть по Гринвичу + 0100. Таким образом, истинное UTC на самом деле 13:14.
Это было бы верно для любого другого региона/часового пояса. Дата и время UTC будут рассчитываться на основе локали/региона клиента.
Под прикрытием я считаю, что это то, что происходит на стороне клиента с Angular при отправке модели обратно в полезную нагрузку на сервер. Это просто вызов toISOString.
Вы также получите те же результаты с JSON.stringify, который, как я полагаю, вызывает toISOString под прикрытием.
console.log(JSON.stringify(date1));
console.log(JSON.stringify(date2));
Попробуйте запустить некоторые из этих команд в Chrome Sources › Snippets или другом блокноте JavaScript.
var date1 = new Date('2019-02-01T14:14:00');
var date2 = new Date('2019-05-01T14:14:00');
console.log(date1);
console.log(date2);
console.log(JSON.stringify(date1));
console.log(JSON.stringify(date2));
console.log('toISOString ' + date1.toISOString());
console.log('toISOString ' + date2.toISOString());
console.log('toGMTString ' + date1.toGMTString());
console.log('toGMTString ' + date2.toGMTString());
console.log('toLocaleString ' + date1.toLocaleString());
console.log('toLocaleString ' + date2.toLocaleString());
console.log('toUTCString ' + date1.toUTCString());
console.log('toUTCString ' + date2.toUTCString());
console.log(date1.getTimezoneOffset());
console.log(date2.getTimezoneOffset());
Итак, в заключение мы получаем дату и время UTC от клиента.
Это, безусловно, хорошо и делает локаль/регион даты и времени независимым.
Вооружившись этим пониманием, есть обходные пути, если вы хотите хранить локальные даты и время в своей базе данных, а не даты и времени UTC.
Приведенное выше предложение кода на стороне клиента, безусловно, исправляет смещение, но учтите, что данные все равно будут сериализованы обратно клиенту в виде строки даты UTC. Удалив смещение таким образом, вы фактически нарушили дату UTC. На сервере веб-API по-прежнему будет получать суффикс Z, и это будет рассматриваться как дата в формате UTC. Таким образом, вы на самом деле скорректировали смещение даты, но не контекст формата UTC.
fixDate(d: Date): Date {
d.setHours(d.getHours() - d.getTimezoneOffset() / 60);
return d;
}
Однако, если вы должны были отправить дату обратно в виде строки (преобразовать ее самостоятельно и удалить суффикс Z) обратно в этот формат:
2020-04-23T01:00:00
Тогда вы не будете подразумевать, что дата была датой UTC.
Принимая во внимание все вышесказанное, я считаю (после нескольких дней изучения этого вопроса) то, что лучше оставить клиенту сериализацию типов Date как UTC. Примите тот факт, что именно так это и работает, и что всегда возвращать строковые даты в формате UTC — это хорошо с точки зрения согласованности.
С точки зрения серверной части (веб-API в моем случае) дата может быть получена как дата UTC и либо сохранена в вашей базе данных/хранилище данных как дата UTC, ИЛИ вы можете преобразовать ее на стороне сервера в любую локаль/регион по вашему выбору. Помните, что UTC не зависит от региона, что хорошо для глобальных приложений.
В моем случае я решил преобразовать входящие даты и время UTC в локальные даты и времени, используя следующий фрагмент кода перед сохранением в нашей базе данных.
o.AppliesStartDate.ToLocalTime();
Я надеюсь, что это поможет кому-то и, надеюсь, прояснит, как все работает. Два дня назад я вообще этого не понял... но теперь это имеет смысл.
Вы также можете делать такие вещи, как в веб-API С#:
TimeZoneInfo ist = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time");
TimeZoneInfo gmt = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
var a1 = new DateTime(2019, 5, 30, 12, 30, 30, DateTimeKind.Utc);
Console.WriteLine(TimeZoneInfo.ConvertTimeFromUtc(a1, gmt));
Console.WriteLine(TimeZoneInfo.ConvertTimeFromUtc(a1, ist ));
Это может дополнительно прояснить, что даты принимаются в веб-API как типы дат в формате UTC. Если вы проверите свойство kind на стороне веб-API десериализованной структуры даты и времени, вы увидите UTC.
Я надеюсь, это поможет вам.
person
Robin Webb
schedule
02.02.2019