Расчет DATEADD

Как происходит расчет для части даты MONTH в DATEADD()

Добавить месяц

SELECT '2012-01-29' AS [Date], CAST(DATEADD(MONTH, 1, '2012-01-31') AS DATE) AS NextDate
UNION
SELECT '2012-01-31' AS [Date], CAST(DATEADD(MONTH, 1, '2012-01-31') AS DATE) AS NextDate
UNION
SELECT '2013-01-31' AS [Date], CAST(DATEADD(MONTH, 1, '2013-01-31') AS DATE) AS NextDate

Результат

введите здесь описание изображения

Вычесть месяц

SELECT '2012-02-29' AS [Date], CAST(DATEADD(MONTH, -1, '2012-02-29') AS DATE) AS PrevDate
UNION
SELECT '2012-03-01' AS [Date], CAST(DATEADD(MONTH, -1, '2012-03-01') AS DATE) AS PrevDate

Результат

введите здесь описание изображения

Когда я добавляю месяц к датам 29,30,31 of Jan'2012, я получаю тот же результат, что и February 29. Для вычитания для даты 29 Feb'2012 отображается 29 Jan'2012. Невозможно получить даты 30 & 31 of Jan'2012.

Я хочу знать краткое объяснение.


person Jesuraja    schedule 10.07.2014    source источник


Ответы (1)


Поведение явно задокументировано в документации для DATEADD:

DATEADD (datepart , number , date )

...

Если datepart равно month, а в месяце date больше дней, чем в возвращаемом месяце, а date день не существует в месяце возврата возвращается последний день месяца возврата. Например, в сентябре 30 дней; поэтому два следующих оператора возвращают 2006-09-30 00:00:00.000:

SELECT DATEADD(month, 1, '2006-08-30');

SELECT DATEADD(month, 1, '2006-08-31');

Что касается того, почему у него такое поведение, все сводится к тому факту, что месяцы переменной длины означают, что вы должны применять некоторую форму компромисса при выполнении математических операций с датами, и не существует ни одного «правильного» ответа. Считаете ли вы 31 января «последним днем ​​января» или «30 дней после 1 января». И то, и другое — правильный способ думать о 31-м. Но если вы измените January на February, вы получите две разные даты: 28 или 29 февраля для «последнего дня февраля» или 2 или 3 марта для «30 дней после 1-го дня февраля».

Но функции должны возвращать только одно значение.

Я не говорю, что SQL Server применяет любую из приведенных выше интерпретаций. Однако он гарантирует, что если вы добавите, скажем, 1 месяц к определенной дате, вы можете быть уверены, что полученная дата выпадает на следующий месяц.

person Damien_The_Unbeliever    schedule 10.07.2014