web-dev-qa-db-fra.com

Meilleure façon de stocker le temps (hh: mm) dans une base de données

Je veux stocker les heures dans une table de base de données, mais je n'ai besoin que de stocker les heures et les minutes ..__ Je sais que je pourrais utiliser DATETIME et ignorer les autres composants de la date, mais quel est le meilleur moyen de le faire sans stocker plus d'informations que j'ai réellement besoin?

84
Matthew Dresser

Vous pouvez le stocker en tant qu'entier du nombre de minutes après minuit:

par exemple. 

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

Vous auriez cependant besoin d'écrire du code pour reconstituer l'heure, mais cela ne devrait pas être compliqué.

114
BigJump

Si vous utilisez SQL Server 2008+, considérez le type TIME dat. Article SQLTeam avec plus d'exemples d'utilisation.

48
WebMatrix

DATETIME début DATETIME fin

Je vous implore d'utiliser deux valeurs DATETIME à la place, étiqueté quelque chose comme début_événement et fin_événement

Le temps est une affaire complexe

La plupart des pays ont maintenant adopté le système métrique basé sur le denery pour la plupart des mesures, à tort ou à raison. C’est une bonne chose dans l’ensemble, car au moins, nous pouvons tous convenir que un g, un ml, un cm 3. Au moins approximativement. Le système métrique présente de nombreux défauts, mais au moins il est constamment défectueux au niveau international.

Avec le temps cependant, nous avons; 1000 millisecondes en une seconde, 60 secondes à une minute, 60 minutes à une heure, 12 heures pour chaque demi-journée, environ 30 jours par mois, qui varient selon le mois et même l'année en question, chaque pays ayant son heure décalée , la façon dont le temps est formaté dans chaque pays varie.

C’est beaucoup à digérer, mais il est impossible qu’un scénario aussi complexe ait une solution simple.

Certains coins peuvent être coupés, mais il y a ceux où il est plus sage de ne pas

Bien que la réponse principale suggère que vous stockiez un nombre entier de minutes après minuit peut sembler parfaitement raisonnable, j’ai appris à éviter de le faire à la dure.

Les raisons pour implémenter deux valeurs DATETIME sont une augmentation de la précision, de la résolution et du retour. 

Celles-ci sont toutes très utiles lorsque la conception produit des résultats indésirables.

Est-ce que je stocke plus de données que nécessaire?

Il peut sembler initialement que plus d’informations sont stockées que ce dont j’ai besoin, mais il ya une bonne raison de prendre ce coup. 

Le stockage de ces informations supplémentaires finit presque toujours par me faire gagner du temps et des efforts sur le long terme, car je constate inévitablement que lorsque quelqu'un se fait dire combien de temps a duré, il voudra également savoir quand et où l'événement a eu lieu.

C'est une énorme planète

Dans le passé, j'ai été coupable d'ignorer qu'il y a d'autres pays sur cette planète que le mien. Cela semblait une bonne idée à l’époque, mais cela a TOUJOURS abouti à des problèmes, des maux de tête et une perte de temps par la suite. TOUJOURS considérer tous les fuseaux horaires.

C #

Un DateTime rend bien à une chaîne en C #. La méthode ToString (string Format) est compacte et facile à lire. 

Par exemple.

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

Serveur SQL

De même, si vous lisez votre base de données séparément de l'interface de votre application, les datesTimes sont faciles à lire en un coup d'œil et les calculs sont simples à effectuer.

Par exemple.

SELECT DATEDIFF(MINUTE, event_start, event_end)

ISO8601 date standard

Si vous utilisez SQLite, vous ne disposez pas de cela, utilisez plutôt un champ de texte et stockez-le au format ISO8601, par exemple.

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

Remarques: 

  • Cela utilise une horloge de 24 heures *

  • La partie +0000 de l'ISO 8601 mappe directement sur la lattitude en coordonnée GPS. Il est donc intéressant d’examiner s’il serait utile de stocker la longitude, la latitude et l’altitude avec les données. Cela variera dans l'application.

  • ISO8601 est un format international. 

  • Le wiki est très bon pour plus de détails sur http://en.wikipedia.org/wiki/ISO_8601 .

  • La date et l'heure sont stockées en heure internationale et le décalage est enregistré en fonction de l'endroit où l'heure a été enregistrée dans le monde. 

