Meilleure façon de stocker l'heure (hh: mm) dans une database

Je veux stocker des time dans une table de database mais seulement besoin de stocker les heures et les minutes. Je sais que je pourrais juste utiliser DATETIME et ignorer les autres composants de la date, mais quelle est la meilleure façon de le faire sans stocker plus d'informations que j'ai réellement besoin?

    Vous pouvez le stocker sous la forme d'un integer 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é.

    Si vous utilisez SQL Server 2008+, tenez count du type de données TIME . Article SQLTeam avec plus d'exemples d'utilisation.

    Juste stocker un datetime régulier et ignorer tout le rest. Pourquoi passer plus de time à écrire du code qui charge un int, le manipule et le convertit en datetime, alors que vous pourriez simplement charger un datetime?

    DATETIME start DATETIME fin

    Je vous implore d'utiliser à la place deux valeurs DATETIME , étiquetées quelque chose comme event_start et event_end .

    Le time est une affaire complexe

    La plupart du monde a maintenant adopté le système mésortingque basé sur la dénégation pour la plupart des mesures, à tort ou à raison. C'est globalement bien, car au less on peut tous convenir que ag, c'est un ml, c'est un centimètre cube. Au less à peu près ainsi. Le système mésortingque a de nombreux défauts, mais au less il est constamment défectueux à l'échelle internationale.

    Avec le time cependant, nous avons; 1000 millisecondes dans 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 a son time compensé par d'autres , la façon dont le time est formaté dans chaque pays varie.

    Il y a beaucoup à digérer, mais le plus long et le plus court est impossible pour un scénario aussi complexe d'avoir 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 meilleure réponse ici suggère que vous stockez un integer de minutes après minuit peut sembler parfaitement raisonnable, j'ai appris à éviter de le faire à la dure.

    Les raisons d'implémenter deux valeurs DATETIME sont une augmentation de la précision, de la résolution et de la rétroaction.

    Ceux-ci sont tous très utiles lorsque la design produit des résultats indésirables.

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

    Au début, il peut sembler que plus d'informations sont stockées que ce dont j'ai besoin, mais il y a une bonne raison de prendre ce coup.

    Stocker ces informations supplémentaires finit presque toujours par me faire gagner du time et de l'énergie à long terme, car je trouve inévitablement que lorsque quelqu'un est informé de la durée d'un événement, il veut é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 avait d'autres pays sur cette planète à part le mien. Cela semblait être une bonne idée à l'époque, mais cela a TOUJOURS entraîné des problèmes, des maux de tête et une perte de time plus tard. TOUJOURS considérer tous les fuseaux horaires.

    C #

    Un DateTime rend bien à une string en C #. La méthode ToSsortingng (string de format) est compacte et facile à lire.

    Par exemple

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

    Serveur SQL

    Aussi, si vous lisez votre database séparément à l'interface de votre application, dateTimes sont agréable à lire en un coup d'œil et effectuer des calculs sur eux sont simples.

    Par exemple

     SELECT DATEDIFF(MINUTE, event_start, event_end) 

    Norme de date ISO8601

    Si vous utilisez SQLite alors vous n'avez pas cela, utilisez plutôt un champ de text et stockez-le au format ISO8601 par exemple.

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

    Remarques:

    • Cela utilise l'horloge 24 heures *

    • La partie +0000 de l'ISO8601 correspond directement à lattitude dans une coordonnée GPS. Il est donc utile de considérer si cela vaudrait la peine de stocker la longitude, la lattitude et l'altitude avec datatables. Cela va varier 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ù le time a été stocké dans le monde.

    Selon mon expérience, il est toujours nécessaire de stocker la date et l'heure complètes, peu importe si je pense qu'il y a quand je commence le projet. ISO8601 est un très bon moyen de le faire à l'avenir.

    Conseils supplémentaires gratuits

    Il vaut également la peine de regrouper les events comme une string. Par exemple, si vous enregistrez une course, l'set de l'événement peut être groupé par coureur, course_circuit, circuit_checkpoints et circuit_laps.

    Dans mon expérience, il est également sage d'identifier qui a stocké l'logging. Soit en tant que table séparée remplie via un triggersur ou en tant que colonne supplémentaire dans la table d'origine.

    Plus vous investissez, plus vous en sortez

    Je comprends parfaitement le désir d'être aussi économe en espace que possible, mais je le ferais rarement au désortingment de la perte d'information.

    Une règle de base avec les bases de données est comme le dit le titre, une database ne peut vous dire que ce qu'elle contient, et il peut être très coûteux de remonter dans datatables historiques et de combler les lacunes.

    La solution est de le corriger la première fois. Ceci est certainement plus facile à dire qu'à faire, mais vous devriez maintenant avoir un aperçu plus approfondi de la design efficace d'une database et avoir par la suite une meilleure chance d'y arriver correctement la première fois.

    Plus votre design initiale est bonne, less les réparations seront coûteuses.

    Je dis seulement tout ça, parce que si je pouvais remonter dans le time, c'est ce que je me dirais quand je serais arrivé.

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

    Je les convertirais en un entier (HH * 3600 + MM * 60), et le stocker de cette façon. Petite taille de stockage, et encore assez facile à travailler.

    Si vous utilisez MySQL, utilisez un type de champ TIME et les fonctionnalités associées à TIME.

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

    Si jamais vous devez regarder en arrière et examiner les tables à la main, les entiers peuvent être plus confus qu'un horodatage réel.

    SQL Server stocke réellement l'heure en tant que fractions d'un jour. Par exemple, 1 jour entier = valeur de 1. 12 heures est une valeur de 0.5.

    Si vous voulez stocker la valeur de time sans utiliser un type DATETIME, stocker l'heure sous une forme décimale conviendrait à ce besoin, tout en rendant la conversion à un DATETIME simple.

    Par exemple:

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

    Stocker la valeur en tant que DECIMAL (9,9) consum 5 octets. Cependant, si la précision n'est pas de la plus haute importance, un REAL ne consumrait que 4 octets. Dans les deux cas, le calcul agrégé (c'est-à-dire le time moyen) peut être facilement calculé sur des valeurs numériques, mais pas sur les types Data / Time.

    Essayez smalldatetime. Il ne peut pas vous donner ce que vous voulez mais cela vous aidera dans vos besoins futurs dans les manipulations de date / heure.

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

    Ce que je pense que vous requestz est une variable qui va stocker les minutes sous forme de nombre. Cela peut être fait avec les différents types de variables entières:

     SELECT 9823754987598 AS MinutesInput 

    Ensuite, dans votre programme, vous pouvez simplement afficher 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"].toSsortingng()); //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 requestz que l'efficacité soit utilisée. Mais, si vous manquez de time, utilisez simplement un BigInt nullable pour stocker votre valeur de minutes.

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

    Maintenant, je vais expliquer sous la forme d'un aller-return dans l'espace.

    Malheureusement, une colonne de table ne stocke qu'un seul type. Par conséquent, vous devrez créer une nouvelle table pour chaque type si nécessaire.

    Par exemple:

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

    • Si MinutesInput = 256 .. 131071 alors utilisez SmallInt (Remarque: la valeur min de SmallInt est -32 768. Par conséquent, annulez et ajoutez 32768 lorsque vous stockez et récupérez la valeur pour utiliser la gamme complète avant de convertir comme ci-dessus).

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

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

    • Si MinutesInput> 36893488147419103231 alors j'utiliserais personnellement VARCHAR (X) en augmentant X autant que nécessaire car un char est un octet. Je devrai revoir cette réponse à une date ultérieure pour la décrire en entier (ou peut-être qu'un camarade stackoverflow peut terminer cette réponse).

    Puisque chaque valeur nécessitera sans aucun doute une key unique, l'efficacité de la database ne sera apparente que si la plage des valeurs stockées est un bon mélange entre très petit (près de 0 minute) et très élevé (plus grand que 8589934591).

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

    Au lieu de minutes-après-minuit, nous stockons comme horloge de 24 heures, comme un SMALLINT.

    09h12 = 9h12 14h15 = 14h15

    lors de la conversion en "forme lisible par l'homme" nous insérons simplement un deux-points ":" deux caractères de la droite. Gauche-pad avec des zéros si nécessaire. Enregistre les mathématiques dans chaque sens, et utilise quelques octets de less (par rapport à varchar), plus impose que la valeur est numérique (plutôt que alphanumérique)

    Assez maladroit cependant … il aurait dû y avoir un datatype TIME en MS SQL depuis plusieurs années déjà IMHO …

    L'économie de time en format UTC peut aider mieux comme suggéré par Kristen.

    Assurez-vous que vous utilisez l'horloge 24 heures parce qu'il n'y a pas de méridien AM ou PM être utilisé en UTC.

    Exemple:

    • 04h12 – 0412
    • 10:12 – 1012
    • 14h28 – 14h28
    • 23h56 – 23h56

    Il est toujours préférable d'utiliser le format standard à quatre numbers.

    Stocker les ticks comme un 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 en tant que ticks dans les coulisses, mais dans le cas de certaines bases de données, par exemple 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, parce que dans le cas de SqlLite, qui offre seulement 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 string ou de deux cellules INT combinées. C'est parce qu'un INT est un nombre signé 32 bits alors que BIGINT est un nombre signé 64 bits.

    Remarque

    Ma preference personnelle, cependant, serait de stocker la date et l'heure en tant que string ISO8601 .

    À mon humble avis quelle est la meilleure solution dépend dans une certaine mesure de la façon dont vous stockez le time dans le rest de la database (et le rest de votre application)

    Personnellement, j'ai travaillé avec SQLite et j'essaie toujours d'utiliser un horodatage Unix pour stocker le time absolu, donc quand je parle de l'heure (comme vous le requestz) je fais ce que Glen Solsberry écrit dans sa réponse et stocke le nombre de secondes depuis minuit

    En adoptant cette approche générale, les gens (y compris moi!) Lisant le code sont less confus si j'utilise la même norme partout