Удаление смещения часового пояса из DateTimeOffset. Удаление Смещение часового пояса От DateTimeOffset Нулевое смещение дат sql server

DateTimeOffset testDateAndTime = new DateTimeOffset(2008, 5, 1, 8, 6, 32, new TimeSpan(1, 0, 0)); //CLEAN TIME AND DATE testDateAndTime = testDateAndTime.DateTime.Date; var datesTableEntry = db.DatesTable.First(dt => dt.Id == someTestId); datesTableEntry.test= testDateAndTime; db.SaveChangesAsync();

РЕЗУЛЬТАТ В БАЗА ДАННЫХ: 2008-05-01 00:00:00.0000000 -04:00

Как включить -4:00 в +00:00 (из кода перед сохранением)?

Я пытался:

Public Task SetTimeZoneOffsetToZero(DateTimeOffset dateTimeOffSetObj) { TimeSpan zeroOffsetTimeSpan = new TimeSpan(0, 0, 0, 0, 0); return dateTimeOffSetObj.ToOffset(zeroOffsetTimeSpan); }

Он ничего не делает.

Конечная цель - просто иметь дату без смещения времени или часового пояса. Я НЕ хочу преобразовывать время в другой часовой пояс (т. 00:00:00.0000000 Я не хочу, чтобы он вычитал 4 часа из 00:00:00.0000000 времени и 00:00:00.0000000 смещение установленного времени на +00:00 , я просто хочу, чтобы он установил смещение к +00:00). Я хочу текущую дату с нулевым смещением.

Редактировать:

Вот что можно предложить в другом месте:

DateTimeOffset testDateAndTime = new DateTimeOffset(2008, 5, 1, 8, 6, 32, new TimeSpan(1, 0, 0)); testDateAndTime = testDateAndTime.DateTime.Date; //Zero out time portion testDateAndTime = DateTime.SpecifyKind(testDateAndTime.Date, DateTimeKind.Utc); //"Zero out" offset portion

Я был уверен, что SpecifyKind будет SpecifyKind моей dateTimeOffset, например, измените BOTH время и смещение часового пояса, но при тестировании, похоже, просто изменит смещение часового пояса, что и есть то, что я хочу. Есть ли проблема с этим?

1 ответ

Проблема не имеет ничего общего с базой данных. Если вы установили точку останова или зарегистрировали выход где-нибудь, вы должны увидеть, как смещение будет привязано вскоре после этого кода:

TestDateAndTime = testDateAndTime.DateTime.Date;

Позвольте сломать это:

  • Вы начали с значения DateTimeOffset 2008-05-01T08:06:32+01:00
  • Затем вы вызывали.DateTime , в результате чего значение DateTime 2008-05-01T08:06:32 с DateTimeKind.Unspecified .
  • Затем вы вызывали.Date , что привело к значению DateTime 2008-05-01T00:00:00 с DateTimeKind.Unspecified .
  • Вы возвращаете результат в testDateAndTime , который имеет тип DateTimeOffset . Это вызывает неявное преобразование из DateTime в DateTimeOffset которое применяет локальный часовой пояс . В вашем случае представляется, что смещение для этого значения в вашем локальном часовом поясе - -04:00 , поэтому итоговое значение - это DateTimeOffset 2008-05-01T00:00:00-04:00 , как вы описали,

Ты сказал:

Конечная цель - просто иметь дату без смещения времени или часового пояса.

Ну, в настоящее время нет собственного типа данных С#, который является просто датой без времени. Существует чистый тип Date в пакете System.Time в corefxlab , но это не совсем готово для типичного производственного приложения. Там LocalDate в библиотеке времени Noda, которую вы можете использовать сегодня, но вам все равно придется преобразовать обратно в родной тип перед сохранением в базе данных. Таким образом, в то же время, самое лучшее, что вы можете сделать, это:

  • Измените свой SQL Server на использование типа date в этом поле.
  • В вашем коде.NET используйте DateTime со временем 00:00:00 и DateTimeKind.Unspecified . Вы должны помнить, чтобы игнорировать временную часть (так как есть действительно даты без локальной полуночи в определенных часовых поясах).
  • Измените test оповещение как DateTime , а не DateTimeOffset .

В общем случае, в то время как DateTimeOffset подходит для большого количества сценариев (например, событий timestamping), он не подходит для значений только даты.

Я хочу текущую дату с нулевым смещением.

Если вы действительно хотите, чтобы это как DateTimeOffset , вы бы сделали:

TestDateAndTime = new DateTimeOffset(testDateAndTime.Date, TimeSpan.Zero);

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

Что касается дополнительного вопроса, заданного в вашем редактировании - указание DateTimeKind.Utc изменяет поведение неявного приведения. Вместо использования локального часового пояса используется время UTC, которое всегда имеет смещение нуля. Результат такой же, как и более явный вид, который я дал выше. Я по-прежнему рекомендую против этого по тем же причинам.

Рассмотрим пример начала с 2016-12-31T22:00:00-04:00 . По вашему подходу вы должны сохранить в базе данных 2016-12-31T00:00:00+00:00 . Однако это два разных момента времени. Первый, нормализованный к UTC, будет 2017-01-01T02:00:00+00:00 , а второй, преобразованный в другой часовой пояс, будет 2016-12-30T20:00:00-04:00 . Обратите внимание на изменение дат в конверсии. Вероятно, это не то поведение, которое вы хотели бы использовать в своем приложении.

Вариант гуманный ([необходимо зарегистрироваться для просмотра ссылки]).

