Преобразовать 7-значную дату по юлианскому календарю в DateTime в SQL?

Я видел множество примеров в Интернете и несколько здесь, на SO. Однако ни один из них не работает с моими данными. Вот несколько дат по юлианскому календарю с их известными преобразованными значениями.

JUL | DateTime
2454522 | 2008-02-25 00:00:00.000
2454571 | 2008-04-14 00:00:00.000
2455713 | 2011-05-31 00:00:00.000

Я пробовал это, что не работает:

DECLARE @JD int = 2454522
SELECT DATEADD(YEAR, @JD / 1000 - 1900, @JD % 1000 - 1)

Это дает мне это: 2455-06-06 00:00:00.000, что явно неверно. Что мне здесь не хватает? Заранее спасибо.


person BBauer42    schedule 29.04.2013    source источник
comment
Для какой СУБД это?   -  person David Aldridge    schedule 29.04.2013
comment
Преобразование между юлианской датой и YMD не так уж и тривиально. См. en.wikipedia.org/wiki/Julian_day для объяснения и алгоритма вычисления единицы из другой.   -  person sizzzzlerz    schedule 29.04.2013
comment
@DavidAldridge: Учитывая использование @ для обозначения имени переменной, это выглядит как SQLServer.   -  person    schedule 29.04.2013
comment
@David Извините, за SQL   -  person BBauer42    schedule 29.04.2013
comment
BBauer42: SQL (сокращение от языка структурированных запросов) — это язык, используемый для управления данными, хранящимися в системе управления реляционными базами данных (сокращенно RDBMS). Существует множество РСУБД (таких как Oracle, MySQL, Microsoft SQLServer, PostgreSQL и т. д.), каждая из которых имеет свою собственную версию SQL. Дэвид спрашивал, какой из них используется — это важно, потому что каждый диалект SQL имеет свой собственный способ работы с датами, отличный от других. Я пришел к выводу, что вы используете SQLServer. Можете ли вы подтвердить, верно ли это, и если нет, то какую версию SQL вы используете?   -  person    schedule 30.04.2013
comment
Прошу прощения, SQL Server 2012.   -  person BBauer42    schedule 30.04.2013


Ответы (3)


Один подход, который должен работать в SQLServer:

select @jd, dateadd(d,@jd - 2440588,'1970-01-01')

SQLFiddle здесь.

person Community    schedule 29.04.2013

Пока ваша СУБД поддерживает некоторый набор скалярных функций, способных вычислять количество дней между двумя датами и добавлять количество дней к заданной дате, все, что вам нужно сделать, это вычислить какое-то значение нормализации для юлианских дат и сделать некоторые довольно простые математические даты.

В среде DB/2 соответствующими функциями являются: ДНИ и ДАТА. начните с некоторой базовой даты, которую вы знаете по юлианскому календарю. Например, юлианская дата для 01.01.2000: 2451545.

Затем используйте скалярные функции DAYS/DATE для вычисления целочисленного значения той же даты. Запрос для этого в DB/2:

select days(date('2000-01-01'))
from sysibm.sysdummy1
;

Результат этого запроса: 730120

Используйте эти два значения, чтобы вычислить коэффициент нормализации для юлианских дат: 2451545 - 730120 = 1721425

Теперь вы можете вычислить григорианскую дату из юлианской даты следующим образом:

select date(juliandate - 1721425)
from sysibm.sysdummy1
;

Используя примеры из вашего вопроса:

select date(2454522 - 1721425),
       date(2454571 - 1721425),
       date(2455713 - 1721425)
from sysibm.sysdummy1
;

Возвращает следующие даты: 25 февраля 2008 г. 14 апреля 2008 г. 31 мая 2011 г.

Ваша СУБД может не поддерживать определенные скалярные функции, используемые в приведенном выше примере, однако большинство из них будут поддерживать какой-либо механизм добавления некоторого количества дней к дате по григорианскому календарю и определения количества дней между двумя датами. Вы должны быть в состоянии разработать некоторую работоспособную формулу, используя эти функции и коэффициент нормализации для юлианских дат, как показано выше.

person NealB    schedule 29.04.2013

Это значения астрономической даты по юлианскому календарю, только целые дни. Быстрое и грязное преобразование в datetime в SQL Server (которое, конечно, не может быть ниже 1753 года) будет таким:

DECLARE @jd as int = 2454522
SELECT CAST(@jd - 2415021 as datetime)

2008-02-25 00:00:00.000

2415021 происходит от следующего:

SELECT CAST(0 as datetime)

1900-01-01 00:00:00.000

И согласно преобразователю юлианской даты, 01 января 1900 г. н.э. составляет 2415020,5. Добавьте к этому 0,5, потому что астрономическая дата по юлианскому календарю начинается с полудня, а мы имеем дело только с целыми днями. .

Если вам не нравится грязное, попробуйте это:

DECLARE @jd as int = 2454522
SELECT DATEADD(DAY, @jd - 2415021, '1900-01-01')

2008-02-25 00:00:00.000
person Alex Volkov    schedule 15.10.2013