source: Sophya/trunk/SophyaLib/NTools/dates.cc@ 1837

Last change on this file since 1837 was 241, checked in by ansari, 26 years ago

ppersist + pexc

File size: 19.4 KB
Line 
1#include "machdefs.h"
2#include <stdlib.h>
3#include <string.h>
4#include <stdio.h>
5#include <iostream.h>
6#include <time.h>
7#include <ctype.h>
8#include <math.h>
9#include "perrors.h"
10#include "dates.h"
11
12//++
13// Class TimeZone
14// Lib Outils++
15// include dates.h
16//
17// Classe de fuseau horaire. Permet les conversion
18// GMT <-> temps local, en gérant les changements
19// d'heure hiver-été.
20// Deux fuseaux horaires sont prédéfinis, "France"
21// et "Chili".
22//--
23
24TimeZone* gTimeZone = NULL;
25
26//++
27// Titre Constructeurs
28//--
29
30//++
31TimeZone::TimeZone()
32//
33// Constructeur par défaut. Il lit la variable
34// d'environnement ACQ_TZ pour choisir le fuseau
35// horaire. Si la variable n'est pas définie, nous
36// sommes en France...
37//--
38{
39 char* p = getenv("ACQ_TZ");
40#if defined(__DECCXX) || defined(__KCC__) || defined(__aCC__)
41 if (!p) p = const_cast<char *>("France");
42#else
43 if (!p) p = "France";
44#endif
45 SetZone(p);
46 END_CONSTRUCTOR;
47}
48
49//++
50TimeZone::TimeZone(const char* nom)
51//
52// Constructeur à partir du nom d'un fuseau horaire.
53//--
54{
55 SetZone(nom);
56 END_CONSTRUCTOR
57}
58
59//++
60void TimeZone::SetZone(const char* nom)
61//
62// Choisit un fuseau horaire. Contient la définition
63// du fuseau "France" (GMT+1, DST : dernier dimanche
64// de mars - dernier dimanche de septembre, c'est-à-dire
65// pré-gouvernement Juppé), et Chili (GMT-4, DST :
66// deuxième dimanche d'octobre - deuxième dimanche de mars).
67//--
68{
69 if (!strcmp(nom,"France")) {
70 strcpy(code,"MET");
71 strcpy(name,nom);
72 gmtOffset = 1;
73 hasDST = 1;
74 dstByWeekDay = 1;
75 dstStartDay = Date::jour_Dimanche; // dernier dimanche de mars
76 dstStartNum = -1;
77 dstStartMonth = Date::mois_Mars;
78 dstStopDay = Date::jour_Dimanche; // dernier dimanche de septembre
79 dstStopNum = -1;
80 dstStopMonth = Date::mois_Septembre;
81 dstOffset = 1;
82 } else if (!strcmp(nom,"Chili") || !strcmp(nom,"Chile")) {
83// # Chile has 2nd Sunday in October to 2nd Sunday in March DST
84 strcpy(code,"CST");
85 strcpy(name,"Chili");
86 gmtOffset = -4;
87 hasDST = 1;
88 dstByWeekDay = 1;
89 dstStartDay = Date::jour_Dimanche; // 2e dimanche d'octobre
90 dstStartNum = 2;
91 dstStartMonth = Date::mois_Octobre;
92 dstStopDay = Date::jour_Dimanche; // 2e dimanche de mars
93 dstStopNum = 2;
94 dstStopMonth = Date::mois_Mars;
95 dstOffset = 1;
96 } else THROW(parmErr);
97}
98
99//++
100int TimeZone::IsDst(const Date& date)
101//
102// Teste si une date est en heure d'été (DST).
103//--
104{
105 Date dt = date;
106 if (dt.MM < 0 || dt.JJ < 0) THROW(inconsistentErr)
107 if (dt.hh >= 0) dt += gmtOffset/24.0; // date "fictive" en local d'hiver
108 else dt.ss = dt.hh = dt.mm = 0; // minuit local si heure indeterminee
109 // On est en-dehors des mois frontiere ?
110 if (dstStartMonth < dstStopMonth) {
111 if (dt.MM < dstStartMonth) return 0;
112 if (dt.MM > dstStopMonth) return 0;
113 if (dt.MM > dstStartMonth && dt.MM < dstStopMonth) return 1;
114 } else {
115 if (dt.MM < dstStopMonth) return 1;
116 if (dt.MM > dstStartMonth) return 1;
117 if (dt.MM > dstStopMonth && dt.MM < dstStartMonth) return 0;
118 }
119
120 // Nous sommes dans un mois-frontiere
121 DBASSERT(dt.MM == dstStopMonth || dt.MM == dstStartMonth);
122
123 if (dt.MM == dstStartMonth) {
124 int jour;
125 if (dstByWeekDay) jour = Date::NthMonthDay(dstStartNum,dstStartDay, dt.MM, dt.AA);
126 else jour = (dstStartNum>0) ? dstStartNum : Date::MonthDays(dt.MM, dt.AA)+1-dstStartNum;
127 if (dt.JJ < jour) return 0;
128 if (dt.JJ > jour) return 1;
129 if (dt.hh > 1) return 1;
130 return 0;
131 } else {
132 int jour;
133 if (dstByWeekDay) jour = Date::NthMonthDay(dstStopNum,dstStopDay, dt.MM, dt.AA);
134 else jour = (dstStopNum>0) ? dstStopNum : Date::MonthDays(dt.MM, dt.AA)+1-dstStopNum;
135 if (dt.JJ < jour) return 1;
136 if (dt.JJ > jour) return 0;
137 if (dt.hh < 2) return 0;
138 return 1;
139 }
140}
141
142//++
143int TimeZone::GetOffset(const Date& date)
144//
145// Retourne la difference TL-GMT pour une date donnée,
146// en tenant compte de l'heure d'été éventuelle.
147//--
148{
149 return IsDst(date) ? gmtOffset+dstOffset : gmtOffset;
150}
151
152//++
153// Class Date
154// Lib Outils++
155// include dates.h
156//
157// Une classe date comme une autre, avec gestion
158// temps local / GMT / changement d'heure, et un
159// jour temps sidéral.
160//
161// Une partie de la date (heure, jour...) peut être
162// indéterminée. Les comparaisons sont alors faites
163// de façon astucieuse...
164//
165// La date peut être déterminée de minuit à minuit
166// ou de midi à midi (nuit d'observation). Logique
167// complexe et peut-être foireuse pour passer de
168// l'un à l'autre, mais pas encore d'ennuis pour le
169// moment... Une date-nuit doit avoir une heure
170// indéterminée.
171//
172// Il faut que Date::gTimeZone soit initialisé pour
173// éviter des gros pépins, mais PeidaInit() le fait.
174//
175// An 2000 : Lorsqu'on gère des dates sous forme de chaine :
176// * En sortie, 2 caractères pour l'année entre 1950 et 1999
177// et 4 caractères sinon
178// * En entrée, si AA<100 on ajoute 1900.
179//--
180
181//++
182short Date::MonthDays(short mois, short annee)
183//
184// Retourne le nombre de jours dans le mois
185//--
186{
187 if (mois<1 || mois>12) THROW(inconsistentErr);
188
189 switch(mois) {
190 case mois_Janvier:
191 case mois_Mars:
192 case mois_Mai:
193 case mois_Juillet:
194 case mois_Aout:
195 case mois_Octobre:
196 case mois_Decembre:
197 return 31;
198 case mois_Avril:
199 case mois_Juin:
200 case mois_Septembre:
201 case mois_Novembre:
202 return 30;
203 case mois_Fevrier:
204 return (((annee%4 == 0) && (annee%100 != 0)) || (annee%400 == 0)) ? 29 : 28;
205 }
206 return -1;
207}
208
209//++
210short Date::YearDays(short annee)
211//
212// Retourne le nombre de jours dans l'année
213//--
214{
215 return (((annee%4 == 0) && (annee%100 != 0)) || (annee%400 == 0)) ? 366 : 365;
216}
217
218//++
219bool Date::UndetDate() const
220//
221// Retourne true si une partie de la date (jour
222// ou mois ou année) est indéterminée.
223//--
224{
225 return ((AA == -1) || (MM == -1) || (JJ == -1));
226}
227
228//++
229bool Date::AllUndetDate() const
230//
231// Retourne true si toute la date (jour
232// et mois et année) est indéterminée.
233//--
234{
235 return ((AA == -1) && (MM == -1) && (JJ == -1));
236}
237
238//++
239bool Date::UndetTime() const
240//
241// Retourne true si une partie de l'heure (heure
242// ou minutes ou secondes) est indéterminée.
243//--
244{
245 return ((hh == -1) || (mm == -1) || (ss == -1));
246}
247
248//++
249bool Date::AllUndetTime() const
250//
251// Retourne true si toute l'heure (heure
252// et minutes et secondes) est indéterminée.
253//--
254{
255 return ((hh == -1) && (mm == -1) && (ss == -1));
256}
257
258//Date::operator double() const
259
260//++
261double
262Date::GetDays() const
263//
264// Jours écoulés depuis le 0 janvier 1901 0h TU
265//--
266{
267 if (UndetTime() && !AllUndetTime()) THROW(inconsistentErr);
268 if (UndetDate() && !AllUndetDate()) THROW(inconsistentErr);
269 double t=0;
270 if (!UndetDate()) {
271 int nban = AA-1901;
272 if (nban >= 0)
273 t = nban*365 + (nban/4) - (nban/100) + ((nban+300)/400);
274 else
275 t = nban*365 + (nban/4) - (nban/100) + ((nban-100)/400);
276 for (int i=1; i<MM; i++) t += Date::MonthDays(i,AA);
277 t += JJ;
278 }
279 if (!UndetTime()) t += hh/24.0 + mm/1440.0 + ss/86400.0;
280 else if (nuit) t += 0.5;
281 return t;
282}
283
284//++
285void Date::Set(double t)
286//
287// Jours écoulés depuis le 0 janvier 1901 0h TU
288//--
289{
290 t += 1/8640000.0;
291 int nban = int(floor((t/*-1*/) / 365.2425));
292 if (nban >= 0)
293 t -= nban*365 + ((nban)/4) - ((nban)/100) + ((nban+300)/400);
294 else
295 t -= nban*365 + ((nban)/4) - ((nban)/100) + ((nban-100)/400);
296
297 AA = 1901 + nban;
298 if (t > Date::YearDays(AA)+1) {
299 t -= Date::YearDays(AA);
300 AA++;
301 } else if (t<1) {
302 AA--;
303 t += Date::YearDays(AA);
304 }
305
306 MM = 1;
307 while (t > Date::MonthDays(MM,AA)+1) {
308 t -= Date::MonthDays(MM,AA);
309 MM++;
310 }
311
312 JJ = int(t);
313 t -= JJ;
314
315 t *= 24;
316 hh = int(t);
317
318 t = (t-hh)*60;
319 mm = int(t);
320
321 t = (t-mm)*60;
322 ss = t;
323
324 nuit = 0;
325}
326//++
327Date::Date()
328//
329// Constructeur. Prend l'heure courante...
330//--
331: timeZone(gTimeZone)
332{
333 time_t t = time(NULL);
334 struct tm* TM = gmtime(&t);
335
336 AA = TM->tm_year + 1900;
337 MM = TM->tm_mon+1;
338 JJ = TM->tm_mday;
339 hh = TM->tm_hour;
340 mm = TM->tm_min;
341 ss = TM->tm_sec;
342 nuit = 0;
343 END_CONSTRUCTOR
344}
345
346//++
347Date::Date(int J, int M, int A, int h, int m, double s)
348//
349// Constructeur simple.
350//--
351: JJ(J), MM(M), AA(A), hh(h), mm(m), ss(s), timeZone(gTimeZone), nuit(0)
352{
353 END_CONSTRUCTOR
354}
355
356//++
357Date::Date(double t)
358//
359// Constructeur à partir des
360// jours écoulés depuis le 0 janvier 1901 0h TU
361//
362//--
363: timeZone(gTimeZone)
364{
365 Set(t);
366 END_CONSTRUCTOR
367}
368
369//++
370void Date::SetTimeZone(TimeZone* tz)
371//
372// On change de fuseau horaire.
373//--
374{
375 timeZone = tz;
376}
377
378//++
379Date::Date(const char* date, const char* heure, int tOpt)
380//
381// Constructeur à partir de la date sous la forme
382// 'DD/MM/YYYY' 'HH/MM/SS', et tOpt est Date::kGMTTime
383// (par défaut) ou Date::kLocalTime.
384//
385// Tout ou partie de la date peut être indéterminée ('??').
386//--
387: timeZone(gTimeZone)
388{
389 Set(date,heure,tOpt);
390 END_CONSTRUCTOR
391}
392
393//++
394Date::Date(string const& date, string const& heure, int tOpt)
395//
396// Constructeur à partir de la date sous la forme
397// 'DD/MM/YYYY' 'HH/MM/SS', et tOpt est Date::kGMTTime
398// (par défaut) ou Date::kLocalTime.
399//
400// Tout ou partie de la date peut être indéterminée ('??').
401//--
402: timeZone(gTimeZone)
403{
404 Set(date,heure,tOpt);
405 END_CONSTRUCTOR
406}
407
408//++
409void Date::Set(string const& date, string const& heure, int tOpt)
410//
411// Positionne la date sous la forme
412// 'DD/MM/YYYY' 'HH/MM/SS', et tOpt est Date::kGMTTime
413// (par défaut) ou Date::kLocalTime.
414//
415// Tout ou partie de la date peut être indéterminée ('??').
416//--
417{
418 Set(date.c_str(), heure == "" ? (char*)NULL : heure.c_str(), tOpt);
419}
420
421//++
422void Date::Set(const char* date, const char* heure, int tOpt)
423//
424// Positionne la date sous la forme
425// 'DD/MM/YYYY' 'HH/MM/SS', et tOpt est Date::kGMTTime
426// (par défaut) ou Date::kLocalTime.
427//
428// Tout ou partie de la date peut être indéterminée ('??').
429//--
430{
431 nuit = 0;
432 if (date) {
433 if (strlen(date) >= 5) { // J(J)/M(M)/AA(AA), ?/?/?, combinaison
434 const char* p = date;
435 if (p[0] == '?' && (p[1] == '?' || p[1] == '/')) JJ = -1;
436 else {
437 if (!isdigit(p[0])) THROW(inconsistentErr);
438 if (!isdigit(p[1]) && p[1] != '/') THROW(inconsistentErr);
439 JJ = atoi(p);
440 if (JJ <= 0) THROW(inconsistentErr);
441 }
442
443 if (p[1] == '/') p += 2;
444 else if (p[2] == '/') p+= 3;
445 else THROW(inconsistentErr);
446
447 if (p[0] == '?' && (p[1] == '?' || p[1] == '/')) MM = -1;
448 else {
449 if (!isdigit(p[0])) THROW(inconsistentErr);
450 if (!isdigit(p[1]) && p[1] != '/') THROW(inconsistentErr);
451 MM = atoi(p);
452 if (MM <= 0 || MM >12) THROW(inconsistentErr);
453 }
454
455 if (p[1] == '/') p += 2;
456 else if (p[2] == '/') p+= 3;
457 else THROW(inconsistentErr);
458
459 if (p[0] == '?') AA = -1;
460 else {
461 if (!isdigit(p[0])) THROW(inconsistentErr);
462 if (!isdigit(p[1])) THROW(inconsistentErr);
463 AA = atoi(p);
464 if (AA < 100 && AA >= 0 && date[6] != '0') AA += 1900;
465 }
466
467 if (AA > 0 && MM > 0 && JJ > 0 && JJ > MonthDays(MM,AA)) THROW(inconsistentErr);
468
469 } else if (strlen(date)==4) { // Code EROS de date
470 if (date[0] == '?') AA = -1;
471 else {
472 if (!isdigit(date[0])) THROW(inconsistentErr);
473 AA = 1990 + date[0] - '0';
474 }
475
476 if (date[1] == '?') MM = -1;
477 else {
478 if (!isalpha(date[1])) THROW(inconsistentErr);
479 if (islower(date[1]))
480 MM = date[1] - 'a' + 1;
481 else
482 MM = date[1] - 'A' + 1;
483 if (MM<1 || MM>12) THROW(inconsistentErr);
484 }
485
486 if (date[2] == '?' && date[3] == '?') JJ = -1;
487 else {
488 if (!isdigit(date[2])) THROW(inconsistentErr);
489 if (!isdigit(date[3])) THROW(inconsistentErr);
490 JJ = atoi(date+2);
491 }
492
493 if (AA > 0 && MM > 0 && JJ > 0 && JJ > MonthDays(MM,AA)) THROW(inconsistentErr);
494 nuit = 1;
495 } else THROW(inconsistentErr); // Mauvaise longueur
496 } else { // Pas de date
497 JJ = MM = AA = -1;
498 }
499
500 if (heure) {
501 const char* p = heure;
502 if (p[0] == '?' && (p[1] == '?' || p[1] == ':')) hh = -1;
503 else {
504 if (!isdigit(p[0])) THROW(inconsistentErr);
505 if (!isdigit(p[1]) && p[1] != ':') THROW(inconsistentErr);
506 hh = atoi(p);
507 }
508
509 if (p[1] == ':') p += 2;
510 else if (p[2] == ':') p+= 3;
511 else THROW(inconsistentErr);
512
513 if (p[0] == '?' && (p[1] == '?' || p[1] == ':')) mm = -1;
514 else {
515 if (!isdigit(p[0])) THROW(inconsistentErr);
516 if (!isdigit(p[1]) && p[1] != '/') THROW(inconsistentErr);
517 mm = atoi(p);
518 }
519
520 if (p[1] == ':') p += 2;
521 else if (p[2] == ':') p+= 3;
522 else THROW(inconsistentErr);
523
524 if (p[0] == '?') ss = -1;
525 else {
526 if (!isdigit(p[0])) THROW(inconsistentErr);
527 ss = atoi(p);
528 }
529 } else {
530 ss = hh = mm = -1;
531 }
532
533 if (tOpt == kLocalTime) {
534 DBASSERT(timeZone != NULL);
535 operator -= (timeZone->gmtOffset/24.0);
536 if (timeZone->IsDst(*this))
537 operator -= (timeZone->dstOffset/24.0); // A VERIFIER SANS DOUTE INEXACT
538 }
539
540 if (nuit && !UndetTime() && hh < 12)
541 *this += 1;
542}
543
544//++
545void Date::GetDateStr(char* s, int tOpt) const
546//
547// Récupère la date sous la forme d'une chaîne 'DD/MM/YYYY'
548// en tOpt = Date::kGMTTime ou Date::kLocalTime.
549//--
550{
551 Date dt(*this);
552 if (tOpt == kLocalTime && !UndetTime()) {
553 DBASSERT(timeZone != NULL);
554 dt += timeZone->GetOffset(*this)/24.0;
555 }
556
557 if (dt.AA < 1950 || dt.AA > 1999)
558 sprintf(s, "%02d/%02d/%04d", dt.JJ, dt.MM, dt.AA);
559 else
560 sprintf(s, "%02d/%02d/%02d", dt.JJ, dt.MM, dt.AA-1900);
561
562 if (dt.JJ == -1)
563 s[0] = s[1] = '?';
564 if (dt.MM == -1)
565 s[3] = s[4] = '?';
566 if (dt.AA == -1) {
567 s[6] = s[7] = '?';
568 s[8] = '\0';
569 }
570}
571
572//++
573void Date::GetDateCode(char* s, int tOpt) const
574//
575// Code EROS de la date.
576//--
577{
578 Date dt(*this);
579 if (tOpt == kLocalTime && !UndetTime()) {
580 DBASSERT(timeZone != NULL);
581 dt += timeZone->GetOffset(*this)/24.0;
582 }
583
584 if (!dt.UndetTime() && dt.hh<12) dt -= 1;
585
586 if (dt.AA != -1) {
587 if (dt.AA < 1990 || dt.AA > 2016) THROW(inconsistentErr);
588 int i = dt.AA - 1990;
589 if (i<10)
590 s[0] = '0' + i;
591 else
592 s[0] = 'a' + i - 10;
593 } else
594 s[0] = '?';
595
596 if (dt.MM != -1)
597 s[1] = 'a' + dt.MM - 1;
598 else
599 s[1] = '?';
600
601 if (dt.JJ != -1)
602 sprintf(s+2, "%02d", dt.JJ);
603 else
604 s[2] = s[3] = '?';
605
606 s[4] = 0;
607}
608
609//++
610void Date::GetTimeStr(char* s, int tOpt) const
611//
612// Récupère l'heure sous la forme 'HH:MM:SS'
613//--
614{
615 Date dt(*this);
616 if (tOpt == kLocalTime) {
617 DBASSERT(timeZone != NULL);
618 dt += timeZone->GetOffset(*this)/24.0;
619 }
620
621 sprintf(s, "%02d:%02d:%02d", dt.hh, dt.mm, int(dt.ss));
622 if (dt.hh == -1)
623 s[0] = s[1] = '?';
624 if (dt.mm == -1)
625 s[3] = s[4] = '?';
626 if (dt.ss == -1)
627 s[6] = s[7] = '?';
628}
629
630//++
631void Date::GetSidTStr(char* s) const
632//
633// Récupèrera un jour le temps sidéral.
634//--
635{
636 strcpy(s,"TOBEDONE!!");
637}
638
639//++
640string Date::DateStr(int tOpt) const
641//
642// Récupère la date sous la forme d'une chaîne 'DD/MM/YYYY'
643// en tOpt = Date::kGMTTime ou Date::kLocalTime.
644//--
645{
646 char s[20];
647 GetDateStr(s,tOpt);
648 return s;
649}
650
651//++
652string Date::DateCode(int tOpt) const
653//
654// Code EROS de la date.
655//--
656{
657 char s[20];
658 GetDateCode(s,tOpt);
659 return s;
660}
661
662//++
663string Date::TimeStr(int tOpt) const
664//
665// Récupère l'heure sous la forme 'HH:MM:SS'
666//--
667{
668 char s[20];
669 GetTimeStr(s,tOpt);
670 return s;
671}
672
673//++
674string Date::SidTStr() const
675//
676// Récupèrera un jour le temps sidéral.
677//--
678{
679 char s[20];
680 GetSidTStr(s);
681 return s;
682}
683
684//++
685int Date::DayOfWeek(int tOpt) const
686//
687// Retourne le jour dans la semaine, 0-6
688// avec 0 = Date::jour_Lundi.
689//--
690{
691 double t = GetDays();
692 if (tOpt == kLocalTime && hh >=0) {
693 DBASSERT(timeZone != NULL);
694 t += timeZone->GetOffset(*this)/24.0;
695 }
696 int ndays = int(t); // nb de jours depuis 0 janvier 1901
697 ndays = (ndays + 1) % 7;
698 if (ndays<0) ndays += 7;
699 return ndays;
700}
701
702//++
703short Date::NthMonthDay(short i, short joursem, short mois, short annee)
704//
705// Retourne la date correspondant au ieme joursem dans le mois
706// correspondant (exemple, 2e dimanche de mars 1960).
707//--
708{
709 if (i>0) {
710 int jprem = Date(1, mois, annee, 0, 0, 0).DayOfWeek();
711 int d = (joursem - jprem);
712 if (d<0) d+=7;
713 return d + 1 + (i-1)*7;
714 } else {
715 int ider = MonthDays(mois, annee);
716 int jder = Date(ider, mois, annee, 0, 0, 0).DayOfWeek();
717 int d = (joursem - jder);
718 if (d>0) d-=7;
719 return d + ider + (i+1)*7;
720 }
721}
722
723//++
724Date& Date::operator += (double dt)
725//
726// dt en jours
727//--
728{
729 int u = UndetTime();
730 Set(GetDays()+dt);
731 if (u) ss = hh = mm = -1;
732 return *this;
733}
734
735//++
736Date& Date::operator -= (double dt)
737//
738// dt en jours
739//--
740{
741 int u = UndetTime();
742 Set(GetDays()-dt);
743 if (u) ss = hh = mm = -1;
744 return *this;
745}
746
747//++
748Date operator + (Date const& d, double dt)
749//
750//--
751{
752 Date a(d);
753 a += dt;
754 return a;
755}
756
757//++
758Date operator - (Date const& d, double dt)
759//
760//--
761{
762 Date a(d);
763 a -= dt;
764 return a;
765}
766
767//++
768double operator - (Date const& a, Date const& b)
769//
770// Résultat en jours
771//--
772{
773 if (a.UndetTime() != b.UndetTime()) THROW(inconsistentErr);
774 if (a.UndetDate() != b.UndetDate()) THROW(inconsistentErr);
775 return a.GetDays() - b.GetDays();
776}
777
778//++
779bool operator == (Date const& a, Date const& b)
780//
781// On n'a pas égalite dès que des éléments déterminés sont différents
782//--
783{
784 if (a.nuit && a.UndetTime() && !b.nuit && !b.UndetTime() && b.hh<12)
785 {Date d = a+1; d.nuit = 0; return d == b;}
786 else if (b.nuit && b.UndetTime() && !a.nuit && !a.UndetTime() && a.hh<12)
787 {Date d = b+1; d.nuit = 0; return a == d;}
788
789 if (a.AA != -1 && b.AA != -1 && a.AA != b.AA) return false;
790 if (a.MM != -1 && b.MM != -1 && a.MM != b.MM) return false;
791 if (a.JJ != -1 && b.JJ != -1 && a.JJ != b.JJ) return false;
792 if (a.hh != -1 && b.hh != -1 && a.hh != b.hh) return false;
793 if (a.mm != -1 && b.mm != -1 && a.mm != b.mm) return false;
794 if (a.ss != -1 && b.ss != -1 && a.ss != b.ss) return false;
795 return true;
796}
797
798//++
799bool operator != (Date const& a, Date const& b)
800//
801//--
802{
803 return !(a == b);
804}
805
806//++
807bool operator <= (Date const& a, Date const& b)
808//
809// Inégalité large. Pas de subtilités
810//--
811{
812 if (a.nuit && a.UndetTime() && !b.nuit && !b.UndetTime() && b.hh<12)
813 {Date d = a+1; d.nuit = 0; return d <= b;}
814 else if (b.nuit && b.UndetTime() && !a.nuit && !a.UndetTime() && a.hh<12)
815 {Date d = b+1; d.nuit = 0; return a <= d;}
816
817 if (a.AA != -1 && b.AA != -1) {
818 if (a.AA < b.AA) return true;
819 if (a.AA > b.AA) return false;
820 }
821 if (a.MM != -1 && b.MM != -1) {
822 if (a.MM < b.MM) return true;
823 if (a.MM > b.MM) return false;
824 }
825 if (a.JJ != -1 && b.JJ != -1) {
826 if (a.JJ < b.JJ) return true;
827 if (a.JJ > b.JJ) return false;
828 }
829 if (a.hh != -1 && b.hh != -1) {
830 if (a.hh < b.hh) return true;
831 if (a.hh > b.hh) return false;
832 }
833 if (a.mm != -1 && b.mm != -1) {
834 if (a.mm < b.mm) return true;
835 if (a.mm > b.mm) return false;
836 }
837 if (a.ss != -1 && b.ss != -1) {
838 if (a.ss < b.ss) return true;
839 if (a.ss > b.ss) return false;
840 }
841 return true;
842}
843
844//++
845bool operator < (Date const& a, Date const& b)
846//
847// Inégalité stricte, codée à partir de la large pour résoudre
848// sans cas particuliers les subtilités
849// 01/02/95 < ??/03/95 mais pas 01/02/95 < ??/02/95
850//--
851{
852 return (a <= b) && !(a == b);
853}
854
855//++
856bool operator >= (Date const& a, Date const& b)
857//
858//--
859{
860 return (b <= a);
861}
862
863//++
864bool operator > (Date const& a, Date const& b)
865//
866//--
867{
868 return (b < a);
869}
870
871//++
872ostream& operator << (ostream& s, Date const& d)
873//
874//--
875{
876 char x[20];
877 d.GetDateStr(x);
878 s << x << " ";
879 d.GetTimeStr(x);
880 s << x;
881 return s;
882}
Note: See TracBrowser for help on using the repository browser.