Суть проблемы в чем.. Если Вы случайно развернули базу на сервере SQL со «смещением даты» 0 то возникла проблема, когда в базе встречается реквизит с типом ВРЕМЯ т.е.в этот реквизит ставится 01.01.0001 10:30:00 или дата записалась пустой 01.01.0001 00:00:00. При записи такого реквизита не происходит его запись.
В интернете предлагают создать новую базу со смещением 2000.
Но новую базу создавать не очень хотелось. И менять у всех пользователях путь к базе.
Тогда я пошел по пути, а где ж хранится это значение в SQL-е. Нашел и поменял на 2000 и все стало ок..
А теперь по шагово, где поменять.

Выгнать всех пользователей.

ВНИМАНИЕ!!!

1. Сначала сделайте резервную копию средствами 1С т.е. выгрузите ее в *.dt
Это нужно делать до того как поменяете «смещение»
Если этого не сделать то во всей вашей базе спр., док, и т.д.
где есть есть реквизит дата будет стоять допустим 02.10.0009
ЧТО НЕ ДОПУСТИМО….
Итак Вы сделали выгрузку в *.dt

2. Заходим в SQL Server Management Studio
Находим Вашу базу в списку нажимаем плюсик.
Находи там папочку «Таблицы» и раскрываем ее.
Откроется куча таблиц, идем в самый низ, находим таблицу
_YearOffset, становимся на нее и правой клавишей выбираем пункт «Открыть таблицу» см. рис.1
Меняем значение 0 на 2000
Закрываем SQL Server Management Studio

3. Заходим в конфигуратор и загружаем ранее сохраненную базу.

Если это не сделать, то все даты будут с годом 0009.
После того как база загрузилась… Можно зайти в 1С и удостоверится что даты нормальные.
Результат мы поменяли «смещение дата с 0 на 2000»

Иногда бывает так, что этот вариант использовать не получается по тем или иным причинам. Тогда есть более хардкорный вариант ([необходимо зарегистрироваться для просмотра ссылки]):

Declare TablesAndFields cursor for

SELECT objects.name as Tablename, columns.name as columnname
FROM dbo.sysobjects as objects
left join dbo.syscolumns as columns on objects.id = columns.id
where objects.xtype = "U" and columns.xtype = 61

open TablesAndFields

WHILE @@FETCH_STATUS = 0
BEGIN Exec ("update " + @TableName + "
set " + @ColumnName + " = ""2000- 01- 01 00:00:00" "
where " + @ColumnName + " > ""3999- 12- 31 23:59:59" "")

This is executed as long as the previous fetch succeeds.
FETCH NEXT FROM TablesAndFields into @TableName, @ColumnName
END

close TablesAndFields
deallocate TablesAndFields
go

Перед любыми манипуляциями не забывайте делать копии баз данных!

Проблема не имеет ничего общего с базой данных. Если установить точку останова или войти выход где-то, вы должны быть в состоянии видеть смещение быть пристегивается вскоре после этого кода:

TestDateAndTime = testDateAndTime.DateTime.Date;

Давайте сломаем это вниз:

  • Вы начали с DateTimeOffset значение 2008-05-01T08:06:32+01:00
  • Затем вы назвали.DateTime , что привело к значению DateTime 2008-05-01T08:06:32 с DateTimeKind.Unspecified .
  • Затем вы позвонили.Date , что привело к значению DateTime 2008-05-01T00:00:00 с DateTimeKind.Unspecified .
  • Вы назначаете результат на testDateAndTime , который имеет тип DateTimeOffset . Это вызывает неявный литой от DateTime до DateTimeOffset - , который применяет местный часовой пояс . В вашем случае представляется, что смещение для этого значения в вашем местном часовом поясе составляет -04:00 , поэтому полученное значение равно DateTimeOffset из 2008-05-01T00:00:00-04:00 , как вы описали.

Вы сказали:

Конечной целью является просто иметь дату без времени или часового пояса смещения.

Ну, есть в настоящее время не родной C# типа данных, который просто дата без времени.Существует чистый Date тип в System.Time пакет в corefxlab , но это еще не совсем готово для типичного производственного приложения. Там LocalDate в библиотеке Noda Time , которую вы можете использовать сегодня, но перед сохранением в базу данных вам все равно придется преобразовать обратно в собственный тип. Таким образом, в то же время, самое лучшее, что вы можете сделать:

  • Измените свой SQL Server на использование типа date в поле.
  • В вашем коде.NET используйте DateTime со временем 00:00:00 и DateTimeKind.Unspecified . Вы должны помнить, чтобы игнорировать временную часть (так как есть действительно даты без локальной полуночи в определенных часовых поясах).
  • Изменить test опоры, чтобы быть DateTime , а не DateTimeOffset .

В целом, в то время как DateTimeOffset подходит большое количество сценариев (например, меток времени событий), она не подходит хорошо для даты только значения.

Я хочу текущую дату с нулевым смещением.

Если вы действительно хотите это как DateTimeOffset , вы могли бы сделать:

TestDateAndTime = new DateTimeOffset(testDateAndTime.Date, TimeSpan.Zero);

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

Относительно дополнительного вопроса, заданного в вашем правлении. Указание DateTimeKind.Utc изменяет поведение неявного приведения. Вместо использования местного часового пояса используется время UTC, которое всегда имеет смещение нуля. Результат такой же, как и более явный вид, который я дал выше. Я по-прежнему рекомендую против этого по тем же причинам.

Рассмотрите пример, начинающийся с 2016-12-31T22:00:00-04:00 . По вашему подходу вы должны сохранить в базе данных 2016-12-31T00:00:00+00:00 . Однако это два разных момента времени. Первый, нормализованный к UTC, будет 2017-01-01T02:00:00+00:00 , а второй, преобразованный в другой часовой пояс, будет 2016-12-30T20:00:00-04:00 . Обратите внимание на изменение дат в конверсии. Вероятно, это не то поведение, которое вы хотели бы использовать в своем приложении.

Публикации по теме