2009-09-06 3 views
8

SQLite docs указывает, что предпочтительным форматом для хранения значений даты и времени в БД является использование Julian Day (с использованием встроенных функций).Должен ли я хранить данные DateTime как julianday в SQLite?

Однако все фреймворки, которые я видел в python (pysqlite, SQLAlchemy), хранят значения datetime.datetime как строки в формате ISO. Почему они это делают?

Обычно я пытаюсь адаптировать рамки для хранения datetime как julianday, и это довольно болезненно. Я начал сомневаться, что стоит усилий.

Пожалуйста, поделитесь своим опытом в этом поле со мной. Имеет ли смысл придерживаться julianday?

ответ

5

Хранить в двух вариантах. Рамки могут быть установлены по-своему, и если ваш ожидает найти необработанный столбец с форматированной по ISO строкой, то это, вероятно, больше боль, чтобы обойти, чем это стоит.

Конфликт в наличии двух столбцов - это согласованность данных, но sqlite должен иметь все необходимое для его работы. Версия 3.3 поддерживает ограничения проверки и триггеры. Читайте дальше: date and time functions. Вы должны быть в состоянии делать то, что вам нужно полностью в базе данных.

CREATE TABLE Table1 (jd, isotime); 

CREATE TRIGGER trigger_name_1 AFTER INSERT ON Table1 
BEGIN 
    UPDATE Table1 SET jd = julianday(isotime) WHERE rowid = last_insert_rowid(); 
END; 

CREATE TRIGGER trigger_name_2 AFTER UPDATE OF isotime ON Table1 
BEGIN 
    UPDATE Table1 SET jd = julianday(isotime) WHERE rowid = old.rowid; 
END; 

И если вы не можете делать то, что вам нужно в БД вы можете написать расширение C для выполнения нужных функций. Таким образом, вам не нужно прикасаться к каркасу, кроме как загружать расширение.

+0

Спасибо за это предложение! Это отличная идея, и она решает все мои проблемы с этой проблемой. –

+1

Зачем вам _want_ хранить его в обе стороны? Единственное реальное преимущество хранения юлианских дней над строками в формате ISO - это пространство для хранения. Если ваша структура ожидает строку в формате ISO, просто используйте ее. Все функции [datetime] SQLite (http://www.sqlite.org/lang_datefunc.html) может обрабатывать строки ISO так же хорошо, как и юлианские дни. – Martijn

6

Julian Day удобен для расчетов всех видов расчетов, но он может хранить время часть прилично (с точными часами, минутами и секундами). Раньше я использовал оба поля Julian Day (для дат) и секунды-из-за-Epoch (для datetime экземпляров), но только тогда, когда у меня были особые потребности в вычислении (дат и соответственно времени). Простота дат и дат в формате ISO, как мне кажется, должна сделать их предпочтительным выбором, скажем, около 97% времени.

+1

Таким образом, я буду придерживаться стандартных фреймов, пока у меня нет явных причин не делать этого. Спасибо! –

+0

Не могли бы вы немного рассказать о том, почему точность julianday в течение нескольких часов, минут и секунд недостаточно хороша? –

+0

@Slava, подумайте о представлении «1 секунда»: это 1/86400.'th дня, который НЕ МОЖЕТ быть точно представлен как фракционная часть float с двойной точностью, поскольку представление последнего находится в двоичной форме, а 86400 не является мощность двух. –

0

Потому что 2010-06-22 00:45:56 намного проще для чтения человеком, чем 2455369.5318981484. Текстовые даты отлично подходят для выполнения специальных запросов в SQLiteSpy или SQLite Manager.

Основной недостаток, конечно, является то, что текстовые даты требуют 19 байт вместо 8.

1

Но, как правило, человек не читает непосредственно из базы данных. Дробное время в юлианский день легко преобразуется в человека, читаемого (например)

void hour_time(GenericDate *ConvertObject) 
{ 
    double frac_time = ConvertObject->jd; 
    double hour   = (24.0*(frac_time - (int)frac_time)); 
    double minute  = 60.0*(hour - (int)hour); 
    double second  = 60.0*(minute - (int)minute); 
    double microsecond = 1000000.0*(second - (int)second); 

    ConvertObject->hour   = hour; 
    ConvertObject->minute  = minute; 
    ConvertObject->second  = second; 
    ConvertObject->microsecond = microsecond; 

};