D'après mon expérience, il est toujours nécessaire de stocker la date et l'heure complètes, que je le pense ou non, au début du projet. ISO8601 est un très bon moyen de le faire pour l'avenir.

Conseils supplémentaires gratuits

Cela vaut également la peine de regrouper des événements comme une chaîne. Par exemple. si vous enregistrez une course, tout l'événement peut être groupé par coureur, race_circuit, circuit_checkpoints et circuit_laps.

D'après mon expérience, il est également sage d'identifier qui a stocké le disque. Soit comme une table séparée remplie via un déclencheur, soit comme une colonne supplémentaire dans la table d'origine. 

Plus vous en mettez, plus vous en sortez

Je comprends tout à fait le désir d’être aussi économique que possible en matière d’espace, mais je le ferais rarement aux dépens de la perte d’informations.

Comme le titre l'indique, une base de données est la règle, une base de données ne peut vous en dire autant que possible, et il peut être très coûteux de revenir en arrière dans les données historiques en comblant les lacunes.

La solution consiste à le faire correctement du premier coup. C’est certes plus facile à dire qu’à faire, mais vous devriez maintenant avoir une idée plus précise de la conception efficace de la base de données et par la suite une chance beaucoup plus grande de bien faire les choses la première fois.

Plus votre conception initiale est bonne, moins les réparations seront coûteuses par la suite.

Je ne fais que dire tout cela, car si je pouvais remonter dans le temps, c'est ce que je me dirais quand je serai arrivé là-bas.

11

Stockez simplement une date-heure normale et ignorez tout le reste. Pourquoi passer plus de temps à écrire du code qui charge un int, le manipule et le convertit en un datetime, alors que vous pouvez simplement charger un datetime?

10
Seth

comme vous ne l'avez pas mentionné un peu si vous êtes sur SQL Server 2008, vous pouvez utiliser le type de données time, sinon utilisez les minutes depuis minuit

4
SQLMenace

Je les convertirais en un entier (HH * 3600 + MM * 60) et les stockerais ainsi. Petite taille de stockage, et toujours assez facile à utiliser.

2
Glen Solsberry

SQL Server stocke en réalité le temps sous forme de fractions de jour. Par exemple, 1 journée entière = valeur de 1. 12 heures est une valeur de 0,5.

Si vous souhaitez stocker la valeur de l'heure sans utiliser un type DATETIME, le stockage de l'heure sous forme décimale répond à ce besoin, tout en simplifiant la conversion en DATETIME.

Par exemple:

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

