C'est un problème que j'ai rencontré plusieurs fois. Imaginez que vous ayez un enregistrement que vous souhaitez stocker dans une table de base de données. Cette table a une colonne DateTime appelée "date_created". Cet enregistrement en particulier a été créé il y a longtemps et vous n'êtes pas vraiment sûr de la date exacte, mais vous connaissez l'année et le mois. Autres disques que vous connaissez juste l'année. Autres enregistrements vous connaissez le jour, le mois et l'année.
Vous ne pouvez pas utiliser un champ DateTime, car "mai 1978" n'est pas une date valide. Si vous le divisez en plusieurs colonnes, vous perdez la possibilité d'interroger. Quelqu'un d'autre a-t-il rencontré cela? Si oui, comment l'avez-vous géré?
Pour clarifier le système que je suis en train de construire, c'est un système de suivi des archives. Certains contenus ont été produits il y a longtemps et tout ce que nous savons, c'est "mai 1978". Je pourrais le stocker comme le 1er mai 1978, mais seulement avec un moyen de noter que cette date n’est précise que pour le mois. Ainsi, quelques années plus tard, lorsque je récupèrerai ces archives, je ne serai pas confus lorsque les dates ne correspondent pas.
Pour mes besoins, il est important de différencier "jour inconnu de mai 1978" du "1er mai 1978". De plus, je ne voudrais pas stocker les inconnus comme 0, comme "0 mai 1978", car la plupart des systèmes de base de données refusent cela comme une date non valide.
la source
Réponses:
Stockez toutes les dates dans le champ DATE normal de la base de données et disposez d’un champ d’exactitude supplémentaire pour indiquer le degré de précision du champ DATE.
date_created_accuracy: 1 = date exacte, 2 = mois, 3 = année.
Si votre date est floue (par exemple, mai 1980), stockez-la au début de la période (par exemple, le 1er mai 1980). Ou si votre date est exacte à l'année (par exemple 1980), stockez-la le 1er janvier. 1980 avec la valeur de précision correspondante.
De cette façon, vous pouvez facilement interroger de manière assez naturelle et avoir toujours une idée de la précision des dates. Par exemple, cela vous permet d'interroger des dates entre
Jan 1st 1980
etFeb 28th 1981
, et d'obtenir des dates1980
etMay 1980
.la source
select * from mytable where date_created between "1980/1/1" and "1981/2/28" and date_created_accuracy <= 2;
. Génie.date_created_accuracy
champ. Vous pouvez afficher "mai 1980" ou simplement "1980" dans les résultats ou dans l'interface utilisateur si cela est aussi précis que le champ l'indique.Si vous n'avez pas besoin d'utiliser ce type de données comme information de date / heure normale, n'importe quel format de chaîne suffirait.
Mais si vous devez conserver toutes les fonctionnalités, il existe deux solutions de contournement auxquelles je peux penser, qui nécessitent toutes les deux des informations supplémentaires stockées dans la base de données:
min date
et lesmax date
champs, qui ont des valeurs différentes pour les données "incomplètes", mais coïncident pour des dates précises.type
champ aux enregistrements et conservez les informations manquantes.la source
min date
etmax date
champs. Je pense que c'est la solution la plus flexible, mais précise et facile à utiliser.Il s’agit en réalité d’une définition d’exigences plutôt que d’un problème technique: vous devez vous concentrer sur "comment définir les dates antérieures" et la solution technique va suivre.
Les fois où j'ai dû aborder quelque chose comme ça, nous avons généralement:
Parfois, il faut faire quelque chose comme rendre les dates floues - par exemple, une date peut avoir besoin de répondre à une requête pour quoi que ce soit en mai 1978. Cela est faisable - il suffit de créer vos champs create_date 2, les anciens enregistrements obtiennent un 30 les jours sont répartis comme il convient, les nouveaux ont 2 valeurs identiques.
la source
Le moyen le plus simple d'indiquer si la date est exacte consiste à créer un champ de précision INT (1) avec la valeur NULL par défaut.
Si la date est exacte, stockez la date et l'heure dans "date_created" et laissez la précision à NULL
Si la date n’est précise que pour le mois, stockez la date et l’heure au 1er du mois avec la valeur de précision 1
Si la date n’est exacte que pour l’année, date-heure du magasin, le 1er janvier, avec la valeur d’exactitude 2
Vous pouvez utiliser différents nombres pour contenir différentes valeurs telles que premier trimestre, etc.
la source
Dans le passé, j’enregistrais des dates avec précision comme date de début et de fin. Le jour du 21 mai 2012 serait représenté par le début = 12h, le 21 mai 2012 et la fin = 12h, le 22 mai 2012. L'année 2012 serait représentée par le début = 12 h, le 1 janvier 2012 et fin = 12 h, le 1 janvier 2013.
Je ne sais pas si je recommanderais cette approche. Lorsque vous affichez les informations à l'utilisateur, vous devez détecter correctement qu'une plage de dates couvre exactement un jour afin d'afficher le "25 mai" au lieu de deux points de terminaison trop spécifiques (ce qui signifie que vous devez gérer l'heure d'été, etc.).
Cependant, lorsque vous n'essayez pas de traduire en humain, la programmation avec les points de terminaison est beaucoup plus facile qu'avec centre + précision. Vous ne vous retrouvez pas avec beaucoup de cas. C'est plutôt sympa.
la source
Pourquoi ne pas stocker deux dates.
Created_After et Created_Before. La sémantique réelle étant "créée le ou après" et "créée le ou avant"
Donc, si vous connaissez la date exacte, Created_After et Created_Before sera la même date.
Si vous savez que c'était la première semaine de mai 2000, Created_After = '2000-05-01' et Created_Before = '2000-05-07'.
Si vous savez simplement que mai 1999, les valeurs seront '1999-05-01' et '1999-05-30'.
Si c'est "l'été de '42", les valeurs seront "1942-06-01" et "1942-08-31".
Ce schéma est simple à interroger avec du SQL normal et assez facile à suivre pour un utilisateur non technique.
Par exemple, pour trouver tous les documents pouvant avoir été créés en mai 2001:
Inversement, vous trouverez tous les documents définitivement créés en mai 2001:
la source
Le format date / heure ISO 8601 est fourni avec une définition de la durée, par exemple:
2012-01-01P1M
(lire: 1er janvier 2012, période: 1 mois) est ce qui devrait être «en janvier 2012».Je voudrais utiliser cela pour stocker les données. Pour ce faire, vous aurez peut-être besoin d'un champ de base de données de type String. C'est une autre question de savoir comment mener une recherche judicieuse à ce sujet.
la source
Généralement, je les stocke toujours en tant que dates de requête générales, même si elles sont légèrement moins précises.
S'il est important de connaître la précision, j'ai stocké une "fenêtre" de précision sous forme de décimale +/- ou de recherche (jour, mois, année, etc.). Dans d'autres cas, au lieu de la fenêtre, je stocke simplement la valeur de date d'origine sous forme de chaîne et convertis ce que je peux en date / heure, éventuellement 1978-05-01 00:00:00 et "mai 1978" pour votre exemple donné.
la source
Dit qui? Voici ce que vous faites:
Donc, si je fais un insert comme:
insert into thistable (Day, Month, Year) values (-1, 2, 2012);
alors TheDate deviendra le 01/02/2013, mais je saurai que c'est vraiment une date indéterminée dans 2/2012 en raison du -1 dans le champ Jour.Si je suis
insert into thistable (TheDate) values ('2/5/2012');
alors jour sera 5, mois sera 2 et année sera 2012 et parce qu'aucun d'entre eux n'est -1 je saurai que c'est la date exacte.Je ne perds pas la possibilité d'interroger car le déclencheur d'insertion / de mise à jour garantit que mes 3 champs (Jour, Mois, Année) produisent toujours une valeur DateTime dans TheDate qui peut être interrogée.
la source
Une autre option consisterait à stocker les dates sous forme d’entiers du formulaire
YYYYMMDD
.19510000
19510300
19510314
0
Avantages
Vous pouvez stocker votre date floue dans un champ au lieu de deux, ou une date et une précision comme le suggèrent de nombreuses autres réponses.
Les requêtes sont toujours faciles:
SELECT * FROM table WHERE thedate>=19510000 and thedate<19520000
SELECT * FROM table where thedate>=19510300 and thedate<19510400
SELECT * FROM table where thedate=19510314
REMARQUES
GetDateString(int fuzzyDate)
facile à mettre en œuvre.99
pour le 'padding' au lieu du00
mois ou du jour.la source
L'ISO 8601 spécifie également une syntaxe pour les "dates floues". Le 12 février 2012 à 15 heures serait "2012-02-12T15" et février 2012 pourrait être simplement "2012-02". Cela s'étend bien en utilisant le tri lexicographique standard:
la source
Voici mon point de vue sur ceci:
Passer de la date floue à l'objet datetime (qui s'intégrera dans une base de données)
Et ensuite une fonction qui prend l'objet datetime et le ramène à une date floue.
Et puis un test unitaire. Ai-je oublié des cas?
Il existe un cas particulier dans lequel un événement s'est produit exactement à
2001-01-01T00:00:00.333333
mais le système sera interprété comme étant "2001", mais cela semble très improbable.la source
Je travaille pour une maison d'édition qui traite beaucoup de vieux livres où nous ne pouvons souvent pas obtenir les dates exactes. Nous avons généralement deux champs pour une entrée de date donnée, la date et vers booléenne:
Nous utilisons le champ de date pour indiquer la date d’un événement ou une date "suffisamment proche" dans le cas où nous ne connaissons pas la date vraie. Si nous ne connaissons pas la date vraie, nous marquons le
dateCirca
champ commeY
et donnons une date assez proche, qui est marquée comme "1er", comme par exemplela source
Vue d'ensemble
Il existe de nombreuses représentations possibles, et donc des schémas de base de données, permettant de stocker des dates-heures floues (ou même simplement des dates floues):
[1], [2] et [3] sont tous (implicitement) des intervalles uniformes, c'est-à-dire un ensemble de points dans le temps (égaux).
[4] est le plus expressif, c’est-à-dire lorsqu’il permet des phrases ou des expressions écrites possibles (ou du moins arbitrairement longues). Mais c'est aussi le plus difficile à travailler. À la limite, une IA au niveau humain serait nécessaire pour gérer des valeurs arbitraires. Pratiquement, la plage de valeurs possibles devrait être sévèrement restreinte et des valeurs «structurées» alternatives seraient probablement préférées pour de nombreuses opérations, telles que le tri, la recherche.
[5] est probablement la représentation compacte la plus générale qui soit (un peu) pratique.
Intervalles uniformes
Les intervalles uniformes constituent le moyen le plus simple et le plus simple de représenter un ensemble de valeurs (possibles) date-heure.
Pour [1], les parties de la valeur date-heure sont ignorées, c'est-à-dire les parties correspondant à des unités plus fines que la précision ou l'exactitude indiquée. sinon, cela équivaut à [2] et le code précision / exactitude est équivalent à un intervalle avec les mêmes unités (et une quantité implicite de 1).
[2] et [3] sont expressément équivalents. [1] est strictement moins expressif que l'un ou l'autre puisqu'il existe des intervalles efficaces qui ne peuvent pas être représentés par [1], ex. une date-heure floue équivalente à un intervalle de 12 heures couvrant une limite de date.
[1] est plus facile à saisir pour les utilisateurs que toute autre représentation et devrait généralement nécessiter (au moins légèrement) moins de dactylographie. Si les dates peuvent être entrées dans différentes représentations textuelles, par exemple "2013", "2014-3", "2015-5-2", "30/07/2016 11p", "2016-07-31 18:15" , la précision ou l'exactitude peut également être déduite automatiquement de l'entrée.
L’exactitude ou la précision de [1] est également plus facile à convertir en un formulaire à transmettre aux utilisateurs, par exemple «2015-2015 avec l’exactitude mensuelle» en «mai 2015», par opposition à «13 mai 2015 2p, plus ou moins 13,5 jours». (notez que ce dernier ne peut de toute façon pas être représenté par [1]).
Les cordes
Dans la pratique, les valeurs de chaîne devront être converties en d'autres représentations pour interroger, trier ou comparer plusieurs valeurs. Ainsi, alors que tout langage naturel (humain) écrit est strictement plus expressif que [1], [2], [3] ou [5], nous n'avons pas encore les moyens de gérer beaucoup plus que des représentations ou des formats de texte standard. Compte tenu de cela, c'est probablement la représentation la moins utile en soi .
L'un des avantages de cette représentation est que les valeurs doivent, dans la pratique, être présentées aux utilisateurs tels quels et ne pas nécessiter de transformation pour être facilement compréhensibles.
Distributions de probabilité
Les distributions de probabilité généralisent les représentations d'intervalle uniforme [1], [2], [3] et (sans doute) sont équivalentes à la représentation (générale) sous forme de chaîne [4].
L'un des avantages des distributions de probabilités par rapport aux chaînes est que les premières sont sans ambiguïté.
[5-1] conviendrait pour des valeurs qui (le plus souvent) sont conformes à une distribution existante, par exemple une valeur date-heure générée par un appareil pour lequel les mesures sont connues (ou supposées) se conformer à une distribution spécifique.
[5-2] est probablement le meilleur moyen (un peu) pratique de représenter de manière compacte des valeurs arbitraires de type "date floue". Bien sûr, la calculabilité des distributions de probabilité spécifiques utilisées est importante et il existe certainement des problèmes intéressants (et peut-être impossibles) à résoudre lors de l'interrogation, du tri ou de la comparaison de valeurs différentes, mais la plupart de ces problèmes sont probablement déjà connus ou résolus quelque part dans le système existant. dans la littérature mathématique et statistique, il s’agit donc d’une représentation extrêmement générale et non ambiguë.
la source
J'aime beaucoup la solution de James Anderson - La délimitation précise des dates est le moyen d'obtenir la structure de requête la plus flexible. Une autre façon de réaliser la même chose consiste à utiliser un début, une fin ou même un centre
date
plus uninterval
(disponible au moins dans PostgreSQL , Oracle et SQLAlchemy ).la source
Dans votre cas, vous n'avez besoin que de l'année, du mois et du jour. L'année et le mois sont obligatoires, le jour est facultatif. J'utiliserais quelque chose comme ça:
De plus, vous pouvez toujours utiliser les index très efficacement. Le (minuscule = moins, les queires deviennent un peu plus "compliqués" (plus longs).
la source
1978-??-31
?Je voudrais simplement stocker l'heure exacte pour les dates normales et rendre la partie heure de la date floue générique comme 00:00:00. Je voudrais ensuite faire toutes les dates floues le 1er du mois.
Lorsque vous interrogez, vous
Il existe de meilleures solutions que cela, mais je déteste personnellement les métadonnées (données relatives à mes données). Il a juste l'habitude de perdre le contrôle après un certain temps.
la source