OOFILE  1.9
oof5.cpp
Go to the documentation of this file.
1 // COPYRIGHT 1994-1997 A.D. Software, All rights reserved
2 
3 // OOFILE database field-related classes
4 // date & time fields - see also oof3.cpp & oof4.cpp
5 
6 #include "oofpch_c.h" // for precompilation of core files
7 
8 #ifndef H_OOFIOS
9  #include "oofios.h"
10 #endif
11 #ifndef H_OOF2
12  #include "oof2.h"
13 #endif
14 #ifndef H_OOF4
15  #include "oof4.h"
16 #endif
17 #ifndef OOF_EXCEP
18  #include "oofexcep.h"
19 #endif
20 #ifndef H_OOFQUERY
21  #include "oofquery.h"
22 #endif
23 #ifndef H_OOFREL
24  #include "oofrel.h"
25 #endif
26 
27 #include <ctype.h>
28 #include <time.h> // for dbDate stuff
29 
30 #ifdef OOF_MEM_DEBUG_LAST_INCLUDE
31  #include OOF_MEM_DEBUG_LAST_INCLUDE
32 #endif
33 
34 #ifndef OOF_NO_STDLIB
35  #ifndef std
36  using namespace std;
37  #endif
38 #endif
39 
40 // token maps define the order in which we search for tokens
41 // and should really be sorted in decreasing order of being used
42 // by typical users, except this whole tokenising scheme is probably
43 // going to be rewritten
44 
45 // define static variables
50 
51 unsigned short dbDate::sNextCenturyThreshold = 1970;
52 unsigned short dbDate::sPrevCenturyThreshold = 2070;
53 
57 
58 
59 // gross c stuff
60 // eMIN must come before eM or the parser confuses one for the other
66  eACT,eDEA};
67 
68 // must be within the 20th Century (19xx)
69 // AD 980504 I don't understand the above comment. AFAIK the only restriction is that it must
70 // be within about 130 years of the upper date you wish to record, unless there's a weak algorithm
71 unsigned int dbDateTime::sBaseYear = 1970;
72 
73 #define NUMTOKENS 46
74 #define MAXTOKENS 50
75 #define MAXLINELEN 200
76 
77 // token matching strings and lengths - in the same order as the OOF_TOKENTYPE enums defined in oof4.h
78 
79 static char *vocab[NUMTOKENS]={"DDDD", "DDD", "DDTH", "DD", "DAYNAME", "DAY", "MMMM", "MMM","MM",
80  "MONTH", "MON", "YYYY", "YY", "YEAR",
81  "dddd", "ddd", "ddth", "dayname", "day", "mmmm", "mmm", "month", "mon",
82  "Dddd", "Ddd", "Dayname", "Day", "D", "Mmmm", "Mmm", "Month", "Mon", "M",
83  "HH", "hh", "MIN", "SEC", "PM", "Pm", "pm",
84  "#", "Z", ".", ",", "<", ">"};
85 
86 static short vlen[NUMTOKENS]={4,3,4,2,7,3,4,3,2,
87  5,3,4,2,4,
88  4,3,4,7,3,4,3,5,3,
89  4,3,7,3,1,4,3,5,3,1,
90  2,2,3,3,2,2,2,
91  1,1,1,1,1,1};
92 
93 // end gross c stuff
94 
95 // global to source file oof4.cpp (used by dbDateTime,dbTime,and dbFullDateTime)
96 
97 const unsigned long kMilliSecondsInDay = 24*60*60*1000;
98 const unsigned long kSecondsInDay = 24*60*60;
99 const unsigned long kSecondsInHour = 60*60;
100 const unsigned long kSecondsInMinute = 60;
101 
102 
103 bool
104 skipTillDigitAmPm( istream& is, hourT& hourMod, char fieldSep, char recSep)
105 {
106  char ch, nextch;
107 
108  while( is.good() ) // not end of line
109  {
110  ch = is.peek();
111  if ((ch==fieldSep) || (ch==recSep)) {
112  return false; // early exit - empty line
113  }
114  if( (ch>='0') && (ch<='9') ) { // digit
115  return true;
116  }
117  else
118  {
119  if( (toupper(ch)=='P') || (toupper(ch)=='A') )
120  {
121  is >> ch;
122  nextch = is.peek();
123  if( toupper(nextch)=='M' ) // "PM" or "AM"
124  {
125  if( toupper(ch)=='P' )
126  hourMod = pm_hour;
127  else
128  hourMod = am_hour;
129  }
130  }
131  }
132  is >> ch; // skip the char
133  }
134  return false;
135 }
136 
137 
138 // -------------------------------------------------------
139 // d b N u m e r i c F i e l d
140 // -------------------------------------------------------
141 TOKEN
142 dbNumericField::get_token(const char **s, const OOF_TOKENTYPE *m, unsigned int len)
143 /* Takes a string handle and checks if the current item is in the */
144 /* vocabulary and returns a token number of that vocab item.. It */
145 /* also moves the string along past that token */
146 {
147  TOKEN retval;
148  const OOF_TOKENTYPE *map;
149 
150  map = m;
151 
152  if (isdigit(**s))
153  {
154  unsigned int num;
155 
156  sscanf(*s,"%i",&num);
157  retval.token=eNUM;
158  retval.value=num;
159  for((*s)++;(isdigit(**s)||(**s=='x'));(*s)++)
160  ;
161  } else {
162  unsigned int i;
163 
164  for(i=0;i<len;i++) // the number of tokens in the subset
165  {
166  if (strncmp(*s,vocab[map[i]],vlen[map[i]])==0)
167  {
168  *s+=vlen[map[i]];
169  retval.token=map[i]; // using mapping table to match positions
170 // retval.token=(OOF_TOKENTYPE)i;
171  return(retval);
172  }
173  }
174  retval.token=eOTHER;
175  for(i=0;**s!='\0';)
176  {
177  retval.s[i++]=**s;
178  (*s)++;
179  for(unsigned int j=0;j<len;j++)
180  if (strncmp(*s,vocab[map[j]],vlen[map[j]])==0){
181  retval.s[i]='\0';
182  return(retval);
183  }
184  assert(i<SLEN-1);
185  }
186  retval.s[i]='\0';
187  }
188  return(retval);
189 }
190 
191 
192 void
193 dbNumericField::parseMask(const char *s, TOKEN* r, const OOF_TOKENTYPE *map, unsigned int len)
194 {
195  short index=0;
196  const char *stringStart;
197  stringStart = s;
198  bool haveACT = false;
199  while((*s!='\0')&&(index<MAXTOKENS-1)) {
200  r[index]=get_token(&s,map,len);
201  /* At this point we wish to enforce the following behaviour:
202  If an ACT token is found, everything found before it is considered as
203  the string equivalent only. If a DEA token is found, everything after
204  it is considered as string equivalent only */
205  if (r[index].token== eACT)
206  haveACT = true;
207  if (index && (r[index].token== eACT)) { // ACT found, but not the first token
208  index = 0; // reset to the start
209  r[index].token = eOTHER; // make the first token an OTHER
210  strncpy(r[index].s,stringStart,(s-stringStart-1)); // copy everything found so far into first token
211  *(r[index].s+(s-stringStart-1)) ='\0'; // terminate the new string
212  r[++index].token = eACT;
213  index++;
214  continue;
215  }
216  else
217  if (haveACT&&(*s!='\0')&&(r[index].token == eDEA)) { // DEA found, and there is more string to come
218  r[++index].token = eOTHER;
219  strcpy(r[index].s,s);
220  index++;
221  break; // we're finished now
222  }
223  index++;
224  }
225  r[index].token=eEOT; // Just in Case
226 }
227 
228 
229 // -------------------------------------------------------
230 // d b D a t e
231 // -------------------------------------------------------
232 // prototype private func
233 void skipStreamPattern(istream&, const char *);
234 
235 dbDate::dbDate(const OOF_IndexOptions indexOptions) :
236  dbNumericField(indexOptions)
237 {
239 }
240 
241 
242 dbDate::dbDate(const char *fieldName) :
243  dbNumericField(fieldName)
244 {
246 }
247 
248 
249 dbDate::dbDate(const char *fieldName, const OOF_IndexOptions indexOptions) :
250  dbNumericField(fieldName, indexOptions)
251 {
253 }
254 
255 
257  dbNumericField(k)
258 {
260 }
261 
262 
263 dbDate::dbDate(const dbDate& rhs) :
264  dbNumericField(rhs)
265 {}
266 
267 
269 {
270 }
271 
272 
273 dbField*
275 {
276  return new dbDate(*this);
277 }
278 
279 
280 
281 
282 
283 dbDate&
284 dbDate::calculateWith(dbDateCalculator* adoptedCalculator, bool useOnlyForDefaults)
285 {
286  CalculateWith(adoptedCalculator, useOnlyForDefaults);
287  return *this;
288 }
289 
290 
291 void
293 {
294  assert(mCalculator);
295  setDate( calculator()->calc(this) );
296 }
297 
298 
299 unsigned long
301 {
302  return sizeof(unsigned long);
303 }
304 
305 
306 void
308 {
309  if (srcField->fieldType()==dateField)
310  *this = *(dbDate*)srcField; // safe downcast
311 #ifdef OOF_DEBUG
312  else
313  dbConnect::raise(stringstream() << flush << "wrong field type passed in to dbDate::copyValueFrom, copying to " << fieldName() << " from " << srcField->fieldName());
314 #endif
315 }
316 
317 
318 void
320 {
321  if (srcField->fieldType()==dateField) {
322  unsigned long rhs = *(dbDate*)srcField; // safe downcast
323  if (value() != rhs)
324  this->setDate(rhs);
325  }
326 #ifdef OOF_DEBUG
327  else
328  dbConnect::raise(stringstream() << flush << "wrong field type passed in to dbDate::copyValueFrom, copying to " << fieldName() << " from " << srcField->fieldName());
329 #endif
330 }
331 
332 
335 {
336  return dateField;
337 }
338 
339 
342 {
343  return uLongField;
344 }
345 
346 
347 void
348 dbDate::extract(ostream& os) const
349 {
350  const unsigned long binDate = (long)*this;
351  if (binDate) {
352  unsigned short day, month, year;
353  long2ymd(binDate, year, month, day);
354  if (mFormatMask.length())
355  ymd2Stream(mFormatMask, year, month, day, os);
356  else
357  ymd2Stream(year, month, day, os);
358  }
359 }
360 
361 
362 bool
363 dbDate::insert(istream& is, char fieldSep, char recSep)
364 {
365  // is the stream good?
366  if (!is.good())
367  return false;
368  // read in the date
369  unsigned short y,m,d;
370  istream2ymd(is,y,m,d,fieldSep,recSep,sDefaultDateOrder);
371  // read in a potential field/record separator
372  const char c = is.peek();
373  bool hitEndOfField = false;
374  if ((c==fieldSep) || (c==recSep))
375  hitEndOfField = true;
376  if (hitEndOfField)
377  setDate(y,m,d);
378  return hitEndOfField;
379 }
380 
381 
382 ostream&
383 dbDate::today(ostream& os)
384 {
385  unsigned short day, month, year;
386  currentDate2ymd(year, month, day);
387  return ymd2Stream(year, month, day, os);
388 }
389 
390 
391 ostream&
392 dbDate::ymd2Stream(unsigned short year, unsigned short month, unsigned short day, ostream& os)
393 {
394  switch (sDefaultDateOrder) {
395  case orderYMD :
396  os << year << "/" << month << "/" << day;
397  break;
398 
399  case orderDMY :
400  os << day << "/" << month << "/" << year;
401  break;
402 
403  case orderMDY :
404  os << month << "/" << day << "/" << year;
405  break;
406  }
407  return os;
408 }
409 
410 
411 
412 
413 ostream&
414 dbDate::ymd2Stream(const char* mask, unsigned short year, unsigned short month, unsigned short day, ostream& os)
415 {
416  if(checkDate(year,month,day)) {
417  // parse the mask
418  TOKEN maskbits[MAXTOKENS]; // temporary !!!
420 
421  char somechars[10]; // to take a possible month name
422 
423  for(int index=0;maskbits[index].token!=eEOT;index++) {
424  switch (maskbits[index].token) {
425  case eD :
426  // put day number as string into stream
427  os << day;
428  break;
429  case eDD :
430  // put day number as string into stream, padded with zeros
431  if (day < 10)
432  os << '0'; // pad with zeros
433  os << day;
434  break;
435  case eDDD : case eDAY :
436  // put month name as TLA into stream
437  ymd2dayname(year, month, day,somechars,true,true);
438  os << somechars;
439  break;
440  case eDDDD :case eDAYNAME :
441  // put month as string into stream
442  ymd2dayname(year, month, day,somechars,false,true);
443  os << somechars;
444  break;
445  case eDdd : case eDay :
446  // put month name as TLA into stream
447  ymd2dayname(year, month, day,somechars);
448  os << somechars;
449  break;
450  case eDddd : case eDayname :
451  // put month as string into stream
452  ymd2dayname(year, month, day,somechars,false);
453  os << somechars;
454  break;
455  case eddd : case eday :
456  // put month name as TLA into stream
457  ymd2dayname(year, month, day,somechars);
458  somechars[0]=tolower(somechars[0]);
459  os << somechars;
460  break;
461  case edddd : case edayname :
462  // put month as string into stream
463  ymd2dayname(year, month, day,somechars,false);
464  somechars[0]=tolower(somechars[0]);
465  os << somechars;
466  break;
467  case eM :
468  // put month number as string into stream
469  os << month;
470  break;
471  case eMM :
472  // put month number as string into stream, padded with zeros
473  if (month < 10)
474  os << '0'; // pad with zeros
475  os << month;
476  break;
477  case eMMM : case eMON :
478  // put month name as TLA into stream
479  month2str(month,somechars,true,true);
480  os << somechars;
481  break;
482  case eMMMM : case eMONTH :
483  // put month as string into stream
484  month2str(month,somechars,false,true);
485  os << somechars;
486  break;
487  case eMmm : case eMon :
488  // put month name as TLA into stream
489  month2str(month,somechars);
490  os << somechars;
491  break;
492  case eMmmm : case eMonth :
493  // put month as string into stream
494  month2str(month,somechars,false);
495  os << somechars;
496  break;
497  case emmm : case emon :
498  // put month name as TLA into stream
499  month2str(month,somechars);
500  somechars[0]=tolower(somechars[0]);
501  os << somechars;
502  break;
503  case emmmm : case ezmonth :
504  // put month as string into stream
505  month2str(month,somechars,false);
506  somechars[0]=tolower(somechars[0]);
507  os << somechars;
508  break;
509  case eYY :
510  // put short form year as string into stream
511  os << (year%100);
512  break;
513  case eYYYY : case eYEAR :
514  // put year as string into stream
515  os << year;
516  break;
517  case eDDTH :
518  ddth(day,somechars,true);
519  os << somechars;
520  break;
521  case ezddth :
522  ddth(day,somechars);
523  os << somechars;
524  break;
525  case eACT : case eDEA :
526  // do nothing
527  break;
528  case eOTHER:
529  os << maskbits[index].s;
530  break;
531  default: // as much to stop gcc complaining as any other reason
532  RAISE_EXCEPTION(oofE_FieldError(NULL, NULL,
533  "Unhandled token type in dbDate::ymd2Stream indicates OOFILE programmer error"));
534  }
535  }
536  } else
537  os << "INVALID DATE!";
538 
539  return os;
540 }
541 
542 
543 unsigned short dbDate::ymd2dow(unsigned short y, unsigned short m, unsigned short d)
544 {
545 // From article by Kim Larsen, DDJ April 1995
546 // Jan and Feb are treated as months 13 and 14 of previous year
547  if (m<3) {
548  m += 12;
549  y --;
550  }
551  unsigned short ret = (d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400) % 7;
552  ret +=1; // 1-based
553  return ret;
554 }
555 
556 
557 void dbDate::ymd2dayname(unsigned short year, unsigned short month, unsigned short day, char * dayname, bool isshort, bool isupper)
558 {
559  unsigned short dow = ymd2dow(year, month, day);
560  switch (dow) {
561  case 1:
562  if (isshort) {
563  if (isupper)
564  strcpy(dayname,"MON");
565  else
566  strcpy(dayname,"Mon");
567  }
568  else {
569  if (isupper)
570  strcpy(dayname,"MONDAY");
571  else
572  strcpy(dayname,"Monday");
573  }
574  break;
575  case 2:
576  if (isshort) {
577  if (isupper)
578  strcpy(dayname,"TUE");
579  else
580  strcpy(dayname,"Tue");
581  }
582  else {
583  if (isupper)
584  strcpy(dayname,"TUESDAY");
585  else
586  strcpy(dayname,"Tuesday");
587  }
588  break;
589  case 3:
590  if (isshort) {
591  if (isupper)
592  strcpy(dayname,"WED");
593  else
594  strcpy(dayname,"Wed");
595  }
596  else {
597  if (isupper)
598  strcpy(dayname,"WEDNESDAY");
599  else
600  strcpy(dayname,"Wednesday");
601  }
602  break;
603  case 4:
604  if (isshort) {
605  if (isupper)
606  strcpy(dayname,"THU");
607  else
608  strcpy(dayname,"Thu");
609  }
610  else {
611  if (isupper)
612  strcpy(dayname,"THURSDAY");
613  else
614  strcpy(dayname,"Thursday");
615  }
616  break;
617  case 5:
618  if (isshort) {
619  if (isupper)
620  strcpy(dayname,"FRI");
621  else
622  strcpy(dayname,"Fri");
623  }
624  else {
625  if (isupper)
626  strcpy(dayname,"FRIDAY");
627  else
628  strcpy(dayname,"Friday");
629  }
630  break;
631  case 6:
632  if (isshort) {
633  if (isupper)
634  strcpy(dayname,"SAT");
635  else
636  strcpy(dayname,"Sat");
637  }
638  else {
639  if (isupper)
640  strcpy(dayname,"SATURDAY");
641  else
642  strcpy(dayname,"Saturday");
643  }
644  break;
645  case 7:
646  if (isshort) {
647  if (isupper)
648  strcpy(dayname,"SUN");
649  else
650  strcpy(dayname,"Sun");
651  }
652  else {
653  if (isupper)
654  strcpy(dayname,"SUNDAY");
655  else
656  strcpy(dayname,"Sunday");
657  }
658  break;
659  }
660 }
661 
662 
663 void
664 dbDate::month2str(unsigned short monthnum, char * monthname, bool isshort, bool isupper)
665 {
666  switch (monthnum) {
667  case 1:
668  if (isshort) {
669  if (isupper)
670  strcpy(monthname,"JAN");
671  else
672  strcpy(monthname,"Jan");
673  }
674  else {
675  if (isupper)
676  strcpy(monthname,"JANUARY");
677  else
678  strcpy(monthname,"January");
679  }
680  break;
681  case 2:
682  if (isshort) {
683  if (isupper)
684  strcpy(monthname,"FEB");
685  else
686  strcpy(monthname,"Feb");
687  }
688  else {
689  if (isupper)
690  strcpy(monthname,"FEBRUARY");
691  else
692  strcpy(monthname,"February");
693  }
694  break;
695  case 3:
696  if (isshort) {
697  if (isupper)
698  strcpy(monthname,"MAR");
699  else
700  strcpy(monthname,"Mar");
701  }
702  else {
703  if (isupper)
704  strcpy(monthname,"MARCH");
705  else
706  strcpy(monthname,"March");
707  }
708  break;
709  case 4:
710  if (isshort) {
711  if (isupper)
712  strcpy(monthname,"APR");
713  else
714  strcpy(monthname,"Apr");
715  }
716  else {
717  if (isupper)
718  strcpy(monthname,"APRIL");
719  else
720  strcpy(monthname,"April");
721  }
722  break;
723  case 5:
724  if (isshort) {
725  if (isupper)
726  strcpy(monthname,"MAY");
727  else
728  strcpy(monthname,"May");
729  }
730  else {
731  if (isupper)
732  strcpy(monthname,"MAY");
733  else
734  strcpy(monthname,"May");
735  }
736  break;
737  case 6:
738  if (isshort) {
739  if (isupper)
740  strcpy(monthname,"JUN");
741  else
742  strcpy(monthname,"Jun");
743  }
744  else {
745  if (isupper)
746  strcpy(monthname,"JUNE");
747  else
748  strcpy(monthname,"June");
749  }
750  break;
751  case 7:
752  if (isshort) {
753  if (isupper)
754  strcpy(monthname,"JUL");
755  else
756  strcpy(monthname,"Jul");
757  }
758  else {
759  if (isupper)
760  strcpy(monthname,"JULY");
761  else
762  strcpy(monthname,"July");
763  }
764  break;
765  case 8:
766  if (isshort) {
767  if (isupper)
768  strcpy(monthname,"AUG");
769  else
770  strcpy(monthname,"Aug");
771  }
772  else {
773  if (isupper)
774  strcpy(monthname,"AUGUST");
775  else
776  strcpy(monthname,"August");
777  }
778  break;
779  case 9:
780  if (isshort) {
781  if (isupper)
782  strcpy(monthname,"SEP");
783  else
784  strcpy(monthname,"Sep");
785  }
786  else {
787  if (isupper)
788  strcpy(monthname,"SEPTEMBER");
789  else
790  strcpy(monthname,"September");
791  }
792  break;
793  case 10:
794  if (isshort) {
795  if (isupper)
796  strcpy(monthname,"OCT");
797  else
798  strcpy(monthname,"Oct");
799  }
800  else {
801  if (isupper)
802  strcpy(monthname,"OCTOBER");
803  else
804  strcpy(monthname,"October");
805  }
806  break;
807  case 11:
808  if (isshort) {
809  if (isupper)
810  strcpy(monthname,"NOV");
811  else
812  strcpy(monthname,"Nov");
813  }
814  else {
815  if (isupper)
816  strcpy(monthname,"NOVEMBER");
817  else
818  strcpy(monthname,"November");
819  }
820  break;
821  case 12:
822  if (isshort) {
823  if (isupper)
824  strcpy(monthname,"DEC");
825  else
826  strcpy(monthname,"Dec");
827  }
828  else {
829  if (isupper)
830  strcpy(monthname,"DECEMBER");
831  else
832  strcpy(monthname,"December");
833  }
834  break;
835  }
836 }
837 
838 
839 void
840 dbDate::ddth(unsigned short daynum, char * outDD, bool isupper)
841 {
842  stringstream oss;
843 
844  oss << daynum;
845 
846  switch (daynum) {
847  case 1: case 21: case 31:
848  if(isupper)
849  oss << "ST";
850  else
851  oss << "st";
852  break;
853 
854  case 2: case 22:
855  if(isupper)
856  oss << "ND";
857  else
858  oss << "nd";
859  break;
860 
861  case 3: case 23:
862  if(isupper)
863  oss << "RD";
864  else
865  oss << "rd";
866  break;
867 
868  default:if(isupper)
869  oss << "TH";
870  else
871  oss << "th";
872 
873  break;
874 
875 
876  }
877 
878  #if OOF_USE_ANSI_STREAMS
879  string s = oss.str(); // ANSI string
880  const char* s2 = s.c_str();
881  strcpy(outDD, s2);
882  #else
883  unsigned slen=oss.pcount();
884  memcpy(outDD,oss.str(),slen);
885  oss.rdbuf()->freeze(0);
886  outDD[slen]='\0';
887  #endif
888  return;
889 }
890 
891 
892 void
893 dbDate::generateTestData(bool generateRandom, unsigned long seedOrCount)
894 {
895 // const long startDate = ymd2Long(1963, 5, 7);
896 // const long endDate = ymd2Long(2001,1,1);
897 // const long dateDiff = endDate - startDate;
898 // setDate(startDate);
899 // operator+=(rand()%dateDiff); // don't have this operator yet!
900 
901 // pretty sick alternative but at least it generates legal dates
902  if (generateRandom) {
903  setDate(ymd2Long( (rand()%(2010-1963) + 1963),
904  (rand()%12), (rand()%28) ));
905  }
906  else {
907  const long startDate = ymd2Long(1963, 5, 7);
908  setDate(seedOrCount+startDate);
909  }
910 }
911 
912 
914 dbDate::between(const char* fromStr, const char* toStr) const
915 {
916  return dbNumericField::between(str2Long(fromStr), str2Long(toStr));
917 }
918 
919 
921 dbDate::outside(const char* fromStr, const char* toStr) const
922 {
923  return dbNumericField::outside(str2Long(fromStr), str2Long(toStr));
924 }
925 
926 
929 {
931  return ret;
932 }
933 
934 
936 dbDate::operator==(const char* str) const
937 {
939 }
940 
941 
943 dbDate::operator!=(const char* str) const
944 {
946 }
947 
948 
950 dbDate::operator<(const char* str) const
951 {
952  return dbNumericField::operator<(str2Long(str));
953 }
954 
955 
957 dbDate::operator<=(const char* str) const
958 {
960 }
961 
962 
964 dbDate::operator>(const char* str) const
965 {
966  return dbNumericField::operator>(str2Long(str));
967 }
968 
969 
971 dbDate::operator>=(const char* str) const
972 {
974 }
975 
976 
978 dbDate::between(const dbDate& fromDate, const dbDate& toDate) const
979 {
980  return dbNumericField::between((long)fromDate, (long)toDate);
981 }
982 
983 
985 dbDate::outside(const dbDate& fromDate, const dbDate& toDate) const
986 {
987  return dbNumericField::outside((long)fromDate, (long)toDate);
988 }
989 
990 
992 dbDate::operator==(const dbDate& rhs) const
993 {
994  return dbNumericField::operator==((long)rhs);
995 }
996 
997 
999 dbDate::operator!=(const dbDate& rhs) const
1000 {
1001  return dbNumericField::operator!=((long)rhs);
1002 }
1003 
1004 
1006 dbDate::operator<(const dbDate& rhs) const
1007 {
1008  return dbNumericField::operator<((long)rhs);
1009 }
1010 
1011 
1013 dbDate::operator<=(const dbDate& rhs) const
1014 {
1015  return dbNumericField::operator<=((long)rhs);
1016 }
1017 
1018 
1020 dbDate::operator>(const dbDate& rhs) const
1021 {
1022  return dbNumericField::operator>((long)rhs);
1023 }
1024 
1025 
1027 dbDate::operator>=(const dbDate& rhs) const
1028 {
1029  return dbNumericField::operator>=((long)rhs);
1030 }
1031 
1032 
1033 dbDate&
1034 dbDate::operator=(const char* str)
1035 {
1036  if (!str || ::strlen(str)==0)
1037  setDate(0);
1038  else {
1039  unsigned short day, month, year;
1040  if(str2ymd(str, year, month, day))
1041  setDate(year, month, day);
1042  else
1043  setDate(ULONG_MAX);
1044  }
1045  return *this;
1046 }
1047 
1048 
1049 dbDate&
1051 {
1052  if (this == &rhs)
1053  return *this;
1054 
1055  setDate((long)rhs);
1056  return *this;
1057 }
1058 
1059 
1060 void
1061 dbDate::setDate(unsigned long n)
1062 {
1063  if (fieldIsStandalone())
1064  mBackend = (OOF_tableBackend*) n;
1065  else {
1066  assert(mBackend);
1067  mBackend->writeLong(n, this);
1068  }
1069 }
1070 
1071 
1072 void
1073 dbDate::setDate(const tm& unixTime )
1074 {
1075  const unsigned short day = unixTime.tm_mday;
1076  const unsigned short month = unixTime.tm_mon + 1; // months since Jan
1077  const unsigned short year = unixTime.tm_year + 1900;
1078 
1079  setDate(year, month, day);
1080 }
1081 
1082 
1083 
1084 #ifdef _Macintosh
1085 void
1086 dbDate::getStr255(Str255 s) const
1087 {
1088  oofString str = copyString();
1089  str.getStr255(s);
1090 }
1091 
1092 
1093 void
1094 dbDate::setStr255(const Str255 s)
1095 {
1096  if (s[0]==0)
1097  setDate(0);
1098  else {
1099  size_t sLen = s[0];
1100  char* cs = new char[sLen+1];
1101  memcpy(cs, &s[1], sLen);
1102  cs[sLen] = '\0';
1103  *this = cs;
1104  }
1105 }
1106 
1107 
1108 
1109 // end of Mac-specific extra conversions
1110 #endif
1111 
1112 
1113 dbDate::operator unsigned long() const
1114 {
1115  unsigned long ret;
1116  if (usingCalculator())
1117  ret = calculator()->calc(this);
1118  else {
1119  if (fieldIsStandalone())
1120  ret = (unsigned long) mBackend;
1121  else {
1122  assert(mBackend);
1123  ret = mBackend->readLong(this);
1124  }
1125  }
1126  return ret;
1127 }
1128 
1129 
1130 void
1132 {
1133  setDaynum(n);
1134 }
1135 
1136 
1137 void
1138 dbDate::setString(const char* str)
1139 {
1140  dbDate::operator=(str);
1141 }
1142 
1143 
1144 void
1145 dbDate::setDate(unsigned short year, unsigned short month, unsigned short day)
1146 {
1147  unsigned long binDate = ymd2Long(year, month, day);
1148  setDate(binDate);
1149 }
1150 
1151 
1152 void
1154 {
1155  unsigned short year, month, day;
1156  currentDate2ymd(year, month, day);
1157  setDate(year, month, day);
1158 }
1159 
1160 
1161 void
1162 dbDate::nextCenturyThreshold(unsigned short inYear)
1163 {
1164  if (inYear < 100) // will accept short years but add century
1165  inYear += currentCentury();
1166  sNextCenturyThreshold = inYear;
1169 }
1170 
1171 
1172 void
1173 dbDate::prevCenturyThreshold(unsigned short inYear)
1174 {
1175 // defines upper bound in current century - 2 digit dates boosted
1176 // beyond this should be put back to the previous century
1177  if (inYear < 100) // will accept short years but add century
1178  inYear += currentCentury();
1179  sPrevCenturyThreshold = inYear;
1181 }
1182 
1183 
1184 unsigned short
1185 dbDate::adjustShortYear(unsigned short inYear)
1186 {
1187 // can set thresholds to 0 to disable them
1188  assert(sNextCenturyThreshold==0 || sNextCenturyThreshold>100);
1189  assert(sPrevCenturyThreshold==0 || sPrevCenturyThreshold>100);
1190  assert(inYear<100);
1191  inYear += currentCentury();
1193  inYear += 100; // boosts into next century, eg: 30 entered in 1999
1194  else if (sPrevCenturyThreshold>0 && inYear>sPrevCenturyThreshold)
1195  inYear -= 100; // put back into prev century, eg: 92 entered in 2001
1196  return inYear;
1197 }
1198 
1199 
1200 
1201 void
1202 dbDate::getDate(unsigned short& year, unsigned short& month, unsigned short& day) const
1203 {
1204  const unsigned long binDate = (long) *this;
1205  long2ymd(binDate, year, month, day);
1206 }
1207 
1208 
1209 unsigned long
1210 dbDate::ymd2Long(unsigned short year, unsigned short month, unsigned short day)
1211 {
1212  if (checkDate(year, month, day)) {
1213  if ((year<100) && (month >0) && (day>0)) // not null date, eg 21/5/00
1214  year = adjustShortYear(year);
1215  return (( ( (( unsigned long)year << 8) + (unsigned long)month) << 8) + day); // use discrete bytes for ease of reading
1216  }
1217  else {
1218  return ULONG_MAX;
1219  }
1220 }
1221 
1222 
1223 void
1224 dbDate::long2ymd(unsigned long binaryDate, unsigned short& year, unsigned short& month, unsigned short& day)
1225 {
1226  day = binaryDate & 0xFF;
1227  unsigned long shifted = binaryDate >> 8;
1228  month = shifted & 0xFF;
1229  shifted = shifted >> 8;
1230  year = shifted;
1231 }
1232 
1233 
1234 long
1235 dbDate::operator-(const dbDate& rhs) const
1236 {
1237  long ret = daynum() - rhs.daynum();
1238  return ret;
1239 }
1240 
1241 
1242 
1243 dbDate
1244 dbDate::operator-(long rhs) const
1245 {
1246  dbDate ret = *this;
1247  ret -= rhs;
1248  return ret;
1249 }
1250 
1251 
1252 
1253 
1254 
1255 dbDate
1256 dbDate::operator+(long rhs) const
1257 {
1258  dbDate ret = *this;
1259  ret += rhs;
1260  return ret;
1261 }
1262 
1263 
1264 dbDate
1266 {
1267  dbDate ret = dbDate(dbField::eFieldIsStandalone); // g++ 2.7 disliked just ret(blah)
1268  ret.setDateToCurrentDate();
1269  return ret;
1270 }
1271 
1272 
1273 void
1274 dbDate::currentDate2ymd(unsigned short& year, unsigned short& month, unsigned short& day)
1275 {
1276  const time_t numTime = time(0);
1277  if (numTime == -1) {
1278 #ifdef OOF_DEBUG
1279  dbConnect::raise("System time not available");
1280 #endif
1281  year = month = day = 0;
1282  }
1283  else {
1284  const tm* timeBits = localtime(&numTime);
1285  day = timeBits->tm_mday;
1286  month = timeBits->tm_mon+1; // months since Jan
1287  year = timeBits->tm_year+1900;
1288  }
1289 }
1290 
1291 
1292 unsigned short
1294 {
1295  const time_t numTime = time(0);
1296  if (numTime == -1) {
1297 #ifdef OOF_DEBUG
1298  dbConnect::raise("System time not available");
1299 #endif
1300  return 1900; // coarse default
1301  }
1302  else {
1303  const tm* timeBits = localtime(&numTime);
1304  return (timeBits->tm_year/100)*100+1900;
1305  }
1306 }
1307 
1308 
1309 bool
1310 dbDate::str2ymd(const char* str, unsigned short& year, unsigned short& month, unsigned short& day, dateFieldOrder theOrder)
1311 {
1312  if (!str) {
1313  year = month = day = 0;
1314  return false;
1315  }
1316  istringstream s((char*)str);
1317  return istream2ymd(s, year, month, day, theOrder);
1318 }
1319 
1320 
1321 unsigned long
1322 dbDate::str2Long(const char* str, dateFieldOrder theOrder)
1323 {
1324  if (!str)
1325  return 0;
1326 
1327  unsigned short year, month, day;
1328  istringstream s((char*)str);
1329  unsigned long ret;
1330  if (istream2ymd(s, year, month, day, theOrder))
1331  ret = ymd2Long(year, month, day);
1332  else
1333  ret = ULONG_MAX;
1334  return ret;
1335 }
1336 
1337 
1338 bool
1339 dbDate::checkDate(const char* str, dateFieldOrder theOrder)
1340 {
1341  if (!str || strlen(str)==0)
1342  return true; // early exit with trivial case - empty string
1343 
1344  unsigned short year, month, day;
1345  istringstream s((char*)str);
1346  istream2ymd(s, year, month, day, theOrder);
1347  const bool ret = checkDate(year, month, day);
1348  return ret;
1349 }
1350 
1351 
1352 bool
1353 dbDate::checkDate(unsigned short year, unsigned short month, unsigned short day)
1354 {
1355  if (day==0)
1356  if ((year==0) && (month==0))
1357  return true; // valid null date
1358  else
1359  return false;
1360 
1361 
1362  // check for valid year
1363  if ((year>9999)||(year>99)&&(year<=999))
1364  return false; // note that 3 digit years are considered invalid
1365 
1366  bool ret;
1367  // check for valid month and year
1368  switch (month) {
1369  case 2:
1370  if (day > 28)
1371  ret = ((day==29) && isLeapYear(year));
1372  else
1373  ret = true;
1374  break;
1375 
1376  case 4: case 6: case 9: case 11:
1377  ret = (day <= 30);
1378  break;
1379 
1380  case 1: case 3: case 5: case 7: case 8: case 10: case 12:
1381  ret = (day <= 31);
1382  break;
1383 
1384  default :
1385  ret = false; // bad month
1386  }
1387  return ret;
1388 }
1389 
1390 
1391 bool
1392 dbDate::isLeapYear(unsigned short year)
1393 {
1394  bool isLeap = false;
1395  if (!(year%4)) { // divisible by 4
1396  if (!(year%100)) // by 100
1397  isLeap = !(year%400); // divisible by 400
1398  else
1399  isLeap = true;
1400  }
1401  return isLeap;
1402 }
1403 
1404 
1405 bool
1406 dbDate::istream2ymd(istream& is, unsigned short& year, unsigned short& month, unsigned short& day, char fieldSep, char recSep,
1407  dateFieldOrder theOrder)
1408 {
1409  char ch = is.peek();
1410  if (ch==recSep) {
1411  year = month = day = 0;
1412  return false; // early exit - empty line
1413  }
1414  if (ch==fieldSep) {
1415  year = month = day = 0;
1416  return true; // early exit - empty field
1417  }
1418 
1419  if (is.good()) {
1420  is.flags(is.flags() & ~ios::skipws | ios::dec); // we look at the white space!
1421  switch (theOrder) {
1422  case orderYMD :
1423  // skip non-digits
1424  skipTillDigit(is, fieldSep, recSep);
1425  // get year
1426  is >> year;
1427  // skip non-alphanumericals
1428  ch = is.peek();
1429  while (!isalnum(ch) && is.good()) {
1430  is >> ch; // skip char
1431  ch = is.peek();
1432  }
1433  // get month
1434  month = istream2month(is);
1435  // skip non-digits
1436  skipTillDigit(is, fieldSep, recSep);
1437  // get day
1438  is >> day;
1439  break;
1440 
1441  case orderDMY :
1442  // skip non-digits
1443  skipTillDigit(is, fieldSep, recSep);
1444  // get day
1445  is >> day;
1446  // skip post numerical characters (st,nd,rd,th)
1447  skipStreamPattern(is,"st");
1448  skipStreamPattern(is,"nd");
1449  skipStreamPattern(is,"rd");
1450  skipStreamPattern(is,"th");
1451  // skip non-alphanumericals
1452  ch = is.peek();
1453  while (!isalnum(ch) && is.good()) {
1454  is >> ch;
1455  ch = is.peek();
1456  }
1457  // get month
1458  month = istream2month(is);
1459  // get next character
1460  ch = is.peek();
1461  if ((ch==fieldSep)||(ch==recSep)) {
1462  year = currentYear();
1463  break;
1464  }
1465  // skip non-alphanumericals
1466  while (!isalnum(ch) && is.good()) {
1467  is >> ch;
1468  ch = is.peek();
1469  }
1470  // get year
1471  is >> year;
1472  break;
1473 
1474  case orderMDY :
1475  // skip non-alphanumericals
1476  ch = is.peek();
1477  while (!isalnum(ch) && is.good()) {
1478  is >> ch;
1479  ch = is.peek();
1480  }
1481  // get month
1482  month = istream2month(is);
1483  // skip non-digits
1484  skipTillDigit(is, fieldSep, recSep);
1485  // get day
1486  is >> day;
1487  // skip post numerical characters (st,nd,rd,th)
1488  skipStreamPattern(is,"st");
1489  skipStreamPattern(is,"nd");
1490  skipStreamPattern(is,"rd");
1491  skipStreamPattern(is,"th");
1492  // get next character
1493  ch = is.peek();
1494  if ((ch==fieldSep)||(ch==recSep)) {
1495  year = currentYear();
1496  break;
1497  }
1498  // skip non-alphanumericals
1499  while (!isalnum(ch) && is.good()) {
1500  is >> ch;
1501  ch = is.peek();
1502  }
1503  // get year
1504  is >> year;
1505  break;
1506  }
1507  skipRestOfField(is, fieldSep, recSep); // mainly for trailing times, eg: 0:00:00 from VB/Access
1508  if ((year<100) && (month >0) && (day>0)) // not null date, eg 21/5/00
1509  year = adjustShortYear(year);
1510  return checkDate(year, month, day);
1511  }
1512  else
1513  return false;
1514 }
1515 
1516 
1517 bool
1518 dbDate::istream2ymd(istream& is, unsigned short& year, unsigned short& month, unsigned short& day, dateFieldOrder theOrder)
1519 {
1520  return istream2ymd(is, year, month, day, dbTable::kFieldSep, dbTable::kRecSep, theOrder);
1521 }
1522 
1523 
1524 unsigned short
1526 {
1527  is.flags(is.flags() & ~ios::skipws | ios::dec); // we look at the white space!
1528  char buf[4];
1529  char ch = is.peek();
1530  unsigned short monthNum=0;
1531  if (is.good()) {
1532  // is month as character or digit?
1533  if (isalpha(ch)) {
1534  is >> ch;
1535  buf[0] = ch;
1536  is.get(buf[1]);
1537  is.get(buf[2]);
1538  buf[3]='\0';
1539  monthNum = str2month(buf);
1540  }
1541  else {
1542  is >> monthNum;
1543  }
1544  } // stream good
1545  // return month as digit
1546  return monthNum;
1547 }
1548 
1549 
1550 unsigned short
1551 dbDate::str2month (const char * s)
1552 {
1553  char month[4];
1554  strncpy(month,s,3);
1555  month[3] = '\0';
1556  for (int i=0; month[i]; ++i)
1557  month[i]=toupper(month[i]);
1558  if (!strcmp(month,"JAN"))
1559  return 1;
1560  else if (!strcmp(month,"FEB"))
1561  return 2;
1562  else if (!strcmp(month,"MAR"))
1563  return 3;
1564  else if (!strcmp(month,"APR"))
1565  return 4;
1566  else if (!strcmp(month,"MAY"))
1567  return 5;
1568  else if (!strcmp(month,"JUN"))
1569  return 6;
1570  else if (!strcmp(month,"JUL"))
1571  return 7;
1572  else if (!strcmp(month,"AUG"))
1573  return 8;
1574  else if (!strcmp(month,"SEP"))
1575  return 9;
1576  else if (!strcmp(month,"OCT"))
1577  return 10;
1578  else if (!strcmp(month,"NOV"))
1579  return 11;
1580  else if (!strcmp(month,"DEC"))
1581  return 12;
1582  else
1583  return 0; // error
1584 }
1585 
1586 
1587 unsigned long
1588 dbDate::ymd2daynum( unsigned short y,unsigned short m,unsigned short d)
1589 /*
1590 Convert Gregorian calendar date to the corresponding Julian day number
1591 j. Algorithm 199 from Communications of the ACM, Volume 6, No. 8,
1592 (Aug. 1963), p. 444. Gregorian calendar started on Sep. 14, 1752.
1593 This function not valid before that.
1594 */
1595 {
1596  unsigned long c, ya;
1597  if (m > 2)
1598  m -= 3;
1599  else {
1600  m += 9;
1601  y--;
1602  } /* else */
1603  c = y / 100;
1604  ya = y - 100*c;
1605  return ((146097*c)>>2) + ((1461*ya)>>2) + (153*m + 2)/5 + d + 1721119;
1606 }
1607 
1608 
1609 void
1610 dbDate::daynum2ymd(unsigned long dn,unsigned short& y,unsigned short& m,unsigned short& d)
1611 /*
1612 Convert a Julian day number to its corresponding Gregorian calendar
1613 date. Algorithm 199 from Communications of the ACM, Volume 6, No. 8,
1614 (Aug. 1963), p. 444. Gregorian calendar started on Sep. 14, 1752.
1615 This function not valid before that.
1616 */
1617 {
1618  unsigned long j = dn - 1721119;
1619  unsigned long dl, yl, ml;
1620  yl = ((j<<2) - 1) / 146097;
1621  j = (j<<2) - 1 - 146097*yl;
1622  dl = j>>2;
1623  j = ((dl<<2) + 3) / 1461;
1624  dl = (dl<<2) + 3 - 1461*j;
1625  dl = (dl + 4)>>2;
1626  ml = (5*dl - 3)/153;
1627  dl = 5*dl - 3 - 153*ml;
1628  dl = (dl + 5)/5;
1629  yl = 100*yl + j;
1630  if (ml < 10)
1631  ml += 3;
1632  else {
1633  ml -= 9;
1634  yl++;
1635  } /* else */
1636  assert( (dl <= USHRT_MAX) && (ml <= USHRT_MAX) && (yl <= USHRT_MAX));
1637  d = dl;
1638  m = ml;
1639  y = yl;
1640 }
1641 
1642 
1643 dbDate&
1645 {
1646  // increment date
1647  setDaynum(daynum()+1);
1648  return *this;
1649 }
1650 
1651 
1652 dbDate&
1654 {
1655  // decrement date
1656  setDaynum(daynum()-1);
1657  return *this;
1658 }
1659 
1660 
1661 dbDate&
1662 dbDate::operator+= (long numDays)
1663 {
1664  // add days to date
1665  setDaynum(daynum()+numDays);
1666  return *this;
1667 }
1668 
1669 
1670 dbDate&
1671 dbDate::operator-= (long numDays)
1672 {
1673  return (*this) += -numDays;
1674 }
1675 
1676 
1677 unsigned long
1679 {
1680  unsigned short day, month, year;
1681  getDate(year, month, day);
1682  return ymd2daynum(year, month, day);
1683 }
1684 
1685 
1686 void
1687 dbDate::setDaynum(unsigned long dn)
1688 {
1689  unsigned short day, month, year;
1690  daynum2ymd(dn, year, month, day);
1691  setDate(year,month,day);
1692 }
1693 
1694 
1695 unsigned short
1697 {
1698  return ((unsigned long) *this) & 0xFF;
1699 }
1700 
1701 
1702 unsigned short
1704 {
1705  return (((unsigned long) *this) >> 8) & 0xFF;
1706 }
1707 
1708 
1709 unsigned short
1711 {
1712  return ((unsigned long) *this) >> 16;
1713 }
1714 
1715 
1716 unsigned short
1718 {
1719  unsigned short y,m,d;
1720  currentDate2ymd(y,m,d);
1721  return d;
1722 }
1723 
1724 
1725 unsigned short
1727 {
1728  unsigned short y,m,d;
1729  currentDate2ymd(y,m,d);
1730  return m;
1731 }
1732 
1733 unsigned short
1735 {
1736  unsigned short y,m,d;
1737  currentDate2ymd(y,m,d);
1738  return y;
1739 }
1740 
1741 // private helper for dbDate
1742 void
1743 skipStreamPattern(istream& is, const char * str)
1744 {
1745  const unsigned short patternLen = strlen(str);
1746  for (unsigned short i=0; i<patternLen; i++) {
1747  char c = toupper(is.peek());
1748  char nextPat = toupper(str[i]);
1749  if (c != nextPat)
1750  return;
1751  is >> c;
1752  }
1753 
1754  return;
1755 }
1756 
1757 
1758 // -------------------------------------------------------
1759 // d b T i m e
1760 // -------------------------------------------------------
1761 
1762 #ifdef __MWERKS__
1763 #pragma mark ## DBTIME_CONSTRUCTORS
1764 #endif
1765 
1766 dbTime::dbTime(const OOF_IndexOptions indexOptions) :
1767  dbNumericField(indexOptions)
1768 {
1770 }
1771 
1772 
1773 dbTime::dbTime(const char *fieldName) :
1774  dbNumericField(fieldName)
1775 {
1777 }
1778 
1779 
1780 dbTime::dbTime(const char *fieldName, const OOF_IndexOptions indexOptions) :
1781  dbNumericField(fieldName, indexOptions)
1782 {
1784 }
1785 
1786 
1788  dbNumericField(k)
1789 {
1791 }
1792 
1793 
1794 
1795 dbTime::dbTime(const dbTime& rhs) :
1796  dbNumericField(rhs)
1797 {}
1798 
1799 
1801 {}
1802 
1803 
1804 dbField*
1806 {
1807  return new dbTime(*this);
1808 }
1809 
1810 
1811 
1812 
1813 
1814 #ifdef __MWERKS__
1815 #pragma mark ## DBTIME_ARITHMETIC_OPERATORS
1816 #endif
1817 
1818 dbTime&
1820 {
1821  setTime( value()+1000 ); // add 1 second
1822  return *this;
1823 }
1824 
1825 dbTime&
1827 {
1828  setTime( value()-1000 ); // subtract 1 second
1829  return *this;
1830 }
1831 
1832 dbTime&
1833 dbTime::operator+= (long numMilliseconds)
1834 {
1835  setTime( value()+numMilliseconds ); // add milliseconds to time
1836  return *this;
1837 }
1838 
1839 dbTime&
1840 dbTime::operator-= (long numMilliseconds)
1841 {
1842  setTime( value()-numMilliseconds ); // subtract milliseconds to time
1843  return *this;
1844 }
1845 
1846 long
1847 dbTime::operator-(const dbTime& rhs) const // return number in milliseconds
1848 {
1849  long ret = value() - rhs.value();
1850  return ret;
1851 }
1852 
1853 dbTime
1854 dbTime::operator-(long rhs) const
1855 {
1856  dbTime ret = *this;
1857  ret -= rhs;
1858  return ret;
1859 }
1860 
1861 dbTime
1862 dbTime::operator+(long rhs) const
1863 {
1864  dbTime ret = *this;
1865  ret += rhs;
1866  return ret;
1867 }
1868 
1869 #ifdef __MWERKS__
1870 #pragma mark ## DBTIME_SEARCH_FACTORIES
1871 #endif
1872 
1874 dbTime::between(const char* fromStr, const char* toStr) const
1875 {
1876  return dbNumericField::between(str2long(fromStr), str2long(toStr));
1877 }
1878 
1879 
1881 dbTime::outside(const char* fromStr, const char* toStr) const
1882 {
1883  return dbNumericField::outside(str2long(fromStr), str2long(toStr));
1884 }
1885 
1886 
1887 dbQueryClause*
1889 {
1891  return ret;
1892 }
1893 
1894 
1896 dbTime::operator==(const char* str) const
1897 {
1898  return dbNumericField::operator==(str2long(str));
1899 }
1900 
1901 
1903 dbTime::operator!=(const char* str) const
1904 {
1905  return dbNumericField::operator!=(str2long(str));
1906 }
1907 
1908 
1910 dbTime::operator<(const char* str) const
1911 {
1912  return dbNumericField::operator<(str2long(str));
1913 }
1914 
1915 
1917 dbTime::operator<=(const char* str) const
1918 {
1919  return dbNumericField::operator<=(str2long(str));
1920 }
1921 
1922 
1924 dbTime::operator>(const char* str) const
1925 {
1926  return dbNumericField::operator>(str2long(str));
1927 }
1928 
1929 
1931 dbTime::operator>=(const char* str) const
1932 {
1933  return dbNumericField::operator>=(str2long(str));
1934 }
1935 
1936 // -- search factories using dbTime operands ---------
1937 
1939 dbTime::between(const dbTime& fromDate, const dbTime& toDate) const
1940 {
1941  return dbNumericField::between((long)fromDate, (long)toDate);
1942 }
1943 
1944 
1946 dbTime::outside(const dbTime& fromDate, const dbTime& toDate) const
1947 {
1948  return dbNumericField::outside((long)fromDate, (long)toDate);
1949 }
1950 
1951 
1953 dbTime::operator==(const dbTime& rhs) const
1954 {
1955  return dbNumericField::operator==((long)rhs);
1956 }
1957 
1958 
1960 dbTime::operator!=(const dbTime& rhs) const
1961 {
1962  return dbNumericField::operator!=((long)rhs);
1963 }
1964 
1965 
1967 dbTime::operator<(const dbTime& rhs) const
1968 {
1969  return dbNumericField::operator<((long)rhs);
1970 }
1971 
1972 
1974 dbTime::operator<=(const dbTime& rhs) const
1975 {
1976  return dbNumericField::operator<=((long)rhs);
1977 }
1978 
1979 
1981 dbTime::operator>(const dbTime& rhs) const
1982 {
1983  return dbNumericField::operator>((long)rhs);
1984 }
1985 
1986 
1988 dbTime::operator>=(const dbTime& rhs) const
1989 {
1990  return dbNumericField::operator>=((long)rhs);
1991 }
1992 
1993 #ifdef __MWERKS__
1994 #pragma mark ## DBTIME_REFECTIVE_OPERATORS
1995 #endif
1996 
1997 unsigned long
1999 {
2000  return sizeof(long);
2001 }
2002 
2005 {
2006  return timeField;
2007 }
2008 
2011 {
2012  return longField;
2013 }
2014 
2015 #ifdef __MWERKS__
2016 #pragma mark ## DBTIME_UTILITIES
2017 #endif
2018 
2019 dbTime&
2020 dbTime::calculateWith(dbTimeCalculator* adoptedCalculator, bool useOnlyForDefaults)
2021 {
2022  CalculateWith(adoptedCalculator, useOnlyForDefaults);
2023  return *this;
2024 }
2025 
2026 
2027 void
2029 {
2030  assert(mCalculator);
2031  setTime( calculator()->calc(this) );
2032 }
2033 
2034 
2035 bool
2036 dbTime::checkTime(short day, unsigned short hour, unsigned short minute, unsigned short second, unsigned short millisecond)
2037 {
2038  if( (day>23) || (day<-23) )
2039  return false;
2040 
2041  // checking for < 0 superfluous for unsigned values
2042  if( hour>23 )
2043  return false;
2044 
2045  if( minute>59 )
2046  return false;
2047 
2048  if( second>59 )
2049  return false;
2050 
2051  if( millisecond>999 )
2052  return false;
2053 
2054  return true;
2055 }
2056 
2057 void
2058 dbTime::long2dhmsm(long binaryTime, short& day, unsigned short& hour, unsigned short& minute, unsigned short& second, unsigned short& millisecond)
2059 {
2060  long remainder = binaryTime;
2061 
2062  day = (short)( remainder / (1000*60*60*24) );
2063  remainder = remainder % (1000*60*60*24);
2064 
2065  hour = (unsigned short)( remainder / (1000*60*60) );
2066  remainder = remainder % (1000*60*60);
2067 
2068  minute = (unsigned short)( remainder / (1000*60) );
2069  remainder = remainder % (1000*60);
2070 
2071  second = (unsigned short)( remainder / 1000 );
2072 
2073  millisecond = remainder % 1000;
2074 }
2075 
2076 long
2077 dbTime::dhmsm2long(short day, unsigned short hour, unsigned short minute, unsigned short second, unsigned short millisecond)
2078 {
2079  long totalMilliseconds = 0;
2080 
2081  if( checkTime(day, hour, minute, second, millisecond) ) {
2082 
2083  totalMilliseconds = (long)millisecond;
2084  totalMilliseconds += 1000 * (long)second;
2085  totalMilliseconds += 1000 * 60 * (long)minute;
2086  totalMilliseconds += 1000 * 60 * 60 * (long)hour;
2087  totalMilliseconds += 1000 * 60 * 60 * 24 * (long)day;
2088  }
2089  else
2090  totalMilliseconds= ULONG_MAX;
2091  return totalMilliseconds;
2092 }
2093 
2094 bool
2095 dbTime::istream2dhmsm(istream& is, short& day, unsigned short& hour, unsigned short& minute, unsigned short& second, unsigned short& millisecond)
2096 {
2097  return istream2dhmsm(is, day, hour, minute, second, millisecond, dbTable::kFieldSep, dbTable::kRecSep);
2098 }
2099 
2100 bool
2101 dbTime::istream2dhmsm(istream& is, short& day, unsigned short& hour, unsigned short& minute,
2102  unsigned short& second, unsigned short& millisecond, char fieldSep, char recSep)
2103 {
2104  hourT hourModifier = hour_24; // assume 24 hour clock
2105  const char ch = is.peek();
2106 
2107  day = hour = minute = second = millisecond = 0;
2108 
2109  if( ch==recSep )
2110  return false; // early exit - empty line
2111 
2112  if( ch==fieldSep )
2113  return true; // early exit - empty field
2114 
2115  if( is.good() ) {
2116  is.flags( is.flags() & ~ios::skipws | ios::dec); // we look at the white space
2117 
2118  if( skipTillDigitAmPm(is,hourModifier, fieldSep, recSep) ) {
2119  is >> hour;
2120 
2121  if( skipTillDigitAmPm(is,hourModifier, fieldSep, recSep) ) {
2122  is >> minute;
2123 
2124  if( skipTillDigitAmPm(is,hourModifier, fieldSep, recSep) ) {
2125  is >> second;
2126 
2127  if( skipTillDigitAmPm(is,hourModifier, fieldSep, recSep) ) {
2128  is >> millisecond;
2129  }
2130  }
2131  }
2132  }
2133  skipTillDigitAmPm(is,hourModifier, fieldSep, recSep);
2134  if( hourModifier==am_hour )
2135  {
2136  if( hour==12 )
2137  hour=0;
2138  }
2139 
2140  if( hourModifier==pm_hour )
2141  {
2142  if( hour<12 )
2143  hour+=12;
2144  }
2145  } // good stream
2146  return checkTime(day, hour, minute, second, millisecond);
2147 }
2148 
2149 ostream&
2150 dbTime::hms2stream(unsigned short hour, unsigned short minute, unsigned short second, ostream& os)
2151 {
2152  os << hour << ':';
2153 
2154  if( minute < 10 )
2155  os << '0'; // pad with zeros
2156  os << minute << ':';
2157 
2158  if( second < 10 )
2159  os << '0'; // pad with zeros
2160  os << second;
2161 
2162  return os;
2163 }
2164 
2165 ostream&
2166 dbTime::hms2stream(unsigned short hour, unsigned short minute, ostream& os)
2167 {
2168  os << hour << ':';
2169 
2170  if( minute < 10 )
2171  os << '0'; // pad with zeros
2172  os << minute << ':';
2173 
2174  return os;
2175 }
2176 
2177 long
2178 dbTime::str2long(const char* str)
2179 {
2180  if (!str)
2181  return 0;
2182 
2183  short day;
2184  unsigned short hour, minute, second, millisecond;
2185 
2186  istringstream s((char*)str);
2187  long ret;
2188  if (istream2dhmsm(s, day, hour, minute, second, millisecond))
2189  ret = dhmsm2long(day, hour, minute, second, millisecond);
2190  else
2191  ret = LONG_MAX;
2192  return ret;
2193 }
2194 
2195 bool
2196 dbTime::str2dhmsm(const char* str, short& day, unsigned short& hour, unsigned short& minute, unsigned short& second, unsigned short& millisecond)
2197 {
2198  if (!str) {
2199  day = hour = minute = second = millisecond = 0;
2200  return false;
2201  }
2202  istringstream s((char*)str);
2203  return istream2dhmsm(s, day, hour, minute, second, millisecond);
2204 }
2205 
2206 
2207 
2208 void
2209 dbTime::generateTestData(bool generateRandom, unsigned long seedOrCount)
2210 {
2211  if (generateRandom)
2212  setTime( (rand()%24), (rand()%60), (rand()%60) );
2213  else
2214  setTime(seedOrCount);
2215 }
2216 
2217 #ifdef __MWERKS__
2218 #pragma mark ## DBTIME_SETTERS
2219 #endif
2220 
2225 void
2227 {
2228  if (fieldIsStandalone()) {
2229 
2230  mBackend = (OOF_tableBackend*) n;
2231  }
2232  else {
2233  assert(mBackend);
2234  mBackend->writeLong(n, this);
2235  }
2236 }
2237 
2238 void
2239 dbTime::setTime(short day, unsigned short hour, unsigned short minute, unsigned short second, unsigned short millisecond)
2240 {
2241  setTime( dhmsm2long(day, hour, minute, second, millisecond) );
2242 }
2243 
2244 void
2245 dbTime::setTime(short day, unsigned short hour, unsigned short minute, unsigned short second)
2246 {
2247  setTime( dhmsm2long(day, hour, minute, second, 0) );
2248 }
2249 
2250 void
2251 dbTime::setTime(unsigned short hour, unsigned short minute, unsigned short second)
2252 {
2253  setTime( dhmsm2long(0, hour, minute, second, 0) );
2254 }
2255 
2256 void
2257 dbTime::setTime(const tm& unixTime )
2258 {
2259  const unsigned short second = unixTime.tm_sec;
2260  const unsigned short minute = unixTime.tm_min;
2261  const unsigned short hour = unixTime.tm_hour;
2262 
2263  setTime(hour, minute, second);
2264 }
2265 
2266 void
2268 {
2269  unsigned short hour, minute, second;
2270 
2271  currentTime2hms(hour, minute, second);
2272  setTime(hour, minute, second);
2273 }
2274 
2275 void
2277 {
2278  if( srcField->fieldType()==timeField )
2279  setTime( ((dbTime*)srcField)->value() );
2280 
2281 #ifdef OOF_DEBUG
2282  else
2284  stringstream() << flush << "wrong field type passed in to dbTime::copyValueFrom, copying to "
2285  << fieldName() << " from " << srcField->fieldName()
2286  );
2287 #endif
2288 }
2289 
2290 void
2292 {
2293  if( srcField->fieldType()==timeField ) {
2294 
2295  const long rhs = ((dbTime*)srcField)->value();
2296  if( value() != rhs )
2297  setTime( rhs );
2298  }
2299 
2300 #ifdef OOF_DEBUG
2301  else
2303  stringstream() << flush << "wrong field type passed in to dbTime::copyValueIfDifferent, copying to "
2304  << fieldName() << " from " << srcField->fieldName()
2305  );
2306 #endif
2307 }
2308 
2309 dbTime&
2310 dbTime::operator=(const char* str)
2311 {
2312  if (!str || ::strlen(str)==0)
2313  setTime(0);
2314  else {
2315  short day;
2316  unsigned short hour, minute, second, millisecond;
2317  str2dhmsm(str, day, hour, minute, second, millisecond);
2318  setTime(day, hour, minute, second, millisecond);
2319  }
2320  return *this;
2321 }
2322 
2323 
2324 dbTime&
2326 {
2327  if (this == &rhs)
2328  return *this;
2329 
2330  setTime( (long)rhs );
2331  return *this;
2332 }
2333 
2334 
2335 bool
2336 dbTime::insert(istream& is, char fieldSep, char recSep)
2337 {
2338  if( !is.good() ) // is the stream good?
2339  return false;
2340 
2341  // read in the time
2342  short day;
2343  unsigned short hour, minute, second, millisecond;
2344  istream2dhmsm(is,day,hour,minute,second,millisecond,fieldSep,recSep);
2345 
2346  // read in a potential field/record separator
2347  const char c = is.peek();
2348  bool hitEndOfField = false;
2349  if ((c==fieldSep) || (c==recSep))
2350  hitEndOfField = true;
2351  if (hitEndOfField)
2352  setTime(day,hour,minute,second,millisecond);
2353  return hitEndOfField;
2354 }
2355 
2356 
2357 #ifdef __MWERKS__
2358 #pragma mark ## DBTIME_GETTERS
2359 #endif
2360 
2361 dbTime::operator long() const
2362 {
2363  long ret;
2364  if (usingCalculator())
2365  ret = calculator()->calc(this);
2366  else {
2367  if (fieldIsStandalone())
2368  ret = (long) mBackend;
2369  else {
2370  assert(mBackend);
2371  ret = mBackend->readLong(this);
2372  }
2373  }
2374  return ret;
2375 }
2376 
2377 void
2378 dbTime::getTime( short& days, unsigned short& hours, unsigned short& minutes, unsigned short& seconds, unsigned short& milliseconds ) const
2379 {
2380  long2dhmsm( getTime(), days, hours, minutes, seconds, milliseconds );
2381 }
2382 
2383 void
2384 dbTime::getTime( short& days, unsigned short& hours, unsigned short& minutes, unsigned short& seconds ) const
2385 {
2386  unsigned short milliseconds;
2387 
2388  long2dhmsm( getTime(), days, hours, minutes, seconds, milliseconds );
2389 }
2390 
2391 void
2392 dbTime::getTime( unsigned short& hours, unsigned short& minutes, unsigned short& seconds) const
2393 {
2394  short days;
2395  unsigned short milliseconds;
2396 
2397  long2dhmsm( getTime(), days, hours, minutes, seconds, milliseconds );
2398 }
2399 
2400 void
2401 dbTime::getTime( tm& unixTime ) const
2402 {
2403  short days;
2404  unsigned short hours, minutes, seconds, milliseconds;
2405 
2406  long2dhmsm( getTime(), days, hours, minutes, seconds, milliseconds );
2407 
2408  unixTime.tm_sec = seconds;
2409  unixTime.tm_min = minutes;
2410  unixTime.tm_hour = hours;
2411 }
2412 
2413 short
2415 {
2416  short day;
2417  unsigned short hour, minute, second;
2418 
2419  getTime( day, hour, minute, second );
2420 
2421  return day;
2422 }
2423 
2424 unsigned short
2426 {
2427  unsigned short hour, minute, second;
2428 
2429  getTime( hour, minute, second );
2430 
2431  return hour;
2432 }
2433 
2434 unsigned short
2436 {
2437  unsigned short hour, minute, second;
2438 
2439  getTime( hour, minute, second );
2440 
2441  return minute;
2442 }
2443 
2444 unsigned short
2446 {
2447  unsigned short hour, minute, second;
2448 
2449  getTime( hour, minute, second );
2450 
2451  return second;
2452 }
2453 
2454 unsigned short
2456 {
2457  short day;
2458  unsigned short hour, minute, second, millisecond;
2459 
2460  getTime( day, hour, minute, second, millisecond );
2461 
2462  return millisecond;
2463 }
2464 
2465 void
2466 dbTime::extract(ostream& os) const
2467 {
2468  const long binTime = (long)*this;
2469 
2470  if( binTime ) {
2471  short day;
2472  unsigned short hour, minute, second, millisecond;
2473 
2474  long2dhmsm(binTime, day, hour, minute, second, millisecond);
2475 
2476  //if( mFormatMask.length() )
2477  // hms2stream(mFormatMask, year, month, day, os);
2478  //else
2479  hms2stream(hour, minute, second, os);
2480  }
2481 }
2482 
2483 #ifdef __MWERKS__
2484 #pragma mark ## DBTIME_CURRENT_TIME
2485 #endif
2486 
2487 ostream&
2488 dbTime::now(ostream& os)
2489 {
2490  unsigned short hour, minute, second;
2491  currentTime2hms(hour, minute, second);
2492  return hms2stream(hour, minute, second, os);
2493 }
2494 
2495 void
2496 dbTime::currentTime2hms(unsigned short& hour, unsigned short& minute, unsigned short& second)
2497 {
2498  const time_t numTime = time(0);
2499  if (numTime == -1) {
2500 #ifdef OOF_DEBUG
2501  dbConnect::raise("System time not available");
2502 #endif
2503  hour = minute = second = 0;
2504  }
2505  else {
2506  const tm* timeBits = localtime(&numTime);
2507  second = timeBits->tm_sec;
2508  minute = timeBits->tm_min;
2509  hour = timeBits->tm_hour;
2510  }
2511 }
2512 
2513 dbTime
2515 {
2516  dbTime ret = dbTime(dbField::eFieldIsStandalone); // g++ 2.7 disliked just ret(blah)
2517  ret.setTimeToCurrentTime();
2518  return ret;
2519 }
2520 
2521 unsigned short
2523 {
2524  unsigned short h,m,s;
2525  currentTime2hms(h,m,s);
2526  return h;
2527 }
2528 
2529 unsigned short
2531 {
2532  unsigned short h,m,s;
2533  currentTime2hms(h,m,s);
2534  return m;
2535 }
2536 
2537 unsigned short
2539 {
2540  unsigned short h,m,s;
2541  currentTime2hms(h,m,s);
2542  return s;
2543 }
2544 
2545 /* AD 980728
2546 long
2547 operator- (const dbTime& time1, const dbTime& time2)
2548 {
2549  // return number of milliseconds
2550  return time1.value() - time2.value();
2551 }
2552 
2553 */
2554 
2555 
2556 // -------------------------------------------------------
2557 // d b D a t e T i m e
2558 // -------------------------------------------------------
2559 
2560 #ifdef __MWERKS__
2561 #pragma mark ## DBDATETIME_CONSTRUCTORS
2562 #endif
2563 
2565  dbNumericField(indexOptions)
2566 {
2568 }
2569 
2570 
2571 dbDateTime::dbDateTime(const char *fieldName) :
2572  dbNumericField(fieldName)
2573 {
2575 }
2576 
2577 
2578 dbDateTime::dbDateTime(const char *fieldName, const OOF_IndexOptions indexOptions) :
2579  dbNumericField(fieldName, indexOptions)
2580 {
2582 }
2583 
2584 
2586  dbNumericField(k)
2587 {
2589 }
2590 
2591 
2593  dbNumericField(rhs)
2594 {
2596 }
2597 
2598 
2600 {}
2601 
2602 
2603 dbField*
2605 {
2606  return new dbDateTime(*this);
2607 }
2608 
2609 
2610 
2611 
2612 
2613 #ifdef __MWERKS__
2614 #pragma mark ## DBDATETIME_ARITHMETIC_OPERATORS
2615 #endif
2616 
2617 dbDateTime&
2619 {
2620  setDateTime( value() + numDays*kSecondsInDay );
2621  return *this;
2622 }
2623 
2624 
2625 dbDateTime&
2627 {
2628  *this += 1;
2629  return *this;
2630 }
2631 
2632 
2633 dbDateTime&
2635 {
2636  *this -= 1;
2637  return *this;
2638 }
2639 
2640 
2641 dbDateTime&
2643 {
2644  setDateTime( value() - numDays*kSecondsInDay );
2645  return *this;
2646 }
2647 
2648 unsigned long
2649 dbDateTime::operator+(const dbDateTime& rhs) const // return number in seconds
2650 {
2651  const unsigned long ret = value() + rhs.value();
2652  return ret;
2653 }
2654 
2655 unsigned long
2656 dbDateTime::operator-(const dbDateTime& rhs) const // return number in seconds
2657 {
2658  const unsigned long ret = value() - rhs.value();
2659  return ret;
2660 }
2661 
2662 dbDateTime
2663 dbDateTime::operator+(long numDays) const
2664 {
2665  dbDateTime ret = *this;
2666  ret += numDays;
2667  return ret;
2668 }
2669 
2670 dbDateTime
2671 dbDateTime::operator-(long numDays) const
2672 {
2673  dbDateTime ret = *this;
2674  ret -= numDays;
2675  return ret;
2676 }
2677 
2678 //unsigned long
2679 //dbDateTime::operator+(const dbTime& rhs) const
2680 //{
2681 // unsigned long ret = value() + rhs.value();
2682 // return ret;
2683 //}
2684 
2685 //unsigned long
2686 //dbDateTime::operator-(const dbTime& rhs) const
2687 //{
2688 // unsigned long ret = value() - rhs.value();
2689 // return ret;
2690 //}
2691 
2692 #ifdef __MWERKS__
2693 #pragma mark ## DBDATETIME_SEARCH_FACTORIES
2694 #endif
2695 
2697 dbDateTime::between(const char* fromStr, const char* toStr) const
2698 {
2699  return dbNumericField::between(str2ulong(fromStr), str2ulong(toStr));
2700 }
2701 
2703 dbDateTime::outside(const char* fromStr, const char* toStr) const
2704 {
2705  return dbNumericField::outside(str2ulong(fromStr), str2ulong(toStr));
2706 }
2707 
2708 
2709 dbQueryClause*
2711 {
2713  return ret;
2714 }
2715 
2716 
2718 dbDateTime::operator==(const char* str) const
2719 {
2721 }
2722 
2724 dbDateTime::operator!=(const char* str) const
2725 {
2727 }
2728 
2730 dbDateTime::operator<(const char* str) const
2731 {
2732  return dbNumericField::operator<(str2ulong(str));
2733 }
2734 
2736 dbDateTime::operator<=(const char* str) const
2737 {
2739 }
2740 
2742 dbDateTime::operator>(const char* str) const
2743 {
2744  return dbNumericField::operator>(str2ulong(str));
2745 }
2746 
2748 dbDateTime::operator>=(const char* str) const
2749 {
2751 }
2752 
2753 // -- search factories using dbDateTime operands ---------
2754 
2756 dbDateTime::between(const dbDateTime& fromDate, const dbDateTime& toDate) const
2757 {
2758  return dbNumericField::between(fromDate.value(), toDate.value());
2759 }
2760 
2762 dbDateTime::outside(const dbDateTime& fromDate, const dbDateTime& toDate) const
2763 {
2764  return dbNumericField::outside(fromDate.value(), toDate.value());
2765 }
2766 
2769 {
2770  return dbNumericField::operator==(rhs.value());
2771 }
2772 
2775 {
2776  return dbNumericField::operator!=(rhs.value());
2777 }
2778 
2781 {
2782  return dbNumericField::operator<(rhs.value());
2783 }
2784 
2787 {
2788  return dbNumericField::operator<=(rhs.value());
2789 }
2790 
2793 {
2794  return dbNumericField::operator>(rhs.value());
2795 }
2796 
2799 {
2800  return dbNumericField::operator>=(rhs.value());
2801 }
2802 
2803 #ifdef __MWERKS__
2804 #pragma mark ## DBDATETIME_REFECTIVE_OPERATORS
2805 #endif
2806 
2807 unsigned long
2809 {
2810  return sizeof(unsigned long);
2811 }
2812 
2815 {
2816  return dateTimeField;
2817 }
2818 
2821 {
2822  return uLongField;
2823 }
2824 
2825 #ifdef __MWERKS__
2826 #pragma mark ## DBDATETIME_UTILITIES
2827 #endif
2828 
2829 dbDateTime&
2830 dbDateTime::calculateWith(dbDateTimeCalculator* adoptedCalculator, bool useOnlyForDefaults)
2831 {
2832  CalculateWith(adoptedCalculator, useOnlyForDefaults);
2833  return *this;
2834 }
2835 
2836 
2837 void
2839 {
2840  assert(mCalculator);
2841  setDateTime( calculator()->calc(this) );
2842 }
2843 
2844 
2845 bool
2846 dbDateTime::checkTime(unsigned short year, unsigned short month, unsigned short day, unsigned short hour, unsigned short minute, unsigned short second)
2847 {
2848  if (day==0)
2849  if ((year==0) && (month==0))
2850  return true; // valid null date
2851  else
2852  return false;
2853 
2854  if( year < dbDateTime::sBaseYear )
2855  return false;
2856 
2857  if( (month > 12) || (month == 0) )
2858  return false;
2859 
2860  if( day > daysInMonth( year, month ))
2861  return false;
2862 
2863  if( hour>23 )
2864  return false;
2865 
2866  if( minute>59 )
2867  return false;
2868 
2869  if( second>59 )
2870  return false;
2871 
2872  return true;
2873 }
2874 
2875 
2876 bool
2877 dbDateTime::checkTime(const char* str)
2878 {
2879  if (!str || strlen(str)==0)
2880  return true; // early exit with trivial case - empty string
2881 
2882  unsigned short year, month, day, hour, minute, second;
2883 
2884  istringstream s((char*)str);
2885  istream2ymdhms(s, year, month, day, hour, minute, second, dbDate::sDefaultDateOrder);
2886  bool ret = checkTime(year, month, day, hour, minute, second);
2887  return ret;
2888 }
2889 
2890 
2891 void
2892 dbDateTime::ulong2ymdhms( long binaryTime, unsigned short& year, unsigned short& month, unsigned short& day, unsigned short& hour, unsigned short& minute, unsigned short& second )
2893 {
2894  unsigned long remainder = binaryTime;
2895 
2896  if (binaryTime==0) { // special case - null date
2897  year = month = day = hour = minute = second = 0;
2898  }
2899  else {
2900  // count off the number of years from dbDateTime::sBaseYear
2901  unsigned short tempYear = dbDateTime::sBaseYear;
2902 
2903  while( secsInYear( tempYear ) <= remainder ) {
2904  remainder -= secsInYear( tempYear );
2905  tempYear++;
2906  }
2907  year = tempYear;
2908 
2909  // with the remainder figure out the month number (using the year number)
2910  unsigned short tempMonth = 1;
2911 
2912  while( secsInMonth( year, tempMonth ) <= remainder ) {
2913  remainder -= secsInMonth( year, tempMonth );
2914  tempMonth++;
2915  }
2916  month = tempMonth;
2917 
2918  // then the day number
2919  unsigned short tempDay = 1;
2920 
2921  while( kSecondsInDay <= remainder ) {
2922  remainder -= kSecondsInDay;
2923  tempDay++;
2924  }
2925  day = tempDay;
2926 
2927  // the hour number
2928  unsigned short tempHour = 0;
2929 
2930  while( kSecondsInHour <= remainder ) {
2931  remainder -= kSecondsInHour;
2932  tempHour++;
2933  }
2934  hour = tempHour;
2935 
2936  // the minute number
2937  unsigned short tempMinute = 0;
2938 
2939  while( kSecondsInMinute <= remainder ) {
2940  remainder -= kSecondsInMinute;
2941  tempMinute++;
2942  }
2943  minute = tempMinute;
2944 
2945  // the second number (whatever is remaining)
2946  second = remainder;
2947 
2948  #ifdef OOF_DEBUG
2949  if( checkTime(year,month,day,hour,minute,second) == false ) {
2950  dbConnect::raise(stringstream() << flush << "dbDateTime::ulong2ymdhms produced a bad time: long = " << binaryTime <<
2951  " YMDHMS = " << year << '\t' << month << '\t' << day << '\t' << hour << '\t' << minute << '\t' << second, false);
2952  }
2953  #endif
2954  } // non-zero core number
2955 }
2956 
2957 unsigned long
2958 dbDateTime::ymdhms2ulong(unsigned short year, unsigned short month, unsigned short day, unsigned short hour, unsigned short minute, unsigned short second)
2959 {
2960  unsigned long totalSeconds = 0;
2961 
2962  if( checkTime(year, month, day, hour, minute, second) ) {
2963  if (year) {
2964  assert(month && day && " If year is non-zero, so must month and day be.");
2965  totalSeconds = (unsigned long)second;
2966  totalSeconds += kSecondsInMinute * (unsigned long)minute;
2967  totalSeconds += kSecondsInHour * (unsigned long)hour;
2968  totalSeconds += kSecondsInDay * (unsigned long)(day-1);
2969 
2970  for(unsigned short tempMonth=(month-1); tempMonth>=1; tempMonth-- ) {
2971  totalSeconds += secsInMonth( year, tempMonth );
2972  }
2973 
2974  for(unsigned short tempYear=(year-1); tempYear>=dbDateTime::sBaseYear; tempYear-- ) {
2975  totalSeconds += secsInYear( tempYear );
2976  }
2977  }
2978  }
2979  else
2980  totalSeconds = ULONG_MAX;
2981 
2982  return totalSeconds;
2983 }
2984 
2985 bool
2986 dbDateTime::istream2ymdhms(istream& is, unsigned short& year, unsigned short& month, unsigned short& day,
2987  unsigned short& hour, unsigned short& minute, unsigned short& second, dbDate::dateFieldOrder theOrder)
2988 {
2989  return istream2ymdhms(is, year, month, day, hour, minute, second, dbTable::kFieldSep, dbTable::kRecSep, theOrder);
2990 }
2991 
2992 
2993 bool
2994 dbDateTime::istream2ymdhms(istream& is, unsigned short& year, unsigned short& month,
2995  unsigned short& day, unsigned short& hour, unsigned short& minute,
2996  unsigned short& second, char fieldSep, char recSep,
2997  dbDate::dateFieldOrder theOrder)
2998 {
2999  hourT hourModifier = hour_24; // assume 24 hour clock
3000  char ch = is.peek();
3001 
3002  day = month = year = hour = minute = second = 0;
3003 
3004  if( ch==recSep )
3005  return false; // early exit - empty line
3006 
3007  if( ch==fieldSep )
3008  return true; // early exit - empty field
3009 
3010  if( is.good() ) {
3011  is.flags( is.flags() & ~ios::skipws | ios::dec ); // we look at the white space
3012 
3013  switch (theOrder) {
3014  case dbDate::orderYMD :
3015 
3016  skipTillDigit(is, fieldSep, recSep); // skip non-digits
3017  if (is.good())
3018  is >> year; // get year
3019 
3020  ch = is.peek(); // skip non-alphanumericals
3021  while (!isalnum(ch) && is.good()) {
3022  is >> ch;
3023  ch = is.peek();
3024  }
3025  month = dbDate::istream2month(is); // get month
3026 
3027  skipTillDigit(is, fieldSep, recSep); // skip non-digits
3028  if (is.good())
3029  is >> day; // get day
3030 
3031  if( skipTillDigitAmPm(is,hourModifier, fieldSep, recSep) ) {
3032  is >> hour;
3033 
3034  if( skipTillDigitAmPm(is,hourModifier, fieldSep, recSep) ) {
3035  is >> minute;
3036 
3037  if( skipTillDigitAmPm(is,hourModifier, fieldSep, recSep) ) {
3038  is >> second;
3039  }
3040  }
3041  }
3042  break;
3043 
3044  case dbDate::orderDMY :
3045 
3046  if (skipTillDigit(is, fieldSep, recSep)) // skip non-digits
3047  is >> day; // get day
3048 
3049  skipStreamPattern(is,"st"); // skip post numerical characters (st,nd,rd,th)
3050  skipStreamPattern(is,"nd");
3051  skipStreamPattern(is,"rd");
3052  skipStreamPattern(is,"th");
3053 
3054  ch = is.peek(); // skip non-alphanumericals
3055  while (!isalnum(ch) && is.good()) {
3056  is >> ch;
3057  ch = is.peek();
3058  }
3059  month = dbDate::istream2month(is); // get month
3060 
3061  ch = is.peek(); // skip non-digits, check for eof
3062  while (!isdigit(ch)) {
3063  is >> ch;
3064  if (!is.good()) {
3065  year = currentYear();
3066  break;
3067  }
3068  ch = is.peek();
3069  }
3070  if (is.good()) {
3071  is >> year; // get year
3072 
3073  if( skipTillDigitAmPm(is,hourModifier, fieldSep, recSep) ) {
3074  is >> hour;
3075 
3076  if( skipTillDigitAmPm(is,hourModifier, fieldSep, recSep) ) {
3077  is >> minute;
3078 
3079  if( skipTillDigitAmPm(is,hourModifier, fieldSep, recSep) ) {
3080  is >> second;
3081  }
3082  }
3083  }
3084  } // still good for year
3085  break;
3086 
3087 
3088  case dbDate::orderMDY :
3089 
3090  ch = is.peek(); // skip non-alphanumericals
3091  while (!isalnum(ch) && is.good()) {
3092  is >> ch;
3093  ch = is.peek();
3094  }
3095 
3096  month = dbDate::istream2month(is); // get month
3097 
3098  if (skipTillDigit(is, fieldSep, recSep)) // skip non-digits
3099  is >> day; // get day
3100 
3101  skipStreamPattern(is,"st"); // skip post numerical characters (st,nd,rd,th)
3102  skipStreamPattern(is,"nd");
3103  skipStreamPattern(is,"rd");
3104  skipStreamPattern(is,"th");
3105 
3106  ch = is.peek(); // skip non-digits, check for eof
3107  while (!isdigit(ch)) {
3108  is >> ch;
3109  if (!is.good()) {
3110  year = currentYear();
3111  break;
3112  }
3113  ch = is.peek();
3114  }
3115  if (is.good()) {
3116  is >> year; // get year
3117 
3118  if( skipTillDigitAmPm(is,hourModifier, fieldSep, recSep) ) {
3119  is >> hour;
3120 
3121  if( skipTillDigitAmPm(is,hourModifier, fieldSep, recSep) ) {
3122  is >> minute;
3123 
3124  if( skipTillDigitAmPm(is,hourModifier, fieldSep, recSep) ) {
3125  is >> second;
3126  }
3127  }
3128  }
3129  } // still good for year
3130  break;
3131  }
3132 
3133  skipRestOfField(is, fieldSep, recSep);
3134 
3135  if( (year<100) && (month>0) && (day>0) ) // not null date, eg 21/5/00
3136  year = dbDate::adjustShortYear(year);
3137  if (year<dbDateTime::sBaseYear)
3138  year += 100; // if our base year in next century is only case that can trigger this
3139 
3140  if( hourModifier==am_hour )
3141  {
3142  if( hour==12 )
3143  hour=0;
3144  }
3145 
3146  if( hourModifier==pm_hour )
3147  {
3148  if( hour<12 )
3149  hour+=12;
3150  }
3151 
3152  return checkTime(year, month, day, hour, minute, second);
3153  }
3154  else
3155  return false;
3156 }
3157 
3158 ostream&
3160  unsigned short year, unsigned short month, unsigned short day,
3161  unsigned short hour, unsigned short minute, unsigned short second, ostream& os
3162 )
3163 {
3164  switch (dbDate::sDefaultDateOrder) {
3165  case dbDate::orderYMD :
3166  os << year << '/' << month << '/' << day << ' ';
3167  break;
3168 
3169  case dbDate::orderMDY :
3170  os << month << '/' << day << '/' << year << ' ';
3171  break;
3172 
3173  case dbDate::orderDMY :
3174  os << day << '/' << month << '/' << year << ' ';
3175  break;
3176  };
3177 
3178  os << hour << ':';
3179 
3180  if( minute < 10 )
3181  os << '0'; // pad with zeros
3182  os << minute << ':';
3183 
3184  if( second < 10 )
3185  os << '0'; // pad with zeros
3186  os << second;
3187 
3188  return os;
3189 }
3190 
3191 
3192 ostream&
3194  const char* mask, unsigned short year, unsigned short month, unsigned short day,
3195  unsigned short hour, unsigned short minute, unsigned short second, ostream& os
3196 )
3197 {
3198  if(checkTime(year,month,day,hour,minute,second)) {
3199  // parse the mask
3200  TOKEN maskbits[MAXTOKENS]; // temporary !!!
3202 
3203  char somechars[10]; // to take a possible month name
3204 
3205  for(int index=0;maskbits[index].token!=eEOT;index++) {
3206  switch (maskbits[index].token) {
3207 
3208  case eHH: // 24 hour clock
3209  os << hour;
3210  break;
3211  case ehh: // 12 hour clock
3212  if( hour == 0 ) {
3213  os << "12";
3214  } else {
3215  if( hour > 12 ) {
3216  os << (hour-12);
3217  } else {
3218  os << hour;
3219  }
3220  }
3221  break;
3222  case eMIN: // minutes
3223  if( minute < 10 )
3224  os << '0'; // pad with zeros
3225  os << minute;
3226  break;
3227  case eSEC: // seconds
3228  if( second < 10 )
3229  os << '0'; // pad with zeros
3230  os << second;
3231  break;
3232  case ePM: // hour indicator (all caps)
3233  if( hour < 12 ) {
3234  os << "AM";
3235  } else {
3236  os << "PM";
3237  }
3238  break;
3239  case ePm: // hour indicator (part caps)
3240  if( hour < 12 ) {
3241  os << "Am";
3242  } else {
3243  os << "Pm";
3244  }
3245  break;
3246  case epm: // hour indicator (no caps)
3247  if( hour < 12 ) {
3248  os << "am";
3249  } else {
3250  os << "pm";
3251  }
3252  break;
3253  case eD :
3254  // put day number as string into stream
3255  os << day;
3256  break;
3257  case eDD :
3258  // put day number as string into stream, padded with zeros
3259  if (day < 10)
3260  os << '0'; // pad with zeros
3261  os << day;
3262  break;
3263  case eDDD : case eDAY :
3264  // put month name as TLA into stream
3265  dbDate::ymd2dayname(year, month, day,somechars,true,true);
3266  os << somechars;
3267  break;
3268  case eDDDD :case eDAYNAME :
3269  // put month as string into stream
3270  dbDate::ymd2dayname(year, month, day,somechars,false,true);
3271  os << somechars;
3272  break;
3273  case eDdd : case eDay :
3274  // put month name as TLA into stream
3275  dbDate::ymd2dayname(year, month, day,somechars);
3276  os << somechars;
3277  break;
3278  case eDddd : case eDayname :
3279  // put month as string into stream
3280  dbDate::ymd2dayname(year, month, day,somechars,false);
3281  os << somechars;
3282  break;
3283  case eddd : case eday :
3284  // put month name as TLA into stream
3285  dbDate::ymd2dayname(year, month, day,somechars);
3286  somechars[0]=tolower(somechars[0]);
3287  os << somechars;
3288  break;
3289  case edddd : case edayname :
3290  // put month as string into stream
3291  dbDate::ymd2dayname(year, month, day,somechars,false);
3292  somechars[0]=tolower(somechars[0]);
3293  os << somechars;
3294  break;
3295  case eM :
3296  // put month number as string into stream
3297  os << month;
3298  break;
3299  case eMM :
3300  // put month number as string into stream, padded with zeros
3301  if (month < 10)
3302  os << '0'; // pad with zeros
3303  os << month;
3304  break;
3305  case eMMM : case eMON :
3306  // put month name as TLA into stream
3307  dbDate::month2str(month,somechars,true,true);
3308  os << somechars;
3309  break;
3310  case eMMMM : case eMONTH :
3311  // put month as string into stream
3312  dbDate::month2str(month,somechars,false,true);
3313  os << somechars;
3314  break;
3315  case eMmm : case eMon :
3316  // put month name as TLA into stream
3317  dbDate::month2str(month,somechars);
3318  os << somechars;
3319  break;
3320  case eMmmm : case eMonth :
3321  // put month as string into stream
3322  dbDate::month2str(month,somechars,false);
3323  os << somechars;
3324  break;
3325  case emmm : case emon :
3326  // put month name as TLA into stream
3327  dbDate::month2str(month,somechars);
3328  somechars[0]=tolower(somechars[0]);
3329  os << somechars;
3330  break;
3331  case emmmm : case ezmonth :
3332  // put month as string into stream
3333  dbDate::month2str(month,somechars,false);
3334  somechars[0]=tolower(somechars[0]);
3335  os << somechars;
3336  break;
3337  case eYY :
3338  // put short form year as string into stream
3339  os << (year%100);
3340  break;
3341  case eYYYY : case eYEAR :
3342  // put year as string into stream
3343  os << year;
3344  break;
3345  case eDDTH :
3346  dbDate::ddth(day,somechars,true);
3347  os << somechars;
3348  break;
3349  case ezddth :
3350  dbDate::ddth(day,somechars);
3351  os << somechars;
3352  break;
3353  case eACT : case eDEA :
3354  // do nothing
3355  break;
3356  case eOTHER:
3357  os << maskbits[index].s;
3358  break;
3359  default: // as much to stop gcc complaining as any other reason
3360  RAISE_EXCEPTION(oofE_FieldError(NULL, NULL,
3361  "Unhandled token type in dbDateTime::ymd2Stream indicates OOFILE programmer error"));
3362  }
3363  }
3364  } else
3365  os << "INVALID DATE-TIME!";
3366 
3367  return os;
3368 }
3369 
3370 
3371 
3372 unsigned long
3373 dbDateTime::str2ulong(const char* str)
3374 {
3375  if (!str)
3376  return 0;
3377 
3378  unsigned short year, month, day, hour, minute, second;
3379 
3380  istringstream s((char*)str);
3381  unsigned long ret;
3382  if (istream2ymdhms(s, year, month, day, hour, minute, second, dbDate::sDefaultDateOrder))
3383  ret = ymdhms2ulong(year, month, day, hour, minute, second);
3384  else
3385  ret = ULONG_MAX;
3386  return ret;
3387 }
3388 
3389 bool
3390 dbDateTime::str2ymdhms(const char* str, unsigned short& year, unsigned short& month, unsigned short& day, unsigned short& hour, unsigned short& minute, unsigned short& second)
3391 {
3392  if (!str) {
3393  year = month = day = hour = minute = second = 0;
3394  return false;
3395  }
3396  istringstream s((char*)str);
3397  return istream2ymdhms(s, year, month, day, hour, minute, second, dbDate::sDefaultDateOrder);
3398 }
3399 
3400 unsigned long
3401 dbDateTime::secsInYear(unsigned short year )
3402 {
3403  if( dbDate::isLeapYear(year) ) {
3404  return( 366*kSecondsInDay );
3405  }
3406  else {
3407  return( 365*kSecondsInDay );
3408  }
3409 }
3410 
3411 
3412 unsigned long
3413 dbDateTime::secsInMonth(unsigned short year, unsigned short month )
3414 {
3415  const unsigned long returnSecs = daysInMonth( year, month ) * kSecondsInDay;
3416  return returnSecs;
3417 }
3418 
3419 
3420 unsigned short
3421 dbDateTime::daysInMonth(unsigned short year, unsigned short month )
3422 {
3423  unsigned long returnDays;
3424 
3425  switch( month ) {
3426 
3427  case 2: // February
3428  if( dbDate::isLeapYear(year) ) {
3429  returnDays = 29;
3430  }
3431  else {
3432  returnDays = 28;
3433  }
3434  break;
3435 
3436  case 4: // April
3437  case 6: // June
3438  case 9: // September
3439  case 11: // November
3440  returnDays = 30;
3441  break;
3442 
3443  case 1: // January
3444  case 3: // March
3445  case 5: // May
3446  case 7: // July
3447  case 8: // August
3448  case 10: // October
3449  case 12: // December
3450  returnDays = 31;
3451  break;
3452 
3453 #ifdef OOF_DEBUG
3454  default:
3455  dbConnect::raise(stringstream() << flush << "Unrecognised month passed to dbDateTime::daysInMonth: month = " << month, false);
3456  break;
3457 #endif
3458 
3459  }
3460  return( returnDays );
3461 }
3462 
3463 void
3464 dbDateTime::generateTestData(bool generateRandom, unsigned long seedOrCount)
3465 {
3466  if (generateRandom) {
3467  setDateTime(((rand()%50)+dbDateTime::sBaseYear), // year
3468  ((rand()%11)+1), // month
3469  ((rand()%27)+1), // day
3470  (rand()%24), // hour
3471  (rand()%60), // minute
3472  (rand()%60)); // second
3473  }
3474  else {
3475  const unsigned long startDate = ymdhms2ulong(1963, 5, 7);
3476  setDateTime(seedOrCount+startDate);
3477  }
3478 }
3479 
3480 #ifdef __MWERKS__
3481 #pragma mark ## DBDATETIME_SETTERS
3482 #endif
3483 
3484 
3485 void
3487 {
3488  setDateTime(n);
3489 }
3490 
3491 
3492 
3493 void
3494 dbDateTime::setDateTime(unsigned long n)
3495 {
3496  /* Stores the value in the mBackend pointer for use in the lightweight
3497  subclass oofDateTime when the field storage isn't connected to a database.
3498  */
3499  if( fieldIsStandalone() ) {
3500 
3501  mBackend = (OOF_tableBackend*) n;
3502  }
3503  else {
3504  assert(mBackend);
3505  mBackend->writeLong(n, this);
3506  }
3507 }
3508 
3509 void
3510 dbDateTime::setDateTime(unsigned short year, unsigned short month, unsigned short day, unsigned short hour, unsigned short minute, unsigned short second)
3511 {
3512  setDateTime( ymdhms2ulong(year, month, day, hour, minute, second) );
3513 }
3514 
3515 
3516 void
3517 dbDateTime::setDateTime(const tm& unixTime )
3518 {
3519  const unsigned short second = unixTime.tm_sec;
3520  const unsigned short minute = unixTime.tm_min;
3521  const unsigned short hour = unixTime.tm_hour;
3522  const unsigned short day = unixTime.tm_mday;
3523  const unsigned short month = unixTime.tm_mon + 1; // months since Jan
3524  const unsigned short year = unixTime.tm_year + 1900;
3525 
3526  setDateTime(year, month, day, hour, minute, second);
3527 }
3528 
3529 
3530 void
3532 {
3533  unsigned short year, month, day, hour, minute, second;
3534 
3535  currentTime2ymdhms(year, month, day, hour, minute, second);
3536  setDateTime(year, month, day, hour, minute, second);
3537 }
3538 
3539 void
3541 {
3542  if( srcField->fieldType()==dateTimeField )
3543  setDateTime( ((dbDateTime*)srcField)->value() );
3544 
3545 #ifdef OOF_DEBUG
3546  else
3547  dbConnect::raise(stringstream() << flush << "wrong field type passed in to dbDateTime::copyValueFrom, copying to " << fieldName() << " from " << srcField->fieldName());
3548 #endif
3549 }
3550 
3551 void
3553 {
3554  if( srcField->fieldType()==dateTimeField ) {
3555 
3556  unsigned long rhs = ((dbDateTime*)srcField)->value(); // safe downcast due to above check
3557  if( value() != rhs )
3558  setDateTime( rhs );
3559  }
3560 
3561 #ifdef OOF_DEBUG
3562  else
3563  dbConnect::raise(stringstream() << flush << "wrong field type passed in to dbDateTime::copyValueIfDifferent, copying to " << fieldName() << " from " << srcField->fieldName());
3564 #endif
3565 }
3566 
3567 
3568 dbDateTime&
3569 dbDateTime::operator=(const char* str)
3570 {
3571 
3572  if (!str || ::strlen(str)==0)
3573  setDateTime(0);
3574  else {
3575  unsigned short year, month, day, hour, minute, second;
3576 
3577  if (str2ymdhms(str, year, month, day, hour, minute, second))
3578  setDateTime(year, month, day, hour, minute, second);
3579  else
3580  setDateTime(ULONG_MAX); // invalid
3581  }
3582  return *this;
3583 }
3584 
3585 
3586 dbDateTime&
3588 {
3589  if (this == &rhs)
3590  return *this;
3591 
3592  setDateTime( rhs.value() );
3593  return *this;
3594 }
3595 
3596 
3597 bool
3598 dbDateTime::insert(istream& is, char fieldSep, char recSep)
3599 {
3600  if( !is.good() ) // is the stream good?
3601  return false;
3602 
3603  // read in the time
3604  unsigned short year, month, day, hour, minute, second;
3605  istream2ymdhms(is,year,month,day,hour,minute,second,fieldSep,recSep, dbDate::sDefaultDateOrder);
3606 
3607  // read in a potential field/record separator
3608  const char c = is.peek();
3609  bool hitEndOfField = false;
3610  if ((c==fieldSep) || (c==recSep))
3611  hitEndOfField = true;
3612  if (hitEndOfField)
3613  setDateTime(year,month,day,hour,minute,second);
3614  return hitEndOfField;
3615 }
3616 
3617 #ifdef __MWERKS__
3618 #pragma mark ## DBDATETIME_GETTERS
3619 #endif
3620 
3621 
3622 #ifdef _Macintosh
3623 void
3624 dbDateTime::getStr255(Str255 s) const
3625 {
3626  oofString str = copyString();
3627  str.getStr255(s);
3628 }
3629 
3630 
3631 void
3632 dbDateTime::setStr255(const Str255 s)
3633 {
3634  if (s[0]==0)
3635  setDateTime(0);
3636  else {
3637  const size_t sLen = s[0];
3638  char* cs = new char[sLen+1];
3639  memcpy(cs, &s[1], sLen);
3640  cs[sLen] = '\0';
3641  *this = cs;
3642  }
3643 }
3644 
3645 
3646 
3647 // end of Mac-specific extra conversions
3648 #endif
3649 
3650 
3651 void
3652 dbDateTime::setString(const char* str)
3653 {
3654  dbDateTime::operator=(str);
3655 }
3656 
3657 
3658 dbDateTime::operator unsigned long() const
3659 {
3660  unsigned long ret;
3661 
3662  if( usingCalculator() )
3663  ret = calculator()->calc(this);
3664  else {
3665  if( fieldIsStandalone() )
3666  ret = (unsigned long) mBackend;
3667  else {
3668  assert(mBackend);
3669  ret = mBackend->readLong(this);
3670  }
3671  }
3672  return ret;
3673 }
3674 
3675 void
3676 dbDateTime::getDateTime( unsigned short& year, unsigned short& month, unsigned short& day, unsigned short& hour, unsigned short& minute, unsigned short& second ) const
3677 {
3678  ulong2ymdhms( getDateTime(), year, month, day, hour, minute, second );
3679 }
3680 
3681 void
3682 dbDateTime::getDateTime( tm& unixTime ) const
3683 {
3684  unsigned short year, month, day, hour, minute, second;
3685 
3686  getDateTime(year, month, day, hour, minute, second );
3687 
3688  unixTime.tm_sec = second;
3689  unixTime.tm_min = minute;
3690  unixTime.tm_hour = hour;
3691  unixTime.tm_mday = day;
3692  unixTime.tm_mon = month - 1; // months since Jan
3693  unixTime.tm_year = year - 1900;
3694 }
3695 
3696 unsigned short
3698 {
3699  unsigned short year, month, day, hour, minute, second;
3700  getDateTime( year, month, day, hour, minute, second );
3701  return year;
3702 }
3703 
3704 unsigned short
3706 {
3707  unsigned short year, month, day, hour, minute, second;
3708  getDateTime( year, month, day, hour, minute, second );
3709  return month;
3710 }
3711 
3712 unsigned short
3714 {
3715  unsigned short year, month, day, hour, minute, second;
3716  getDateTime( year, month, day, hour, minute, second );
3717  return day;
3718 }
3719 
3720 unsigned short
3722 {
3723  unsigned short year, month, day, hour, minute, second;
3724  getDateTime( year, month, day, hour, minute, second );
3725  return hour;
3726 }
3727 
3728 unsigned short
3730 {
3731  unsigned short year, month, day, hour, minute, second;
3732  getDateTime( year, month, day, hour, minute, second );
3733  return minute;
3734 }
3735 
3736 unsigned short
3738 {
3739  unsigned short year, month, day, hour, minute, second;
3740  getDateTime( year, month, day, hour, minute, second );
3741  return second;
3742 }
3743 
3744 void
3745 dbDateTime::extract(ostream& os) const
3746 {
3747  const unsigned long binTime = (unsigned long)*this;
3748 
3749  if( binTime ) {
3750  unsigned short year,month,day,hour,minute,second;
3751 
3752  ulong2ymdhms(binTime,year,month,day,hour,minute,second);
3753 
3754  if( mFormatMask.length() )
3755  ymdhms2stream(mFormatMask,year,month,day,hour,minute,second,os);
3756  else
3757  ymdhms2stream(year,month,day,hour,minute,second,os);
3758  }
3759 }
3760 
3761 #ifdef __MWERKS__
3762 #pragma mark ## DBDATETIME_CURRENT_TIME
3763 #endif
3764 
3765 ostream&
3766 dbDateTime::now(ostream& os)
3767 {
3768  unsigned short year, month, day, hour, minute, second;
3769  currentTime2ymdhms(year, month, day, hour, minute, second);
3770  return ymdhms2stream(year, month, day, hour, minute, second, os);
3771 }
3772 
3773 void
3774 dbDateTime::currentTime2ymdhms(unsigned short& year, unsigned short& month, unsigned short& day, unsigned short& hour, unsigned short& minute, unsigned short& second)
3775 {
3776  const time_t numTime = time(0);
3777  if (numTime == -1) {
3778 #ifdef OOF_DEBUG
3779  dbConnect::raise("System time not available");
3780 #endif
3781  year = dbDateTime::sBaseYear;
3782  month = day = 1;
3783  hour = minute = second = 0;
3784  }
3785  else {
3786  const tm* timeBits = localtime(&numTime);
3787  second = timeBits->tm_sec;
3788  minute = timeBits->tm_min;
3789  hour = timeBits->tm_hour;
3790  day = timeBits->tm_mday;
3791  month = timeBits->tm_mon + 1; // months since Jan
3792 
3793  assert( dbDateTime::sBaseYear < (unsigned int)(timeBits->tm_year + 1900) );
3794  year = timeBits->tm_year + 1900;
3795  }
3796 }
3797 
3798 dbDateTime
3800 {
3801  dbDateTime ret = dbDateTime(dbField::eFieldIsStandalone); // g++ 2.7 disliked just ret(blah)
3802  ret.setTimeToCurrentTime();
3803  return ret;
3804 }
3805 
3806 unsigned short
3808 {
3809  unsigned short year, month, day, hour, minute, second;
3810  currentTime2ymdhms(year, month, day, hour, minute, second);
3811  return year;
3812 }
3813 
3814 unsigned short
3816 {
3817  unsigned short year, month, day, hour, minute, second;
3818  currentTime2ymdhms(year, month, day, hour, minute, second);
3819  return month;
3820 }
3821 
3822 unsigned short
3824 {
3825  unsigned short year, month, day, hour, minute, second;
3826  currentTime2ymdhms(year, month, day, hour, minute, second);
3827  return day;
3828 }
3829 
3830 unsigned short
3832 {
3833  unsigned short year, month, day, hour, minute, second;
3834  currentTime2ymdhms(year, month, day, hour, minute, second);
3835  return hour;
3836 }
3837 
3838 unsigned short
3840 {
3841  unsigned short year, month, day, hour, minute, second;
3842  currentTime2ymdhms(year, month, day, hour, minute, second);
3843  return minute;
3844 }
3845 
3846 unsigned short
3848 {
3849  unsigned short year, month, day, hour, minute, second;
3850  currentTime2ymdhms(year, month, day, hour, minute, second);
3851  return second;
3852 }
3853 
3854 
3855 #ifdef _Macintosh
3856 void
3858 {
3859  sBaseYear = 1904;
3860  // using this base year means our internal representation will be the same
3861  // as the long values returned by Mac calls such as ::GetDateTime()
3862  // or in file modification dates
3863 }
3864 #endif
3865 
3866 
3867 /* AD980728
3868 unsigned long
3869 operator- (const dbDateTime& time1, const dbDateTime& time2)
3870 {
3871  // return number of seconds
3872  const unsigned long ret = time1.value() - time2.value();
3873  return ret;
3874 }
3875 */
3876 
3877 
3878 
3879 // -------------------------------------------------------
3880 // o o f D a t e
3881 // -------------------------------------------------------
3883  dbDate(dbField::eFieldIsStandalone)
3884 {}
3885 
3886 
3887 oofDate::oofDate(const char* initialDate) :
3888  dbDate(dbField::eFieldIsStandalone)
3889 {
3890  dbDate::operator=(initialDate);
3891 }
3892 
3893 
3894 
3895 oofDate::oofDate(const tm& unixTime ) :
3896  dbDate(dbField::eFieldIsStandalone)
3897 {
3898  setDate(unixTime);
3899 }
3900 
3901 
3902 
3903 oofDate::oofDate(const dbDate& rhs) :
3904  dbDate(dbField::eFieldIsStandalone)
3905 {
3906  dbDate::operator=(rhs);
3907 }
3908 
3909 
3911  dbDate(dbField::eFieldIsStandalone)
3912 {
3913  dbDate::operator=(rhs);
3914 }
3915 
3916 
3917 dbField*
3919 {
3920  return new oofDate(*this);
3921 }
3922 
3923 
3924 #ifdef __MWERKS__
3925 #pragma mark ## OOFTIME
3926 #endif
3927 
3928 // -------------------------------------------------------
3929 // o o f T i m e
3930 // -------------------------------------------------------
3932  dbTime(dbField::eFieldIsStandalone)
3933 {}
3934 
3935 
3936 oofTime::oofTime(const char* initialTime) :
3937  dbTime(dbField::eFieldIsStandalone)
3938 {
3939  dbTime::operator=(initialTime);
3940 }
3941 
3942 
3943 oofTime::oofTime(const dbTime& rhs) :
3944  dbTime(dbField::eFieldIsStandalone)
3945 {
3946  dbTime::operator=(rhs);
3947 }
3948 
3949 
3951  dbTime(dbField::eFieldIsStandalone)
3952 {
3953  dbTime::operator=(rhs);
3954 }
3955 
3956 
3957 dbField*
3959 {
3960  return new oofTime(*this);
3961 }
3962 
3963 #ifdef __MWERKS__
3964 #pragma mark ## OOFDATETIME
3965 #endif
3966 
3967 // -------------------------------------------------------
3968 // o o f D a t e T i m e
3969 // -------------------------------------------------------
3971  dbDateTime(dbField::eFieldIsStandalone)
3972 {}
3973 
3974 
3975 oofDateTime::oofDateTime(const char* initialTime) :
3976  dbDateTime(dbField::eFieldIsStandalone)
3977 {
3978  dbDateTime::operator=(initialTime);
3979 }
3980 
3981 
3982 oofDateTime::oofDateTime(const tm& unixTime ) :
3983  dbDateTime(dbField::eFieldIsStandalone)
3984 {
3985  setDateTime(unixTime);
3986 }
3987 
3988 
3990  dbDateTime(dbField::eFieldIsStandalone)
3991 {
3992  dbDateTime::operator=(rhs);
3993 }
3994 
3995 
3997  dbDateTime(dbField::eFieldIsStandalone)
3998 {
3999  dbDateTime::operator=(rhs);
4000 }
4001 
4002 
4003 dbField*
4005 {
4006  return new oofDateTime(*this);
4007 }
void skipStreamPattern(istream &, const char *)
Definition: oof5.cpp:1743
static bool istream2ymd(std::istream &is, unsigned short &, unsigned short &, unsigned short &, dateFieldOrder theOrder=dbDate::sDefaultDateOrder)
dbQueryBinary operator>(const char *) const
Definition: oof5.cpp:2742
Definition: oof4.h:29
unsigned short month() const
Definition: oof5.cpp:1703
static unsigned short currentHour()
Definition: oof5.cpp:2522
void setDaynum(unsigned long)
Definition: oof5.cpp:1687
virtual void extract(std::ostream &os) const
Definition: oof5.cpp:2466
static bool str2dhmsm(const char *str, short &day, unsigned short &hour, unsigned short &minute, unsigned short &second, unsigned short &millisecond)
Definition: oof5.cpp:2196
void setStr255(const Str255 s)
Definition: oof5.cpp:3632
static bool checkTime(short day, unsigned short hour, unsigned short minute, unsigned short second, unsigned short millisecond)
Definition: oof5.cpp:2036
unsigned short day() const
Definition: oof5.cpp:1696
unsigned short second() const
Definition: oof5.cpp:3737
unsigned long operator-(const dbDateTime &) const
Definition: oof5.cpp:2656
static oofString sDefaultFormatMask
Definition: oof4.h:1102
dbQueryTrinary outside(long, long) const
Definition: oof4.cpp:56
dbQueryBinary operator==(long) const
Definition: oof4.cpp:64
static short vlen[NUMTOKENS]
Definition: oof5.cpp:86
static unsigned short currentSecond()
Definition: oof5.cpp:3847
Definition: oof4.h:26
unsigned short month() const
Definition: oof5.cpp:3705
unsigned long getDateTime() const
Definition: oof4.h:2127
static void raise(std::ostream &, bool terminateAfterMsg=true)
char s[SLEN]
Definition: oof4.h:41
virtual void copyValueIfDifferent(const dbField *)
Definition: oof5.cpp:3552
unsigned short day() const
Definition: oof5.cpp:3713
Definition: oof4.h:29
#define MAXTOKENS
Definition: oof5.cpp:74
dbQueryTrinary between(long, long) const
Definition: oof4.cpp:48
static void month2str(unsigned short monthnum, char *monthname, bool isshort=true, bool isupper=false)
Definition: oof5.cpp:664
void setDate(unsigned long)
Definition: oof5.cpp:1061
dbQueryBinary operator<=(const char *) const
Definition: oof5.cpp:957
unsigned long value() const
Definition: oof4.h:1696
virtual void copyValueFrom(const dbField *)
Definition: oof5.cpp:2276
virtual const oofString & fieldName() const
Definition: oof3.h:769
virtual dbDate & operator++()
Definition: oof5.cpp:1644
precompilation header.
dbQueryTrinary outside(const char *, const char *) const
Definition: oof5.cpp:921
static dbTime currentTime()
Definition: oof5.cpp:2514
const unsigned long kMilliSecondsInDay
Definition: oof5.cpp:97
Definition: oof4.h:30
dbDateCalculator * calculator() const
Definition: oof4.h:1689
virtual dbQueryLiteral * makeQueryLiteral(long) const
Definition: oof4.cpp:486
Tries to hide the different platforms and version issues with standard IO.
Definition: oof4.h:27
Definition: oof4.h:32
static std::ostream & now(std::ostream &os)
Definition: oof5.cpp:2488
static unsigned long ymd2daynum(unsigned short, unsigned short, unsigned short)
Definition: oof5.cpp:1588
static dateFieldOrder sDefaultDateOrder
Definition: oof4.h:692
Definition: oof4.h:26
static unsigned long str2Long(const char *, dateFieldOrder theOrder=dbDate::sDefaultDateOrder)
Definition: oof5.cpp:1322
Highest level used to assemble queries.
Definition: oofquery.h:46
dbDate & calculateWith(dbDateCalculator *adoptedCalculator, bool useOnlyForDefaults=false)
Definition: oof5.cpp:284
Definition: oof4.h:31
dbQueryBinary operator<(const char *) const
Definition: oof5.cpp:1910
Definition: oof4.h:29
dbQueryBinary operator!=(const char *) const
Definition: oof5.cpp:943
void setStr255(const Str255 s)
Definition: oof5.cpp:1094
virtual OOF_fieldTypes nativeType() const
Definition: oof5.cpp:341
dbQueryBinary operator!=(const char *) const
Definition: oof5.cpp:1903
unsigned short year() const
Definition: oof5.cpp:3697
dbQueryTrinary between(const char *, const char *) const
Definition: oof5.cpp:2697
Definition: oof4.h:29
Definition: oof4.h:26
bool skipRestOfField(std::istream &, char fieldSep=dbTable::kFieldSep, char recSep=dbTable::kRecSep)
virtual bool insert(std::istream &, char fieldSep, char recSep)
Definition: oof5.cpp:2336
static unsigned short currentMinute()
Definition: oof5.cpp:2530
bool fieldIsStandalone() const
Definition: oof3.h:733
unsigned short second() const
Definition: oof5.cpp:2445
static unsigned int sBaseYear
Definition: oof4.h:933
virtual OOF_fieldTypes nativeType() const
Definition: oof5.cpp:2820
virtual OOF_fieldTypes fieldType() const
Definition: oof5.cpp:334
void getDate(unsigned short &year, unsigned short &month, unsigned short &day) const
Definition: oof5.cpp:1202
static unsigned long ymdhms2ulong(unsigned short year, unsigned short month, unsigned short day, unsigned short hour=0, unsigned short minute=0, unsigned short second=0)
Definition: oof5.cpp:2958
Definition: oof4.h:28
void setDateToCurrentDate()
Definition: oof5.cpp:1153
long getTime() const
Definition: oof4.h:1933
Definition: oof4.h:28
static bool str2ymdhms(const char *str, unsigned short &year, unsigned short &month, unsigned short &day, unsigned short &hour, unsigned short &minute, unsigned short &second)
Definition: oof5.cpp:3390
static std::ostream & now(std::ostream &os)
Definition: oof5.cpp:3766
OOF_tableBackend * mBackend
Definition: oof3.h:155
Persistent base for fields which can be represented as numbers.
Definition: oof4.h:166
Definition: oof3.h:26
Calculator attached to a dbDate field.
Definition: oof4.h:121
static std::ostream & hms2stream(unsigned short hour, unsigned short minute, unsigned short second, std::ostream &os)
virtual dbField * clone() const
Definition: oof5.cpp:4004
virtual OOF_fieldTypes fieldType() const
Definition: oof5.cpp:2004
virtual OOF_fieldTypes fieldType() const
Definition: oof5.cpp:2814
void index(const OOF_IndexOptions=kIndexed)
Definition: oof3.cpp:212
dbQueryBinary operator>(const char *) const
Definition: oof5.cpp:964
virtual void copyValueIfDifferent(const dbField *)
Definition: oof5.cpp:2291
static void daynum2ymd(unsigned long, unsigned short &, unsigned short &, unsigned short &)
Definition: oof5.cpp:1610
static unsigned short prevCenturyThreshold()
Definition: oof4.h:1869
Common trinary query for field, eg: People.Salary.between(50000, 90000); Very similar to dbQueryBinar...
Definition: oofquery.h:263
Definition: oof4.h:32
dbQueryBinary operator!=(const char *) const
Definition: oof5.cpp:2724
virtual void setString(const char *)
Definition: oof5.cpp:3652
Definition: oof4.h:28
static bool checkDate(unsigned short year, unsigned short month, unsigned short day)
Definition: oof5.cpp:1353
virtual void CopyCalculatedValueToBuffer()
Definition: oof5.cpp:2028
static OOF_TOKENTYPE tokenMap[NUMDATETOKENS]
Definition: oof4.h:738
OOF_String mFormatMask
Definition: oof4.h:253
virtual dbQueryClause * valueAsQueryLiteral() const
Definition: oof5.cpp:1888
dbDateTime & operator+=(long numDays)
Definition: oof5.cpp:2618
static unsigned long str2ulong(const char *str)
Definition: oof5.cpp:3373
static std::ostream & ymd2Stream(unsigned short, unsigned short, unsigned short, std::ostream &os)
dateFieldOrder
Definition: oof4.h:579
virtual dbDateTime & operator++()
Definition: oof5.cpp:2626
OOF_TOKENTYPE token
Definition: oof4.h:39
Definition: oof4.h:28
const unsigned long kSecondsInMinute
Definition: oof5.cpp:100
dbQueryBinary operator<(const char *) const
Definition: oof5.cpp:2730
static unsigned short nextCenturyThreshold()
Definition: oof4.h:1862
static bool istream2ymdhms(std::istream &is, unsigned short &year, unsigned short &month, unsigned short &day, unsigned short &hour, unsigned short &minute, unsigned short &second, dbDate::dateFieldOrder)
virtual unsigned long fieldStorageLen() const
Definition: oof5.cpp:300
Definition: oof4.h:26
dbQueryBinary operator>=(const char *) const
Definition: oof5.cpp:971
Definition: oof4.h:26
int value
Definition: oof4.h:40
static unsigned short currentYear()
Definition: oof5.cpp:3807
dbDate(const OOF_IndexOptions indexOptions)
Definition: oof5.cpp:235
dbDateTime(const char *fieldName=0)
Definition: oof5.cpp:2571
virtual OOF_fieldTypes nativeType() const
Definition: oof5.cpp:2010
dbQueryBinary operator<=(const char *) const
Definition: oof5.cpp:2736
static unsigned short sPrevCenturyThreshold
Definition: oof4.h:740
dbQueryBinary operator<=(long) const
Definition: oof4.cpp:85
virtual dbQueryClause * valueAsQueryLiteral() const
Definition: oof5.cpp:928
Token used in parsing date or time strings.
Definition: oof4.h:38
virtual bool insert(std::istream &, char fieldSep, char recSep)
Definition: oof5.cpp:3598
Definition: oof4.h:27
Exception for database field operations with descriptive error numbers.
Definition: oofexcep.h:218
dbDateTime & operator-=(long numDays)
Definition: oof5.cpp:2642
unsigned short minute() const
Definition: oof5.cpp:3729
unsigned short minute() const
Definition: oof5.cpp:2435
dbQueryBinary operator==(const char *) const
Definition: oof5.cpp:1896
Common binary query for field, eg: People.Salary > 90000.
Definition: oofquery.h:165
Definition: oof4.h:30
virtual dbField * clone() const
Definition: oof5.cpp:3958
dbQueryBinary operator>=(long) const
Definition: oof4.cpp:99
Definition: oof4.h:29
virtual void copyValueFrom(const dbField *)
Definition: oof5.cpp:3540
virtual void generateTestData(bool generateRandom, unsigned long seedOrCount)
Definition: oof5.cpp:2209
virtual void copyValueFrom(const dbField *)
Definition: oof5.cpp:307
Use to have local non-persistent variable of type dbDateTime.
Definition: oof4.h:1360
Definition: oof4.h:44
dbTime & operator-=(long)
Definition: oof5.cpp:1840
dbCalculator * mCalculator
Definition: oof3.h:158
static unsigned short currentHour()
Definition: oof5.cpp:3831
static unsigned short currentDay()
Definition: oof5.cpp:3823
static unsigned short adjustShortYear(unsigned short inYear)
Definition: oof5.cpp:1185
virtual dbTime & operator++()
Definition: oof5.cpp:1819
static oofString sDefaultFormatMask
Definition: oof4.h:741
virtual dbField * clone() const
Definition: oof5.cpp:274
void getStr255(Str255 s) const
Definition: oofstr.cpp:414
dbDateTime & calculateWith(dbDateTimeCalculator *adoptedCalculator, bool useOnlyForDefaults=false)
Definition: oof5.cpp:2830
dbQueryBinary operator!=(long) const
Definition: oof4.cpp:71
static void currentDate2ymd(unsigned short &, unsigned short &, unsigned short &)
Definition: oof5.cpp:1274
long operator-(const dbTime &) const
Definition: oof5.cpp:1847
virtual void setString(const char *)
Definition: oof5.cpp:1138
dbTimeCalculator * calculator() const
Definition: oof4.h:1927
static bool checkTime(unsigned short year, unsigned short month, unsigned short day, unsigned short hour, unsigned short minute, unsigned short second)
Definition: oof5.cpp:2846
Definition: oof4.h:29
static OOF_TOKENTYPE tokenMap[NUMDATETIMETOKENS]
Definition: oof4.h:1101
Definition: oof4.h:29
static unsigned short currentCentury()
Definition: oof5.cpp:1293
virtual ~dbTime()
Definition: oof5.cpp:1800
Definition: oof4.h:30
dbQueryTrinary outside(const char *, const char *) const
Definition: oof5.cpp:1881
Use to have local non-persistent variable of type dbTime.
Definition: oof4.h:1338
static std::ostream & ymdhms2stream(unsigned short year, unsigned short month, unsigned short day, unsigned short hour, unsigned short minute, unsigned short second, std::ostream &os)
Definition: oof4.h:30
static unsigned long ymd2Long(unsigned short, unsigned short, unsigned short)
Definition: oof5.cpp:1210
virtual bool insert(std::istream &, char fieldSep, char recSep)
Definition: oof5.cpp:363
Definition: oof4.h:31
static void currentTime2hms(unsigned short &, unsigned short &, unsigned short &)
Definition: oof5.cpp:2496
void getStr255(Str255 s) const
Definition: oof5.cpp:1086
static long dhmsm2long(short day, unsigned short hour, unsigned short minute, unsigned short second, unsigned short millisecond)
Definition: oof5.cpp:2077
static void currentTime2ymdhms(unsigned short &year, unsigned short &month, unsigned short &day, unsigned short &hour, unsigned short &minute, unsigned short &second)
Definition: oof5.cpp:3774
static dbDate currentDate()
Definition: oof5.cpp:1265
static void setMacCompatibleBaseYear()
Definition: oof5.cpp:3857
Definition: oof3.h:26
virtual void generateTestData(bool generateRandom, unsigned long seedOrCount)
Definition: oof5.cpp:3464
oofTime()
Definition: oof5.cpp:3931
unsigned long length() const
Primary test: oofStringTest::emptyStringByNullInitIsLenZero()
Definition: oofstr.h:447
dbDateTimeCalculator * calculator() const
Definition: oof4.h:2120
dbDate operator+(long) const
Definition: oof5.cpp:1256
Abstract interface to database backend.
Definition: oof1.h:1047
static char * vocab[NUMTOKENS]
Definition: oof5.cpp:79
static unsigned short daysInMonth(unsigned short year, unsigned short month)
Definition: oof5.cpp:3421
#define NUMTOKENS
Definition: oof5.cpp:73
virtual unsigned long fieldStorageLen() const
Definition: oof5.cpp:2808
dbDate & operator=(const char *str)
Definition: oof5.cpp:1034
static unsigned short ymd2dow(unsigned short, unsigned short, unsigned short)
Definition: oof5.cpp:543
long value() const
Definition: oof4.h:1939
Definition: oof4.h:28
static std::ostream & today(std::ostream &os)
Definition: oof5.cpp:383
dbQueryBinary operator<=(const char *) const
Definition: oof5.cpp:1917
Persistent field used to store a date and time.
Definition: oof4.h:929
oofDate()
Definition: oof5.cpp:3882
static void long2dhmsm(long binaryTime, short &day, unsigned short &hour, unsigned short &minute, unsigned short &second, unsigned short &millisecond)
Definition: oof5.cpp:2058
static unsigned short currentMonth()
Definition: oof5.cpp:3815
void setDateTime(unsigned long numberSecondsSinceBaseDate)
Definition: oof5.cpp:3494
unsigned long daynum() const
Definition: oof5.cpp:1678
static void ymd2dayname(unsigned short, unsigned short, unsigned short, char *dayname, bool isshort=true, bool isupper=false)
Definition: oof5.cpp:557
dbQueryBinary operator>=(const char *) const
Definition: oof5.cpp:2748
dbQueryBinary operator>(const char *) const
Definition: oof5.cpp:1924
static unsigned short currentYear()
Definition: oof5.cpp:1734
hourT
Definition: oof4.h:44
dbQueryBinary operator>=(const char *) const
Definition: oof5.cpp:1931
OOF_fieldTypes
Definition: oof3.h:26
static unsigned short currentMinute()
Definition: oof5.cpp:3839
virtual void setNumber(long)
Definition: oof5.cpp:3486
virtual void writeLong(long, const dbField *)=0
Definition: oof4.h:26
static dbDateTime currentTime()
Definition: oof5.cpp:3799
Definition: oof4.h:27
static unsigned long secsInYear(unsigned short year)
Definition: oof5.cpp:3401
#define SLEN
Definition: oof4.h:25
static void ddth(unsigned short daynum, char *ddth, bool isupper=false)
Definition: oof5.cpp:840
#define RAISE_EXCEPTION(E)
Macro to allow us to either throw an exception or call dbConnect::raise.
Definition: oofexcep.h:31
Calculator attached to a dbTime field.
Definition: oof4.h:143
virtual void extract(std::ostream &os) const
Definition: oof5.cpp:348
dbDate & operator+=(long)
Definition: oof5.cpp:1662
Definition: oof4.h:26
Declare query classes.
static unsigned short str2month(const char *)
Definition: oof5.cpp:1551
Definition: oof3.h:26
Persistent field used to store a date.
Definition: oof4.h:577
dbTime & operator=(const char *str)
Definition: oof5.cpp:2310
dbQueryBinary operator==(const char *) const
Definition: oof5.cpp:2718
dbTime & calculateWith(dbTimeCalculator *adoptedCalculator, bool useOnlyForDefaults=false)
Definition: oof5.cpp:2020
Portable highly capable string class.
Definition: oofstr.h:101
long operator-(const dbDate &) const
Definition: oof5.cpp:1235
unsigned short hour() const
Definition: oof5.cpp:2425
static unsigned short currentMonth()
Definition: oof5.cpp:1726
static long str2long(const char *str)
Definition: oof5.cpp:2178
Definition: oof4.h:30
dbDateTime & operator=(const char *str)
Definition: oof5.cpp:3569
virtual void copyValueIfDifferent(const dbField *)
Definition: oof5.cpp:319
Definition: oof4.h:28
bool skipTillDigitAmPm(istream &is, hourT &hourMod, char fieldSep, char recSep)
Definition: oof5.cpp:104
Definition: oof4.h:27
dbQueryBinary operator>(long) const
Definition: oof4.cpp:92
const unsigned long kSecondsInDay
Definition: oof5.cpp:98
Use to have local non-persistent variable of type dbDate.
Definition: oof4.h:1186
virtual dbDate & operator--()
Definition: oof5.cpp:1653
const oofString & formatMask() const
Definition: oof4.h:1381
virtual ~dbDate()
Definition: oof5.cpp:268
static unsigned short sNextCenturyThreshold
Definition: oof4.h:739
Definition: oof4.h:28
dbQueryTrinary outside(const char *, const char *) const
Definition: oof5.cpp:2703
static void parseMask(const char *s, TOKEN *r, const OOF_TOKENTYPE *map, unsigned int len)
Definition: oof5.cpp:193
unsigned long operator+(const dbDateTime &) const
Definition: oof5.cpp:2649
unsigned short year() const
Definition: oof5.cpp:1710
Definition: oof4.h:29
Persistent field used to store a time without date.
Definition: oof4.h:751
Calculator attached to a dbDateTime field.
Definition: oof4.h:154
oofDateTime()
Definition: oof5.cpp:3970
virtual unsigned long fieldStorageLen() const
Definition: oof5.cpp:1998
void CalculateWith(dbCalculator *adoptedCalculator, bool useOnlyForDefaults)
Definition: oof3.cpp:444
virtual void setNumber(long)
Definition: oof5.cpp:1131
OOF_IndexOptions
type used to specify index options for dbField's.
Definition: oof1.h:236
static unsigned short istream2month(std::istream &)
Definition: oof5.cpp:1525
static bool istream2dhmsm(std::istream &is, short &day, unsigned short &hour, unsigned short &minute, unsigned short &second, unsigned short &millisecond)
Definition: oof4.h:26
Definition: oof4.h:28
Definition: oof4.h:28
virtual void CopyCalculatedValueToBuffer()
Definition: oof5.cpp:2838
OOF_TOKENTYPE
Definition: oof4.h:26
static void long2ymd(unsigned long binaryDate, unsigned short &, unsigned short &, unsigned short &)
Definition: oof5.cpp:1224
void setTimeToCurrentTime()
Definition: oof5.cpp:2267
virtual oofString copyString() const
Definition: oof3.cpp:472
virtual ~dbDateTime()
Definition: oof5.cpp:2599
dbQueryBinary operator<(const char *) const
Definition: oof5.cpp:950
Definition: oof4.h:44
void setTime(long)
Stores the value in the mBackend pointer for use in the lightweight subclass oofTime when the field s...
Definition: oof5.cpp:2226
FieldIsStandaloneT
Definition: oof3.h:65
dbDate & operator-=(long)
Definition: oof5.cpp:1671
virtual OOF_fieldTypes fieldType() const =0
static void ulong2ymdhms(long binaryTime, unsigned short &year, unsigned short &month, unsigned short &day, unsigned short &hour, unsigned short &minute, unsigned short &second)
Definition: oof5.cpp:2892
unsigned short hour() const
Definition: oof5.cpp:3721
dbTime operator+(long) const
Definition: oof5.cpp:1862
virtual void generateTestData(bool generateRandom, unsigned long seedOrCount)
Definition: oof5.cpp:893
void getStr255(Str255 s) const
Definition: oof5.cpp:3624
void setTimeToCurrentTime()
Definition: oof5.cpp:3531
static unsigned long secsInMonth(unsigned short year, unsigned short month)
Definition: oof5.cpp:3413
Definition: oof4.h:30
Definition: oof4.h:27
dbTime(const char *fieldName=0)
Definition: oof5.cpp:1773
Definition: oof4.h:32
Definition: oof4.h:44
dbQueryTrinary between(const char *, const char *) const
Definition: oof5.cpp:914
Definition: oof4.h:30
bool skipTillDigit(std::istream &, char fieldSep=dbTable::kFieldSep, char recSep=dbTable::kRecSep)
dbTime & operator+=(long)
Definition: oof5.cpp:1833
Definition: oof4.h:29
static bool isLeapYear(unsigned short year)
Definition: oof5.cpp:1392
static TOKEN get_token(const char **s, const OOF_TOKENTYPE *m, unsigned int len)
Definition: oof5.cpp:142
static bool str2ymd(const char *, unsigned short &, unsigned short &, unsigned short &, dateFieldOrder theOrder=dbDate::sDefaultDateOrder)
Definition: oof5.cpp:1310
dbQueryTrinary between(const char *, const char *) const
Definition: oof5.cpp:1874
virtual void extract(std::ostream &os) const
Definition: oof5.cpp:3745
virtual void CopyCalculatedValueToBuffer()
Definition: oof5.cpp:292
virtual dbField * clone() const
Definition: oof5.cpp:3918
virtual dbDateTime & operator--()
Definition: oof5.cpp:2634
virtual dbField * clone() const
Definition: oof5.cpp:1805
static unsigned short currentSecond()
Definition: oof5.cpp:2538
short day() const
Definition: oof5.cpp:2414
dbQueryBinary operator==(const char *) const
Definition: oof5.cpp:936
virtual dbField * clone() const
Definition: oof5.cpp:2604
unsigned short millisecond() const
Definition: oof5.cpp:2455
Base class for persistent fields in dbTable's.
Definition: oof3.h:63
dbQueryBinary operator<(long) const
Definition: oof4.cpp:78
virtual dbQueryClause * valueAsQueryLiteral() const
Definition: oof5.cpp:2710
static oofString sDefaultFormatMask
Definition: oof4.h:912
Definition: oof4.h:29
Definition: oof4.h:26
const unsigned long kSecondsInHour
Definition: oof5.cpp:99
static unsigned short currentDay()
Definition: oof5.cpp:1717
virtual dbTime & operator--()
Definition: oof5.cpp:1826
unsigned long value() const
Definition: oof4.h:2134