Лучший способ сохранить время (чч: мм) в базе данных - PullRequest
88 голосов
/ 11 февраля 2009

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

Ответы [ 15 ]

117 голосов
/ 11 февраля 2009

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

например.

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

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

51 голосов
/ 12 февраля 2009

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

11 голосов
/ 06 апреля 2012

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

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

Время - сложное дело

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

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

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

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

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

Причины применения двух значений DATETIME - повышение точности, разрешения и обратной связи.

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

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

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

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

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

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

C #

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

1053 * Е.Г. *

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

SQL-сервер

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

1062 * Е.Г. *

SELECT DATEDIFF(MINUTE, event_start, event_end)

Стандарт даты ISO8601

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

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

Примечания:

  • Используются 24-часовые часы *

  • Часть смещения по времени (или +0000) ISO8601 отображается непосредственно на значение долготы GPS-координаты (без учета перехода на летнее время или по всей стране).

1085 * Е.Г. *

TimeOffset=(±Longitude.24)/360 

... где ± относится к восточному или западному направлению.

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

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

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

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

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

Дополнительные советы бесплатно

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

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

Чем больше вы положите, тем больше вы получите

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

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

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

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

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

9 голосов
/ 12 февраля 2009

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

4 голосов
/ 12 февраля 2009

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

2 голосов
/ 14 февраля 2009

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

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

Например:

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

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

2 голосов
/ 12 февраля 2009

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

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

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

2 голосов
/ 11 февраля 2009

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

1 голос
/ 20 октября 2015

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

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 означает, что время еще не записано.

Теперь я объясню в форме поездки в космос.

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

Например:

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

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

  • Если MinutesInput = 131072 .. 8589934591 , тогда используйте Int (Примечание. Отложите и добавьте 2147483648 по мере необходимости).

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

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

Поскольку каждому значению, несомненно, потребуется уникальный ключ, эффективность базы данных будет очевидна только в том случае, если диапазон хранимых значений представляет собой хорошее сочетание между очень маленьким (около 0 минут) и очень высоким (больше 8589934591) ,

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

1 голос
/ 14 февраля 2009

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

09: 12 = 912 14:15 = 1415

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

Довольно глупо, хотя ... в MS SQL уже много лет должен был быть тип данных TIME ИМХО ...

...