Как значения DATETIME работают в SQLite?

111

Я создаю приложения для Android, и мне нужно сохранить дату / время создания записи. Однако в документации по SQLite говорится: «SQLite не имеет класса хранения, выделенного для хранения дат и / или времени», и «способен хранить даты и время как значения TEXT, REAL или INTEGER».

Есть ли техническая причина использовать один тип вместо другого? И может ли один столбец хранить даты в любом из трех форматов от строки к строке?

Мне нужно будет сравнить даты позже. Например, в своих приложениях я буду показывать все записи, созданные с даты A до даты B. Меня беспокоит, что отсутствие истинного столбца DATETIME может затруднить сравнение.

Хайрил Ушан
источник

Ответы:

84

SQlite не имеет определенного типа datetime. Вы можете использовать TEXT, REALили INTEGERтип, в зависимости от того соответствует вашим потребностям.

Прямо из DOCS

SQLite не имеет класса хранения, выделенного для хранения дат и / или времени. Вместо этого встроенные функции даты и времени SQLite могут сохранять дату и время как значения TEXT, REAL или INTEGER:

  • ТЕКСТ в виде строк ISO8601 («ГГГГ-ММ-ДД ЧЧ: ММ: СС.ССС»).
  • НАСТОЯЩИЙ по юлианскому календарю - количество дней, прошедших с полудня по Гринвичу 24 ноября 4714 г. до н.э., согласно пролептическому григорианскому календарю.
  • INTEGER как время Unix, количество секунд с 1970-01-01 00:00:00 UTC.

Приложения могут сохранять дату и время в любом из этих форматов и свободно конвертировать между форматами, используя встроенные функции даты и времени.

Здесь можно найти встроенные функции даты и времени SQLite .

neo108
источник
11
Важно отметить: все методы хранения дат используют форматы, которые можно сравнивать с помощью стандартных операторов =, <,> и BETWEEN.
Ларри Ластиг,
2
«SQLite не имеет класса хранения, выделенного для хранения дат и / или времени» - за исключением того, что у него есть типы DATE и DATETIME, которые никогда не упоминаются в документации
Slabko
12
@Slabko Это не так. SQLite допускает все (включая DATETIME) в качестве объявленного типа столбца. Исходя из этого, он придает этому столбцу сходство с классом хранения (в документации даже есть пример того, как это работает для DATETIME). Это сходство больше похоже на подсказку, поскольку каждая запись в столбце может иметь другой класс хранения. Класс хранения по-прежнему на ступень слабее, чем тип, и может поддерживаться несколькими типами. Так что да, вы можете использовать DATETIME. Нет, на самом деле он не поддерживает его как тип или класс хранения. Да, в документации действительно есть слово «DATETIME».
Джаспер
20

SQLite не имеет класса хранения, выделенного для хранения дат и / или времени. Вместо этого встроенные функции даты и времени SQLite могут сохранять дату и время как значения TEXT, REAL или INTEGER:

ТЕКСТ в виде строк ISO8601 («ГГГГ-ММ-ДД ЧЧ: ММ: СС.ССС»). НАСТОЯЩИЙ по юлианскому календарю - количество дней, прошедших с полудня по Гринвичу 24 ноября 4714 г. до н.э., согласно пролептическому григорианскому календарю. INTEGER как время Unix, количество секунд с 1970-01-01 00:00:00 UTC. Приложения могут сохранять дату и время в любом из этих форматов и свободно конвертировать между форматами, используя встроенные функции даты и времени.

Сказав это, я бы использовал INTEGER и сохранял секунды с эпохи Unix (1970-01-01 00:00:00 UTC).

Диего Торрес Милано
источник
1
Я тоже предпочитаю это. Стандартные классы, связанные с датой / временем, в любом случае внутренне поддерживаются длинными числами, и их довольно легко сравнить.
Karakuri
1
@dtmilano Почему вы предпочитаете здесь INTEGER вместо String?
Игорь Ганапольский 09
1
INTEGER использует только 8 байтов, TEXT в этом примере использует 23 байта. Непонятно, как выбрать, в каком типе будут храниться данные. Означает ли это, что если я создам столбец типа INTEGER, функции будут автоматически сохраняться как Unix Time?
rayzinnz
2
REAL также использует 8 байтов. До конца 2286 года секунды эпохи будут состоять из 10 цифр, а поскольку IEEE double поддерживает 15-17 значащих цифр , это дает разрешение лучше, чем миллисекунды. RSQLiteпохоже, преобразовывает POSIXctв числовую эпоху, поэтому для меня это работает достаточно хорошо.
r2evans 02
@ r2evans Я не совсем понимаю, что вы говорите. Если я хочу сохранить миллисекунды с эпохи, как мне это сделать?
Майкл
14

Одна из мощных функций SQLite - это возможность выбрать тип хранилища. Преимущества / недостатки каждой из трех различных возможностей:

  • Строка ISO8601

    • Сравнение строк дает верные результаты
    • Сохраняет доли секунды до трех десятичных цифр
    • Требуется больше места для хранения
    • Вы сразу увидите его значение при использовании браузера базы данных.
    • Необходимость синтаксического анализа для других целей
    • Модификатор столбца default current_timestamp будет хранить в этом формате
  • Настоящий номер

    • Высокая точность относительно долей секунд
    • Самый длинный временной диапазон
  • Целое число

    • Наименьшее место для хранения
    • Быстрые операции
    • Малый временной диапазон
    • Возможная проблема 2038 года

Если вам нужно сравнить разные типы или экспортировать во внешнее приложение, вы можете использовать собственные функции преобразования даты и времени SQLite по мере необходимости.

ЗСО
источник
1
Почему возникает проблема 2038 года? INTEGER, похоже, поддерживает 64-битное хранилище.
гуань бошен
1
@guanboshen Насколько я могу судить, единственная причина для беспокойства по поводу 2038 - это поддержка на платформе хоста. Документация SQLite утверждает, что использует C localtime_r()( sqlite.org/lang_datefunc.html#caveats_and_bugs ) в эталонной реализации и localtime()потенциально может быть уязвима для 2038 года, если платформа хоста имеет 32-разрядную версиюtime_t . Тем не менее, поскольку SQLite утверждает, что защищает от этой возможности путем сопоставления внешних дат с предварительным преобразованием безопасного диапазона (см. Ту же ссылку), я думаю, что это вряд ли будет проблемой, за исключением, может быть, эзотерических случаев.
Зои Спаркс,
@ ZoëSparks Спасибо за разъяснения.
гуань бошен
7

Практически для всех вопросов, касающихся даты и времени, я предпочитаю упрощать вещи, очень, очень просто ... вплоть до секунд, хранящихся в целых числах.

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

Поступая таким образом, вам не нужно беспокоиться, когда [вставить текущую избранную базу данных здесь] будет заменено на [будущую избранную базу данных], которая по совпадению не использует формат даты, который вы выбрали сегодня.

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

Кельвин Уильямс
источник
7

Сохраните его в поле типа long. Смотрите Date.getTime()иnew Date(long)

коэм
источник
как я могу это сравнить ?? Можешь дать мне образец запроса ..: D
Хайрил Ушан
Посмотрите на Joda Time для сравнений в коде ( joda-time.sourceforge.net ) и используйте простое длинное сравнение в SQL (например, численное сравнение).
Синтаксис
выберите * из таблицы, где создание находится между a и b;
koem