Лучший способ сохранить время (чч: мм) в базе данных


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

15 82

15 ответов:

вы можете сохранить его в виде целого числа минут после полуночи:

например.

0 = 00:00 
60 = 01:00
252 = 04:12

однако вам придется написать некоторый код, чтобы восстановить время, но это не должно быть сложно.

Если вы используете SQL Server 2008+, рассмотрите TIME тип данных. статья SQLTeam С большим количеством примеров использования.

DATETIME начало DATETIME конец

Я умоляю вас использовать два значения даты и времени вместо этого, помечены что-то вроде event_start и event_end.

время-это сложный бизнес

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

со временем, однако, у нас есть; 1000 миллисекунд в секунду, 60 секунд до минуты, 60 минут до часа, 12 часов для каждой половины дня, примерно 30 дней в месяц, которые варьируются в зависимости от месяца и даже года в вопросе, каждая страна имеет свое время смещение от других, способ форматирования времени в каждой стране варьируются.

Это много, чтобы переварить, но длинные и короткие невозможно для такого сложного сценария, чтобы иметь простое решение.

некоторые углы можно срезать, но есть и такие, где разумнее не делать

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

причины для реализации двух значений DATETIME предназначены для повышения точности, разрешения и обратная связь.

все это очень удобно, когда дизайн дает нежелательные результаты.

я храню больше данных, чем требуется?

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

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

это огромная планета

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

C#

A DateTime хорошо отображает строку в C#. Метод ToString (string Format) компактен и удобен для чтения.

например.

new TimeSpan(EventStart.Ticks - EventEnd.Ticks).ToString("h'h 'm'm 's's'")

SQL server

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

например.

SELECT DATEDIFF(MINUTE, event_start, event_end)

стандарт даты ISO8601

Если используя SQLite, тогда у вас этого нет, поэтому вместо этого используйте текстовое поле и сохраните его в формате ISO8601, например.

"2013-01-27T12:30:00+0000"

Примечания:

  • Это использует 24-часовые часы*

  • часть + 0000 ISO8601 отображает непосредственно на lattitude в GPS-координате. Поэтому стоит задуматься, если это стоило бы хранить долготе, широте и высоте вместе с данными. Это будет варьироваться в приложение.

  • ISO8601-это международный формат.

  • Вики очень хорошо для более подробной информации на http://en.wikipedia.org/wiki/ISO_8601.

  • дата и время хранятся в международном времени, а смещение записывается в зависимости от того, где в мире было сохранено время.

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

Дополнительные советы бесплатно!--16-->

также стоит группировать события вместе, как цепь. Например, при записи гонки все событие может быть сгруппировано по racer, race_circuit, circuit_checkpoints и circuit_laps.

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

чем больше вы вкладываете, тем больше вы выходите

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

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

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

чем лучше ваш первоначальный дизайн, тем дешевле ремонт будет позже.

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

просто храните обычное время и игнорируйте все остальное. Зачем тратить дополнительное время на написание кода, который загружает int, манипулирует им и преобразует его в datetime, когда вы можете просто загрузить datetime?

поскольку вы не упомянули об этом бит, Если вы находитесь на SQL Server 2008, Вы можете использовать тип данных time в противном случае использовать минуты с полуночи

Я бы преобразовал их в целое число (HH*3600 + MM*60) и сохранил его таким образом. Небольшой размер хранения,и все еще достаточно легко работать.

Если вы используете MySQL, используйте тип поля времени и связанную с ним функциональность, которая приходит со временем.

00:00:00-это стандартный формат времени Unix.

Если вам когда-нибудь придется оглянуться назад и просмотреть таблицы вручную, целые числа могут быть более запутанными, чем фактическая отметка времени.

SQL Server фактически хранит время как доли дня. Например, 1 целый день = значение 1. 12 часов-это значение 0,5.

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

например:

SELECT CAST(0.5 AS DATETIME)
--1900-01-01 12:00:00.000

хранение значения в виде десятичной дроби (9,9) потребляло бы 5 байт. Однако, если точность не имеет первостепенного значения, a REAL будет потреблять только 4 байта. В любом случае, агрегированный расчет (т. е. среднее время) может быть легко вычислен по числовым значениям, но не по типам данных/времени.

попробуйте smalldatetime. Это может не дать вам то, что вы хотите, но это поможет вам в ваших будущих потребностях в манипуляциях с датой/временем.

вы уверены, что вам понадобятся только часы и минуты? Если вы хотите сделать что-то значимое с ним (например, вычислить промежутки времени между двумя такими точками данных), не имея информации о часовых поясах и DST может дать неправильные результаты. Часовые пояса, возможно, не применяются в вашем случае, но DST, безусловно, будет.

Я думаю, что вы просите переменную, которая будет хранить минуты как число. Это можно сделать с различными типами целочисленных переменных:

SELECT 9823754987598 AS MinutesInput

тогда в вашей программе вы можете просто просмотреть это в форме, которую вы хотите, рассчитав:

long MinutesInAnHour = 60;

long MinutesInADay = MinutesInAnHour * 24;

long MinutesInAWeek = MinutesInADay * 7;


long MinutesCalc = long.Parse(rdr["MinutesInput"].toString()); //BigInt converts to long. rdr is an SqlDataReader.   


long Weeks = MinutesCalc / MinutesInAWeek;

MinutesCalc -= Weeks * MinutesInAWeek;


long Days = MinutesCalc / MinutesInADay;

MinutesCalc -= Days * MinutesInADay;


long Hours = MinutesCalc / MinutesInAnHour;

MinutesCalc -= Hours * MinutesInAnHour;


long Minutes = MinutesCalc;

возникает проблема, когда вы запрашиваете эффективность для использования. Но, если вам не хватает времени, то просто использовать тип bigint значение null, чтобы сохранить установленное значение минут.

значение null значит, время еще не записано.

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

например:

  • Если MinutesInput = 0..255 затем использовать TinyInt (преобразования, как описано выше.)

  • Если MinutesInput = 256..131071 затем использовать SmallInt (Примечание: тип smallint мин значение -32 768. Поэтому, отрицайте и добавляйте 32768 при хранении и получение значения для использования полного диапазона перед преобразованием, как указано выше).

  • Если MinutesInput = 131072..8589934591 затем использовать Int (Примечание: отрицание и добавление 2147483648 as необходимый.)

  • Если MinutesInput = 8589934592..36893488147419103231 затем использовать BigInt (Примечание: добавить и отменить 9223372036854775808 по мере необходимости).

  • Если MinutesInput > 36893488147419103231 тогда я бы лично использовал VARCHAR (X) увеличивает X по мере необходимости, так как символ является байтом. Я придется пересмотреть этот ответ на более поздний срок, чтобы описать это полностью (или, может быть, парень stackoverflowee может закончить этот ответ).

пока сохраняемые значения не достигнут числа, превышающего 36893488147419103231, вы можете также иметь один столбец BigInt для представления ваших минут, поскольку вам не нужно будет тратить Int на уникальный идентификатор и другой int для хранения значения минут.

вместо минут-за-полночь мы храним его как 24 часа в сутки, как SMALLINT.

09:12 = 912 14:15 = 1415

при преобразовании обратно в" читаемую человеком форму "мы просто вставляем двоеточие": "два символа справа. Левая панель с нулями, если вам нужно. Сохраняет математику каждый путь и использует несколько меньшее количество байтов (по сравнению с varchar), Плюс обеспечивает, чтобы значение было числовым (а не буквенно-цифровым)

довольно глупо, хотя ... там должно быть был тип данных времени в MS SQL в течение многих лет уже IMHO ...

экономия времени в формате UTC может помочь лучше, как предложила Кристен.

убедитесь, что вы используете 24-часовые часы, потому что в UTC нет meridian AM или PM.

пример:

  • 4:12 утра - 0412
  • 10: 12 утра-1012
  • 2: 28 PM-1428
  • 11: 56 PM-2356

его по-прежнему предпочтительнее использовать стандартный четырехзначный формат.

сохранить ticks как long/bigint, которые в настоящее время измеряются в миллисекундах. Обновленное значение можно найти, посмотрев на TimeSpan.TicksPerSecond значение.

большинство баз данных имеют тип DateTime, который автоматически сохраняет время как тики за кулисами, но в случае некоторых баз данных, например SqlLite, хранение тиков может быть способом хранения даты.

большинство языков позволяют легко конвертировать из TicksTimeSpanTicks.

пример

в C# код будет такой:

long TimeAsTicks = TimeAsTimeSpan.Ticks;

TimeAsTimeSpan = TimeSpan.FromTicks(TimeAsTicks);

имейте в виду, хотя, потому что в случае SqlLite, который предлагает только небольшое количество различных типов, которые являются; INT,REAL и VARCHAR необходимо будет хранить количество тиков в виде строки или двух INT клетки в сочетании. Это, потому что INT - это 32-битное число со знаком, тогда как BIGINT - это 64-битный номер со знаком.

Примечание

мое личное предпочтение, однако, будет хранить дату и время как ISO8601 строку.

IMHO то, что лучшее решение зависит в некоторой степени от того, как вы храните время в остальной части базы данных (и остальной части вашего приложения)

лично я работал с SQLite и стараюсь всегда использовать метки времени unix для хранения абсолютного времени, поэтому при работе с временем суток (как вы просите) я делаю то, что Глен Солсберри пишет в своем ответе, и сохраняю количество секунд с полуночи

при принятии этого общего подхода людей (включая меня!) чтение кода менее запутано, если я использую один и тот же стандарт везде