-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extend max year from 4000 to 9999 in timestamps
Probleme detecte par Nicolas: - les dates ou timestamps avec annee 9999 ne sont pas reconnus comme format valide, par le detecteur de format - c'est normal: la limite dans Khiops 10.1 est l'an 4000, depuis la prise en compte des timezone dans les timestamps Solution fonctionnelle: - etendre a nouveau la limite des annees a 9999 - en diminuant legerement la precsiiobn des fraction de scondes (et 1/10000 a 1/1000) - meilleurs compromis utilisateur - moins d'anomalies dans la lecture de bases existantes - le 9999 est souvent utilise pour recoder les valeurs manquantes - il est important de detecter correctement les format timestamps dans ce cas - tout en gardant un precision de une millisconde - perdre le dixieme de millisecondes est peu important - si on veut passer a plus fin, ce sera la micro-secondes - besoin peu frequent - necessitera de toute facon a un autre format (variable numerique directement, probablement) Impact dans la documentation utilisateur, a prendre en compte Implementation existante - les classe Date et Time etait chacune codee avec un int, et timestamp avec un longint concatenant les deux - ce n'est plus possible, car il faut recuperer 2 bits de Time pour les utiliser dans Date Nouveau type interne de type union: DataTime - type interne, utilise par toutes les classe Date, Time, Timestamp, TimestampTZ - defini une union permetant des manipulation simple de tout ou partie des champs - lBytes: longint, compatible avec KWValue, pour acceder a tout en une seule operation - parts: bit fields pour acces a la sous-partie Data, Timezone, Time - fields: bit fields pour acces a tous les champs elementaires - attention, contrainte d'alignement d'une struct bit fields sur des int - les champs de la timezone etant a cheval sur les deux entiers ont du etre decoupes - accesseurs specifiques uniquement pour les champs concernes de la timezone - bascule vers la limite a 9999 pour les annees - ajout de 2 bits pour les anneee, en en recupernt 2 des fractions de secondes - methode Test, permettant de verifier les contraintes internes de l'union Utilisation systematique de l'union DateTime dans les type Date, Time, Timestamp, TimestampTZ - ok avec tous les tests unitaires - validation sur LearningTest\TestKhiops\Rules\DateTimeRules - tests complets sur LearningTest
- Loading branch information
1 parent
8fe164e
commit ea3466b
Showing
14 changed files
with
427 additions
and
203 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// Copyright (c) 2023 Orange. All rights reserved. | ||
// This software is distributed under the BSD 3-Clause-clear License, the text of which is available | ||
// at https://spdx.org/licenses/BSD-3-Clause-Clear.html or see the "LICENSE" file for more details. | ||
|
||
#include "KWDateTime.h" | ||
|
||
void DateTime::Test() | ||
{ | ||
DateTime dtDateTimeValue; | ||
DateTime dtForbiddenValue; | ||
DateTime dtDateValue; | ||
DateTime dtTimezoneValue; | ||
DateTime dtTimeValue; | ||
int i; | ||
|
||
// Taille de la structures | ||
cout << "DateTime: " << sizeof(DateTime) << "\n"; | ||
assert(sizeof(DateTime) == sizeof(longint)); | ||
|
||
// Nombre de digits des fractions de scondes | ||
cout << "Frac seconds digits: " << nFracSecondsDigitNumber << "\n"; | ||
cout << "Frac seconds max: " << nMaxFracSeconds << "\n"; | ||
assert(10 * (nMaxFracSeconds / 10) == nMaxFracSeconds); | ||
assert(int(pow(10, nFracSecondsDigitNumber)) == nMaxFracSeconds), | ||
|
||
// Contenu a 0 | ||
dtDateTimeValue.lBytes = 0; | ||
cout << "\nDateTime invalid value\n", dtDateTimeValue.WriteInternalFields(cout); | ||
|
||
// Contenu interdit | ||
dtForbiddenValue.lBytes = lForbiddenValue; | ||
cout << "\nDateTime forbidden value\n"; | ||
dtForbiddenValue.WriteInternalFields(cout); | ||
|
||
// Test de mis a jour partielle de la Date | ||
dtDateValue.lBytes = dtForbiddenValue.lBytes; | ||
dtDateValue.parts.nTime = 0; | ||
dtDateValue.SetTimeZone(0); | ||
cout << "\nDate only forbidden value\n"; | ||
dtDateValue.WriteInternalFields(cout); | ||
|
||
// Test de mis a jour partielle de la Timezone | ||
dtTimezoneValue.lBytes = dtForbiddenValue.lBytes; | ||
dtTimezoneValue.parts.nDate = 0; | ||
dtTimezoneValue.parts.nTime = 0; | ||
cout << "\nTimezone only forbidden value\n"; | ||
dtTimezoneValue.WriteInternalFields(cout); | ||
|
||
// Test de mis a jour partielle de la Time | ||
dtTimeValue.lBytes = dtForbiddenValue.lBytes; | ||
dtTimeValue.parts.nDate = 0; | ||
dtTimeValue.SetTimeZone(0); | ||
cout << "\nTime only forbidden value\n"; | ||
dtTimeValue.WriteInternalFields(cout); | ||
|
||
// Verifications avancees | ||
assert((dtDateValue.lBytes | dtTimezoneValue.lBytes | dtTimeValue.lBytes) == dtForbiddenValue.lBytes); | ||
assert((dtDateValue.lBytes & dtTimeValue.lBytes) == 0); | ||
assert((dtDateValue.lBytes & dtTimezoneValue.lBytes) == 0); | ||
assert((dtTimezoneValue.lBytes & dtTimeValue.lBytes) == 0); | ||
|
||
// Reconstruction | ||
dtDateTimeValue.parts.nDate = dtDateValue.parts.nDate; | ||
dtDateTimeValue.SetTimeZone(dtTimezoneValue.GetTimeZone()); | ||
dtDateTimeValue.parts.nTime = dtTimeValue.parts.nTime; | ||
cout << "\nReconstructed forbidden value\n"; | ||
dtDateTimeValue.WriteInternalFields(cout); | ||
assert(dtDateTimeValue.lBytes == dtForbiddenValue.lBytes); | ||
|
||
// Test de la partie annees | ||
cout << "\nTimezone years\n"; | ||
dtDateTimeValue.lBytes = 0; | ||
for (i = 0; i < nMaxYear; i++) | ||
{ | ||
dtDateTimeValue.fields.nYear = i; | ||
if (i % 1000 == 0) | ||
cout << "." << dtDateTimeValue.fields.nYear; | ||
assert(dtDateTimeValue.fields.nYear == (unsigned int)i); | ||
} | ||
cout << "\n"; | ||
|
||
// Test de la partie a la frontiere de minutes de timestamp | ||
cout << "\nTimezone minutes\n"; | ||
dtDateTimeValue.lBytes = 0; | ||
for (i = 0; i < 60; i++) | ||
{ | ||
dtDateTimeValue.SetTimeZoneMinute(i); | ||
cout << "." << dtDateTimeValue.GetTimeZoneMinute(); | ||
assert(dtDateTimeValue.GetTimeZoneMinute() == i); | ||
assert(dtDateTimeValue.fields.nTimeZoneSign == 0); | ||
assert(dtDateTimeValue.fields.nTimeZoneHour == 0); | ||
assert(dtDateTimeValue.parts.nDate == 0); | ||
assert(dtDateTimeValue.parts.nTime == 0); | ||
} | ||
cout << "\n"; | ||
|
||
// Test de la partie des fractions de secondes | ||
cout << "\nTimezone frac seconds\n"; | ||
dtDateTimeValue.lBytes = 0; | ||
for (i = 0; i < nMaxFracSeconds; i++) | ||
{ | ||
dtDateTimeValue.fields.nFrac = i; | ||
if (i % 100 == 0) | ||
cout << "." << dtDateTimeValue.fields.nFrac; | ||
assert(dtDateTimeValue.fields.nFrac == (unsigned int)i); | ||
} | ||
cout << "\n"; | ||
} | ||
|
||
void DateTime::WriteInternalFields(ostream& ost) const | ||
{ | ||
cout << "dateTimeValue fields\n"; | ||
cout << "\tlDateTime bytes: " << lBytes << "\n"; | ||
cout << "\tDateTime parts: ((" << parts.nDate << "," << GetTimeZone() << "), " << parts.nTime << ")\n"; | ||
cout << "\tDateTime fields: ((" << fields.nYear << "," << fields.nMonth << "," << fields.nDay << " [" | ||
<< fields.nTimeZoneSign << ", " << fields.nTimeZoneHour << ", " << GetTimeZoneMinute() << "])," | ||
<< fields.nHour << "," << fields.nMinute << "," << fields.nSecond << "," << fields.nFrac << ")\n"; | ||
} |
Oops, something went wrong.