Stocker la valeur en tant que DECIMAL (9,9) consomme 5 octets. Cependant, si la précision n'est pas d'une importance capitale, un REAL ne consomme que 4 octets. Dans les deux cas, le calcul global (c'est-à-dire le temps moyen) peut être facilement calculé sur des valeurs numériques, mais pas sur des types de données/temps.

2
Taylor Gerring

Si vous utilisez MySQL, utilisez un type de champ TIME et la fonctionnalité associée fournie avec TIME.

00:00:00 est le format d'heure standard Unix.

Si vous devez regarder en arrière et revoir les tableaux à la main, les entiers peuvent être plus déroutants qu'un horodatage réel.

2
Syntax

Au lieu de minutes après minuit, nous le stockons au format 24 heures, sous forme de PEINTURE.

09:12 = 912 14:15 = 1415

lors de la reconversion en "forme lisible par l'homme", nous insérons simplement un deux-points ":" deux caractères à partir de la droite. Pavé gauche avec zéros si nécessaire. Enregistre les mathématiques dans les deux sens et utilise quelques octets en moins (par rapport à varchar). De plus, la valeur est numérique (et non alphanumérique).

Assez maladroit cependant ... il aurait dû y avoir un type de données TIME en MS SQL depuis plusieurs années déjà à mon humble avis ... 

1
Kristen

Je pense que vous demandez une variable qui stockera les minutes sous forme de nombre. Cela peut être fait avec les différents types de variable entière:

SELECT 9823754987598 AS MinutesInput

Ensuite, dans votre programme, vous pouvez simplement visualiser ceci sous la forme que vous souhaitez en calculant:

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;

Un problème se pose lorsque vous demandez que l'efficacité soit utilisée. Mais si vous manquez de temps, alors utilisez simplement un BigInt nullable pour stocker la valeur de vos minutes.

Une valeur nulle signifie que l'heure n'a pas encore été enregistrée.

Maintenant, je vais expliquer sous la forme d'un aller-retour vers l'espace extra-atmosphérique.

Malheureusement, une colonne de table ne stockera qu'un seul type. Par conséquent, vous devrez créer une nouvelle table pour chaque type, selon les besoins.

Par exemple:

  • Si MinutesInput = 0..255, utilisez alors TinyInt (convertissez comme décrit ci-dessus).

  • Si MinutesInput = 256..131071, utilisez alors SmallInt (Remarque: La valeur min De SmallInt est -32 768. Par conséquent, annulez et ajoutez 32 768 lors du stockage et récupérer la valeur pour utiliser la plage complète avant la conversion comme ci-dessus).

  • Si MinutesInput = 131072..8589934591, utilisez Int (Remarque: annulez et ajoutez 2147483648 si nécessaire).

  • Si MinutesInput = 8589934592..36893488147419103231, utilisez alors BigInt (Remarque: Ajoutez et annulez 9223372036854775808 si nécessaire).

  • Si MinutesInput> 36893488147419103231, j'utiliserais personnellement VARCHAR (X) augmentant X autant que nécessaire, car un caractère est un octet. Je devrai Devra revenir sur cette réponse à une date ultérieure pour la décrire en détail (Ou peut-être un autre membre de la hiérarchie pourra-t-il finir cette réponse).

Étant donné que chaque valeur nécessitera sans aucun doute une clé unique, l'efficacité de la base de données ne sera évidente que si la plage des valeurs stockées est un bon mélange entre très petite (près de 0 minute) et très haute (Supérieure à 8589934591). 

Jusqu'à ce que les valeurs stockées atteignent un nombre supérieur à 36893488147419103231, vous pouvez également avoir une seule colonne BigInt pour représenter vos minutes, car vous n'avez pas besoin de gaspiller un Int sur un identifiant unique et un autre int pour stocker la valeur des minutes.

1

Essayez smalldatetime. Cela ne vous donnera peut-être pas ce que vous voulez, mais cela vous aidera dans vos besoins futurs en manipulations de date/heure.

1
MarlonRibunal

Êtes-vous sûr que vous n'aurez besoin que des heures et des minutes? Si vous voulez faire quelque chose de significatif avec elle (par exemple, calculer des intervalles de temps entre deux points de données), ne pas avoir d'informations sur les fuseaux horaires et l'heure d'été peut donner des résultats incorrects. Les fuseaux horaires ne s'appliquent peut-être pas à votre cas, mais l'heure d'été le sera certainement.

1
mghie

Le gain de temps au format UTC peut aider mieux, comme l’a suggéré Kristen.

Assurez-vous que vous utilisez une horloge de 24 heures car il n'y a pas de méridien AM ou PM à utiliser en UTC.

Exemple:

  • 04h12 - 0412
  • 10h12 - 1012
  • 14h28 PM - 1428
  • 11h56 PM - 2356

Il est toujours préférable d’utiliser le format standard à quatre chiffres. 

0
balamurugavel

Stockez la ticks en tant que long/bigint, qui sont actuellement mesurés en millisecondes. La valeur mise à jour peut être trouvée en regardant la valeur TimeSpan.TicksPerSecond.

La plupart des bases de données ont un type DateTime qui stocke automatiquement l’heure sous forme de ticks dans les coulisses, mais dans le cas de certaines bases de données, par ex. SqlLite, le stockage des ticks peut être un moyen de stocker la date.

La plupart des langues permettent la conversion facile de TicksTimeSpanTicks.

Exemple

En C #, le code serait:

long TimeAsTicks = TimeAsTimeSpan.Ticks;

TimeAsTimeSpan = TimeSpan.FromTicks(TimeAsTicks);

Soyez conscient cependant, car dans le cas de SqlLite, qui n’offre qu’un petit nombre de types différents, qui sont; INT, REAL et VARCHAR Il sera nécessaire de stocker le nombre de ticks sous la forme d'une chaîne ou de deux cellules INT combinées. En effet, INT est un numéro signé de 32 bits alors que BIGINT est un numéro signé de 64 bits. 

Remarque

Ma préférence personnelle cependant serait de stocker la date et l'heure sous forme de chaîne ISO8601.

0