1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "stdafx.h"
17 
18 #include <string>
19 #include <exception>
20 #include <cassert>
21 #include <memory>
22 
23 #ifndef WIN32
24 #include <sys/time.h>
25 #else
26 #include <sys/timeb.h>
27 #include <time.h>
28 #endif
29 
30 #include "zorbautils/hashfun.h"
31 #include <zorbatypes/datetime.h>
32 #include <zorbatypes/duration.h>
33 #include <zorbatypes/timezone.h>
34 #include <zorbatypes/zorbatypes_decl.h>
35 #include <zorbatypes/zstring.h>
36 
37 #include "zorbatypes/datetime/parse.h"
38 
39 #include "util/ascii_util.h"
40 
41 
42 namespace zorba
43 {
44 
45 static const char separators[] = { '-', '-', 'T', ':', ':', '.'};
46 
47 static const char min_length[] = { 4, 2, 2, 2, 2, 2, 0};
48 
49 
50 const int DateTime::FACET_MEMBERS[][8] =
51 {
52   { 1, 1, 1, 1, 1, 1, 1, 0},    // DATETIME_FACET = 0,
53   { 1, 1, 1, 0, 0, 0, 0, 0},    // DATE_FACET = 1,
54   { 0, 0, 0, 1, 1, 1, 1, 0},    // TIME_FACET = 2,
55   { 1, 1, 0, 0, 0, 0, 0, 0},    // GYEARMONTH_FACET = 3
56   { 1, 0, 0, 0, 0, 0, 0, 0},    // GYEAR_FACET = 4
57   { 0, 1, 0, 0, 0, 0, 0, 0},    // GMONTH_FACET = 5
58   { 0, 1, 1, 0, 0, 0, 0, 0},    // GMONTHDAY_FACET = 6
59   { 0, 0, 1, 0, 0, 0, 0, 0}     // GDAY_FACET = 7
60 };
61 
62 
63 const int DateTime::FRAC_SECONDS_UPPER_LIMIT = 1000000;
64 
65 
DateTime()66 DateTime::DateTime()
67   :
68   facet(DATETIME_FACET)
69 {
70   init();
71 }
72 
73 
init()74 void DateTime::init()
75 {
76   facet = DATETIME_FACET;
77 
78   for (int i = YEAR_DATA; i <= DAY_DATA; i++)
79     data[i] = 1;
80 
81   for (int i = HOUR_DATA; i <= FRACSECONDS_DATA; i++)
82     data[i] = 0;
83 
84   the_time_zone = TimeZone();
85 }
86 
87 
createDateTime(const DateTime * date,const DateTime * time,DateTime & result)88 int DateTime::createDateTime(
89     const DateTime* date,
90     const DateTime* time,
91     DateTime& result)
92 {
93   if (!date->getTimezone().timeZoneNotSet() &&
94       !time->getTimezone().timeZoneNotSet() &&
95       !(date->getTimezone() == time->getTimezone()))
96     return 2;
97 
98   int res = createDateTime(date->getYear(),
99                            date->getMonth(),
100                            date->getDay(),
101                            time->getHours(),
102                            time->getMinutes(),
103                            time->getIntSeconds(),
104                            time->getFractionalSeconds(),
105                            result);
106 
107   if (res == 0)
108   {
109     if (!date->getTimezone().timeZoneNotSet())
110       result.the_time_zone = date->getTimezone();
111     else if (!time->getTimezone().timeZoneNotSet())
112       result.the_time_zone = time->getTimezone();
113   }
114 
115   return res;
116 }
117 
118 
createDateTime(int years,int months,int days,int hours,int minutes,int seconds,int fractional_seconds,DateTime & dt)119 int DateTime::createDateTime(
120     int years,
121     int months,
122     int days,
123     int hours,
124     int minutes,
125     int seconds,
126     int fractional_seconds,
127     DateTime& dt)
128 {
129   dt.facet = DATETIME_FACET;
130   dt.data[YEAR_DATA] = years;
131   dt.data[MONTH_DATA] = abs<int>(months);
132   dt.data[DAY_DATA] = abs<int>(days);
133   dt.data[HOUR_DATA] = abs<int>(hours);
134   dt.data[MINUTE_DATA] = abs<int>(minutes);
135   dt.data[SECONDS_DATA] = abs<int>(seconds);
136   dt.data[FRACSECONDS_DATA] = abs<int>(fractional_seconds);
137   return 0;
138 }
139 
140 
createDateTime(int years,int months,int days,int hours,int minutes,double seconds,const TimeZone * tz,DateTime & dt)141 int DateTime::createDateTime(
142     int years,
143     int months,
144     int days,
145     int hours,
146     int minutes,
147     double seconds,
148     const TimeZone* tz,
149     DateTime& dt)
150 {
151   dt.facet = DATETIME_FACET;
152   dt.data[YEAR_DATA] = years;
153   dt.data[MONTH_DATA] = abs<int>(months);
154   dt.data[DAY_DATA] = abs<int>(days);
155   dt.data[HOUR_DATA] = abs<int>(hours);
156   dt.data[MINUTE_DATA] = abs<int>(minutes);
157   dt.data[SECONDS_DATA] = floor<double>(abs<double>(seconds));
158   dt.data[FRACSECONDS_DATA] = round(frac(abs<double>(seconds)) * FRAC_SECONDS_UPPER_LIMIT);
159 
160   if (tz != NULL)
161     dt.the_time_zone = *tz;
162 
163   return 0;
164 }
165 
166 
createDateTime(int years,int months,int days,int hours,int minutes,int seconds,int fractional_seconds,const TimeZone * tz,DateTime & dt)167 int DateTime::createDateTime(
168     int years,
169     int months,
170     int days,
171     int hours,
172     int minutes,
173     int seconds,
174     int fractional_seconds,
175     const TimeZone* tz,
176     DateTime& dt)
177 {
178   dt.facet = DATETIME_FACET;
179   dt.data[YEAR_DATA] = years;
180   dt.data[MONTH_DATA] = abs<int>(months);
181   dt.data[DAY_DATA] = abs<int>(days);
182   dt.data[HOUR_DATA] = abs<int>(hours);
183   dt.data[MINUTE_DATA] = abs<int>(minutes);
184   dt.data[SECONDS_DATA] = abs<int>(seconds);
185   dt.data[FRACSECONDS_DATA] = abs<int>(fractional_seconds);
186 
187   if (tz != NULL)
188     dt.the_time_zone = *tz;
189 
190   return 0;
191 }
192 
193 
createDate(int years,int months,int days,const TimeZone * tz,DateTime & dt)194 int DateTime::createDate(
195     int years,
196     int months,
197     int days,
198     const TimeZone* tz,
199     DateTime& dt)
200 {
201   dt.facet = DATE_FACET;
202   dt.data[YEAR_DATA] = years;
203   dt.data[MONTH_DATA] = abs<int>(months);
204   dt.data[DAY_DATA] = abs<int>(days);
205   dt.data[HOUR_DATA] = 0;
206   dt.data[MINUTE_DATA] = 0;
207   dt.data[SECONDS_DATA] = 0;
208   dt.data[FRACSECONDS_DATA] = 0;
209 
210   if (tz != NULL)
211     dt.the_time_zone = *tz;
212 
213   return 0;
214 }
215 
216 
createTime(int hours,int minutes,double seconds,const TimeZone * tz,DateTime & dt)217 int DateTime::createTime(
218     int hours,
219     int minutes,
220     double seconds,
221     const TimeZone* tz,
222     DateTime& dt)
223 {
224   dt.facet = TIME_FACET;
225   dt.data[YEAR_DATA] = 1;
226   dt.data[MONTH_DATA] = 1;
227   dt.data[DAY_DATA] = 1;
228   dt.data[HOUR_DATA] = abs<int>(hours);
229   dt.data[MINUTE_DATA] = abs<int>(minutes);
230   dt.data[SECONDS_DATA] = floor<double>(abs<double>(seconds));
231   dt.data[FRACSECONDS_DATA] = round(frac(abs<double>(seconds)) * FRAC_SECONDS_UPPER_LIMIT);
232 
233   if (tz != NULL)
234     dt.the_time_zone = *tz;
235 
236   return 0;
237 }
238 
239 
createGYearMonth(int years,int months,DateTime & dt)240 int DateTime::createGYearMonth(int years, int months, DateTime& dt)
241 {
242   dt.facet = GYEARMONTH_FACET;
243   dt.data[YEAR_DATA] = years;
244   dt.data[MONTH_DATA] = abs<int>(months);
245   dt.data[DAY_DATA] = 1;
246   dt.data[HOUR_DATA] = 0;
247   dt.data[MINUTE_DATA] = 0;
248   dt.data[SECONDS_DATA] = 0;
249   dt.data[FRACSECONDS_DATA] = 0;
250 
251   return 0;
252 }
253 
254 
createGYear(int years,DateTime & dt)255 int DateTime::createGYear(int years, DateTime& dt)
256 {
257   dt.facet = GYEAR_FACET;
258   dt.data[YEAR_DATA] = years;
259   dt.data[MONTH_DATA] = 1;
260   dt.data[DAY_DATA] = 1;
261   dt.data[HOUR_DATA] = 0;
262   dt.data[MINUTE_DATA] = 0;
263   dt.data[SECONDS_DATA] = 0;
264   dt.data[FRACSECONDS_DATA] = 0;
265 
266   return 0;
267 }
268 
269 
createGMonth(int months,DateTime & dt)270 int DateTime::createGMonth(int months, DateTime& dt)
271 {
272   dt.facet = GMONTH_FACET;
273   dt.data[YEAR_DATA] = 1;
274   dt.data[MONTH_DATA] = abs<int>(months);
275   dt.data[DAY_DATA] = 1;
276   dt.data[HOUR_DATA] = 0;
277   dt.data[MINUTE_DATA] = 0;
278   dt.data[SECONDS_DATA] = 0;
279   dt.data[FRACSECONDS_DATA] = 0;
280 
281   return 0;
282 }
283 
284 
createGMonthDay(int months,int days,DateTime & dt)285 int DateTime::createGMonthDay(int months, int days, DateTime& dt)
286 {
287   dt.facet = GMONTHDAY_FACET;
288   dt.data[YEAR_DATA] = 1;
289   dt.data[MONTH_DATA] = abs<int>(months);
290   dt.data[DAY_DATA] = abs<int>(days);
291   dt.data[HOUR_DATA] = 0;
292   dt.data[MINUTE_DATA] = 0;
293   dt.data[SECONDS_DATA] = 0;
294   dt.data[FRACSECONDS_DATA] = 0;
295 
296   return 0;
297 }
298 
299 
createGDay(int days,DateTime & dt)300 int DateTime::createGDay(int days, DateTime& dt)
301 {
302   dt.facet = GDAY_FACET;
303   dt.data[YEAR_DATA] = 1;
304   dt.data[MONTH_DATA] = 1;
305   dt.data[DAY_DATA] = abs<int>(days);
306   dt.data[HOUR_DATA] = 0;
307   dt.data[MINUTE_DATA] = 0;
308   dt.data[SECONDS_DATA] = 0;
309   dt.data[FRACSECONDS_DATA] = 0;
310 
311   return 0;
312 }
313 
314 
getLocalTime(DateTime & dt)315 int DateTime::getLocalTime(DateTime& dt)
316 {
317   // TODO: check code on windows
318 #ifndef WIN32
319   struct timeval tv;
320   gettimeofday(&tv, NULL);
321   struct tm curr;
322   localtime_r(&tv.tv_sec, &curr);
323   return createDateTime(curr.tm_year + 1900, curr.tm_mon + 1, curr.tm_mday,
324                         curr.tm_hour, curr.tm_min, curr.tm_sec,
325                         round((tv.tv_usec / 1000000.0) * FRAC_SECONDS_UPPER_LIMIT), dt);
326 #else
327 #ifndef WINCE
328   struct _timeb   tb;
329   _ftime_s(&tb);
330 #else
331   struct timeb   tb;
332   ftime(&tb);
333 #endif
334   struct  tm  curr;
335   _localtime64_s(&curr, &tb.time);
336   return createDateTime(curr.tm_year + 1900, curr.tm_mon + 1, curr.tm_mday,
337                         curr.tm_hour, curr.tm_min, curr.tm_sec,
338                         round((tb.millitm / 1000.0) * FRAC_SECONDS_UPPER_LIMIT), dt);
339 #endif
340 
341 }
342 
343 
parseDateTime(const char * str,ascii::size_type strlen,DateTime & dt)344 int DateTime::parseDateTime(const char* str, ascii::size_type strlen, DateTime& dt)
345 {
346   ascii::size_type pos = 0;
347 
348   // DateTime is of form: '-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
349 
350   ascii::skip_whitespace(str, strlen, &pos);
351 
352   dt.facet = DATETIME_FACET;
353 
354   if (parse_date(str,
355                  strlen,
356                  pos,
357                  dt.data[YEAR_DATA],
358                  dt.data[MONTH_DATA],
359                  dt.data[DAY_DATA]))
360     return 1;
361 
362   if (pos == strlen || str[pos++] != 'T')
363     return 1;
364 
365   if (parse_time(str,
366                  strlen,
367                  pos,
368                  dt.data[HOUR_DATA],
369                  dt.data[MINUTE_DATA],
370                  dt.data[SECONDS_DATA],
371                  dt.data[FRACSECONDS_DATA]))
372     return 1;
373 
374   ascii::size_type savepos = pos;
375 
376   ascii::skip_whitespace(str, strlen, &pos);
377 
378   if (savepos != pos && pos != strlen)
379     return 1;
380 
381   if (pos < strlen)
382   {
383     if (0 != TimeZone::parseTimeZone(str + pos,
384                                      strlen - pos,
385                                      dt.the_time_zone))
386       return 1;
387   }
388 
389   if (dt.data[HOUR_DATA] == 24)
390   {
391     dt.data[HOUR_DATA] = 0;
392     std::auto_ptr<DateTime> tmp(dt.addDuration(Duration(Duration::DAYTIMEDURATION_FACET,
393                                                         false, 0, 0, 1, 0, 0, 0)));
394     dt = *tmp;
395   }
396 
397   return 0;
398 }
399 
400 
parseDate(const char * str,ascii::size_type strlen,DateTime & dt)401 int DateTime::parseDate(const char* str, ascii::size_type strlen, DateTime& dt)
402 {
403   TimeZone tz;
404   ascii::size_type pos = 0;
405 
406   ascii::skip_whitespace(str, strlen, &pos);
407 
408   dt.facet = DATE_FACET;
409 
410   if (parse_date(str,
411                  strlen,
412                  pos,
413                  dt.data[YEAR_DATA],
414                  dt.data[MONTH_DATA],
415                  dt.data[DAY_DATA]))
416     return 1;
417 
418   ascii::size_type savepos = pos;
419 
420   ascii::skip_whitespace(str, strlen, &pos);
421 
422   if (savepos != pos && pos != strlen)
423     return 1;
424 
425   if (pos < strlen)
426   {
427     if (0 != TimeZone::parseTimeZone(str + pos, strlen - pos, dt.the_time_zone))
428       return 1;
429   }
430 
431   return 0;
432 }
433 
434 
parseTime(const char * str,ascii::size_type strlen,DateTime & dt)435 int DateTime::parseTime(const char* str, ascii::size_type strlen, DateTime& dt)
436 {
437   ascii::size_type pos = 0;
438 
439   ascii::skip_whitespace(str, strlen, &pos);
440 
441   dt.facet = TIME_FACET;
442 
443   if (parse_time(str, strlen, pos,
444                  dt.data[HOUR_DATA],
445                  dt.data[MINUTE_DATA],
446                  dt.data[SECONDS_DATA],
447                  dt.data[FRACSECONDS_DATA]))
448     return 1;
449 
450   ascii::size_type savepos = pos;
451 
452   ascii::skip_whitespace(str, strlen, &pos);
453 
454   if (savepos != pos && pos != strlen)
455     return 1;
456 
457   if (pos < strlen)
458   {
459     if (0 != TimeZone::parseTimeZone(str + pos, strlen - pos, dt.the_time_zone))
460       return 1;
461   }
462 
463   if (dt.data[HOUR_DATA] == 24)
464     dt.data[HOUR_DATA] = 0;
465 
466   return 0;
467 }
468 
469 
parseGYearMonth(const char * str,ascii::size_type strlen,DateTime & dt)470 int DateTime::parseGYearMonth(const char* str, ascii::size_type strlen, DateTime& dt)
471 {
472   ascii::size_type pos = 0;
473   ascii::size_type temp_pos = 0;
474   zstring temp;
475 
476   // GYearMonth of form: '-'? yyyy '-' mm zzzzzz?
477 
478   ascii::skip_whitespace(str, strlen, &pos);
479 
480   dt.facet = GYEARMONTH_FACET;
481 
482   if (str[pos] == '-')
483   {
484     temp.append(str + pos, (8 < strlen - pos ? 8 : strlen - pos));
485     ++pos;
486   }
487   else
488   {
489     temp.append(str + pos, (7 < strlen - pos ? 7 : strlen - pos));
490   }
491 
492   temp += "-01";
493 
494   if (parse_date(temp.c_str(),
495                  (ulong)temp.size(),
496                  temp_pos,
497                  dt.data[YEAR_DATA],
498                  dt.data[MONTH_DATA],
499                  dt.data[DAY_DATA]))
500     return 1;
501 
502   pos += 7;
503 
504   ascii::size_type savepos = pos;
505 
506   ascii::skip_whitespace(str, strlen, &pos);
507 
508   if (savepos != pos && pos != strlen)
509     return 1;
510 
511   if (pos < strlen)
512   {
513     if (0 != TimeZone::parseTimeZone(str + pos, strlen - pos, dt.the_time_zone))
514       return 1;
515   }
516 
517   return 0;
518 }
519 
520 
parseGYear(const char * str,ascii::size_type strlen,DateTime & dt)521 int DateTime::parseGYear(const char* str, ascii::size_type strlen, DateTime& dt)
522 {
523   ascii::size_type pos = 0;
524   ascii::size_type temp_pos = 0;
525   zstring temp;
526 
527   // GYear of form: '-'? yyyy zzzzzz?
528 
529   ascii::skip_whitespace(str, strlen, &pos);
530 
531   dt.facet = GYEAR_FACET;
532 
533   temp.reserve(12);
534 
535   if (str[pos] == '-')
536   {
537     temp.append(str + pos, (5 < strlen - pos ? 5 : strlen - pos));
538     ++pos;
539   }
540   else
541   {
542     temp.append(str + pos, (4 < strlen - pos ? 4 : strlen - pos));
543   }
544 
545   temp += "-01-01";
546 
547   if (parse_date(temp.c_str(),
548                  (ulong)temp.size(),
549                  temp_pos,
550                  dt.data[YEAR_DATA],
551                  dt.data[MONTH_DATA],
552                  dt.data[DAY_DATA]))
553     return 1;
554 
555   pos += 4;
556 
557   ascii::size_type savepos = pos;
558 
559   ascii::skip_whitespace(str, strlen, &pos);
560 
561   if (savepos != pos && pos != strlen)
562     return 1;
563 
564   if (pos < strlen)
565   {
566     if (0 != TimeZone::parseTimeZone(str + pos, strlen - pos, dt.the_time_zone))
567       return 1;
568   }
569 
570   return 0;
571 }
572 
573 
parseGMonth(const char * str,ascii::size_type strlen,DateTime & dt)574 int DateTime::parseGMonth(const char* str, ascii::size_type strlen, DateTime& dt)
575 {
576   ascii::size_type pos = 0;
577   ascii::size_type temp_pos = 0;
578   zstring temp;
579 
580   // GMonth of form: --MM zzzzzz?
581   // preceding - is not allowed.
582 
583   ascii::skip_whitespace(str, strlen, &pos);
584 
585   dt.facet = GMONTH_FACET;
586 
587   if (str[pos++] != '-')
588     return 1;
589 
590   temp.reserve(12);
591   temp = "0001";
592   temp.append(str + pos, 3);
593   temp += "-01";
594 
595   if (parse_date(temp.c_str(),
596                  (ulong)temp.size(),
597                  temp_pos,
598                  dt.data[YEAR_DATA],
599                  dt.data[MONTH_DATA],
600                  dt.data[DAY_DATA]))
601     return 1;
602 
603   pos += 3;
604 
605   ascii::size_type savepos = pos;
606 
607   ascii::skip_whitespace(str, strlen, &pos);
608 
609   if (savepos != pos && pos != strlen)
610     return 1;
611 
612   if (pos < strlen)
613   {
614     if (0 != TimeZone::parseTimeZone(str + pos, strlen - pos, dt.the_time_zone))
615       return 1;
616   }
617 
618   return 0;
619 }
620 
621 
parseGMonthDay(const char * str,ascii::size_type strlen,DateTime & dt)622 int DateTime::parseGMonthDay(const char* str, ascii::size_type strlen, DateTime& dt)
623 {
624   ascii::size_type pos = 0;
625   ascii::size_type temp_pos = 0;
626   zstring temp;
627 
628   // GMonthDay of form: --MM-DD zzzzzz?
629   // preceding - is not allowed.
630 
631   ascii::skip_whitespace(str, strlen, &pos);
632 
633   dt.facet = GMONTHDAY_FACET;
634 
635   if (str[pos++] != '-')
636     return 1;
637 
638   temp.reserve(12);
639   temp = "0004";
640   temp.append(str + pos, 6); // Year 4 to make it a leap year, to allow the MonthDay of 29 February
641 
642   if (parse_date(temp.c_str(),
643                  (ulong)temp.size(),
644                  temp_pos,
645                  dt.data[YEAR_DATA],
646                  dt.data[MONTH_DATA],
647                  dt.data[DAY_DATA]))
648     return 1;
649 
650   dt.data[YEAR_DATA] = 1;
651 
652   pos += 6;
653 
654   ascii::size_type savepos = pos;
655 
656   ascii::skip_whitespace(str, strlen, &pos);
657 
658   if (savepos != pos && pos != strlen)
659     return 1;
660 
661   if (pos < strlen)
662   {
663     if (0 != TimeZone::parseTimeZone(str + pos, strlen - pos, dt.the_time_zone))
664       return 1;
665   }
666 
667   return 0;
668 }
669 
670 
parseGDay(const char * str,ascii::size_type strlen,DateTime & dt)671 int DateTime::parseGDay(const char* str, ascii::size_type strlen, DateTime& dt)
672 {
673   ascii::size_type pos = 0;
674   ascii::size_type temp_pos = 0;
675   zstring temp;
676 
677   // GDay of form: ---DD zzzzzz?
678   // preceding - is not allowed.
679 
680   ascii::skip_whitespace(str, strlen, &pos);
681 
682   dt.facet = GDAY_FACET;
683 
684   if (str[pos++] != '-')
685     return 1;
686 
687   if (str[pos++] != '-')
688     return 1;
689 
690   temp = "0001-01";
691   temp.append(str + pos, 3);
692 
693   if (parse_date(temp.c_str(),
694                  (ulong)temp.size(),
695                  temp_pos,
696                  dt.data[YEAR_DATA],
697                  dt.data[MONTH_DATA],
698                  dt.data[DAY_DATA]))
699     return 1;
700 
701   pos += 3;
702 
703   ascii::size_type savepos = pos;
704 
705   ascii::skip_whitespace(str, strlen, &pos);
706 
707   if (savepos != pos && pos != strlen)
708     return 1;
709 
710   if (pos < strlen)
711   {
712     if (0 != TimeZone::parseTimeZone(str + pos, strlen - pos, dt.the_time_zone))
713       return 1;
714   }
715 
716   return 0;
717 }
718 
719 
720 // Returns 0 on success
parse_date(const char * str,ascii::size_type strlen,ascii::size_type & pos,long & year,long & month,long & day)721 int DateTime::parse_date(
722     const char* str,
723     ascii::size_type strlen,
724     ascii::size_type& pos,
725     long& year,
726     long& month,
727     long& day)
728 {
729   bool is_negative = false;
730   ascii::size_type temp_pos;
731 
732   if (pos == strlen)
733     return 1;
734 
735   if (str[pos] == '-')
736   {
737     is_negative = true;
738     ++pos;
739   }
740 
741   // Parse year
742   temp_pos = pos;
743 
744   if (pos == strlen || parse_long(str, strlen, pos, year, 4))
745     return 1;
746 
747   if (pos - temp_pos > 4 && str[temp_pos] == '0')
748     return 1;
749 
750   if (is_negative)
751     year = -year;
752 
753   if (pos == strlen || str[pos++] != '-')
754     return 1;
755 
756   // Parse month
757   if (pos == strlen || parse_long(str, strlen, pos, month, 2, 2))
758     return 1;
759 
760   if (pos == strlen || str[pos++] != '-')
761     return 1;
762 
763   // Parse day
764   if (pos == strlen || parse_long(str, strlen, pos, day, 2, 2))
765     return 1;
766 
767   // Validate the date
768   // year may not be 0
769   if (year == 0)
770     return 1;
771 
772   if (month < 1 || month > 12)
773     return 1;
774 
775   if (day < 1 || day > get_last_day(year, month))
776     return 1;
777 
778   return 0;
779 }
780 
781 
782 // Returns 0 on success
parse_time(const char * str,ascii::size_type strlen,ascii::size_type & position,long & hour,long & minute,long & seconds,long & frac_seconds)783 int DateTime::parse_time(
784     const char* str,
785     ascii::size_type strlen,
786     ascii::size_type& position,
787     long& hour,
788     long& minute,
789     long& seconds,
790     long& frac_seconds)
791 {
792   if (position == strlen)
793     return 1;
794 
795   // Parse hour
796   if (position == strlen || parse_long(str, strlen, position, hour, 2, 2))
797     return 1;
798 
799   if (position == strlen || str[position++] != ':')
800     return 1;
801 
802   // Parse minute
803   if (position == strlen || parse_long(str, strlen, position, minute, 2, 2))
804     return 1;
805 
806   if (position == strlen || str[position++] != ':')
807     return 1;
808 
809   // Parse seconds
810   if (position == strlen || parse_long(str, strlen, position, seconds, 2, 2))
811     return 1;
812 
813   if (position < strlen && str[position] == '.')
814   {
815     double temp_frac_seconds;
816     position++;
817 
818     if (parse_frac(str, strlen, position, temp_frac_seconds))
819       return 1;
820 
821     frac_seconds = round(temp_frac_seconds * FRAC_SECONDS_UPPER_LIMIT);
822   }
823   else
824   {
825     frac_seconds = 0;
826   }
827 
828   // Validate the time
829   if (hour > 24)
830     return 1;
831 
832   if (minute > 59)
833     return 1;
834 
835   if (hour == 24 && minute != 0)
836     return 1;
837 
838   if (seconds > 59)
839     return 1;
840 
841   if (hour == 24 && (seconds != 0 || frac_seconds != 0))
842     return 1;
843 
844   return 0;
845 }
846 
847 
848 
operator =(const DateTime * dt)849 DateTime& DateTime::operator=(const DateTime* dt)
850 {
851   facet = dt->facet;
852 
853   for (int i = 0; i < 7; ++i)
854     data[i] = dt->data[i];
855 
856   the_time_zone = dt->the_time_zone;
857   return *this;
858 }
859 
860 
createWithNewFacet(FACET_TYPE new_facet,DateTime & dt) const861 int DateTime::createWithNewFacet(FACET_TYPE new_facet, DateTime& dt) const
862 {
863   dt = *this;
864   dt.setFacet(new_facet);
865   return 0;
866 }
867 
868 
toString() const869 zstring DateTime::toString() const
870 {
871   zstring result;
872 
873   // output sign
874   if (FACET_MEMBERS[facet][0])
875     if (data[YEAR_DATA] < 0)
876       result.append("-", 1);
877 
878   // output preceding '-' for Gregorian dates, when needed
879   if (facet == GMONTH_FACET || facet == GMONTHDAY_FACET)
880     result.append("--", 2);
881   if (facet == GDAY_FACET)
882     result.append("---", 3);
883 
884   for (int i=0; i<=5; i++)
885   {
886     if (FACET_MEMBERS[facet][i])
887     {
888       result.append(to_string(abs<int>(data[i]), min_length[i]));
889       if (FACET_MEMBERS[facet][i+1] && i<=4)
890         result.push_back(separators[i]);
891     }
892   }
893 
894   if (FACET_MEMBERS[facet][FRACSECONDS_DATA] && (data[FRACSECONDS_DATA] != 0))
895   {
896     int temp;
897     result.append(".", 1);
898 
899     // print leading 0s, if any
900     temp = FRAC_SECONDS_UPPER_LIMIT / 10;
901     while (temp > data[FRACSECONDS_DATA] && temp > 0)
902     {
903       result.append("0", 1);
904       temp /= 10;
905     }
906 
907     // strip trailing 0s, if any
908     temp = data[FRACSECONDS_DATA];
909     while (temp%10 == 0 && temp > 0)
910       temp = temp / 10;
911 
912     result.append(to_string(temp));
913   }
914 
915   result.append(the_time_zone.toString());
916 
917   return result;
918 }
919 
920 
getDate() const921 DateTime* DateTime::getDate() const
922 {
923   DateTime* dt = new DateTime(*this);
924   dt->setFacet(DATE_FACET);
925   return dt;
926 }
927 
928 
getTime() const929 DateTime* DateTime::getTime() const
930 {
931   DateTime* dt = new DateTime(*this);
932   dt->setFacet(TIME_FACET);
933   return dt;
934 }
935 
936 
getYear() const937 int DateTime::getYear() const
938 {
939   return data[YEAR_DATA];
940 }
941 
942 
getMonth() const943 int DateTime::getMonth() const
944 {
945   assert(data[MONTH_DATA] >= 0);
946   return data[MONTH_DATA];
947 }
948 
949 
getDay() const950 int DateTime::getDay() const
951 {
952   assert(data[DAY_DATA] >= 0);
953   return data[DAY_DATA];
954 }
955 
956 
getHours() const957 int DateTime::getHours() const
958 {
959   assert(data[HOUR_DATA] >= 0);
960   return data[HOUR_DATA];
961 }
962 
963 
getMinutes() const964 int DateTime::getMinutes() const
965 {
966   assert(data[MINUTE_DATA] >= 0);
967   return data[MINUTE_DATA];
968 }
969 
970 
getSeconds() const971 xs_decimal DateTime::getSeconds() const
972 {
973   return  xs_decimal(data[SECONDS_DATA])
974         + (xs_decimal(data[FRACSECONDS_DATA])
975           / Integer(FRAC_SECONDS_UPPER_LIMIT)
976           );
977 }
978 
979 
getIntSeconds() const980 int DateTime::getIntSeconds() const
981 {
982   assert(data[SECONDS_DATA] >= 0);
983   return data[SECONDS_DATA];
984 }
985 
986 
getFractionalSeconds() const987 int DateTime::getFractionalSeconds() const
988 {
989   assert(data[FRACSECONDS_DATA] >= 0);
990   return data[FRACSECONDS_DATA];
991 }
992 
993 
getTimezone() const994 TimeZone DateTime::getTimezone() const
995 {
996   return the_time_zone;
997 }
998 
999 
compare(const DateTime * dt,long timezone_seconds) const1000 int DateTime::compare(const DateTime* dt, long timezone_seconds) const
1001 {
1002   std::auto_ptr<DateTime> d1_t;
1003   std::auto_ptr<DateTime> d2_t;
1004 
1005   d1_t.reset(normalizeTimeZone(timezone_seconds));
1006   d2_t.reset(dt->normalizeTimeZone(timezone_seconds));
1007 
1008   if (d1_t->data[YEAR_DATA] < d2_t->data[YEAR_DATA])
1009     return -1;
1010   else if (d1_t->data[YEAR_DATA] > d2_t->data[YEAR_DATA])
1011     return 1;
1012 
1013   // compare the rest of the data
1014   if (d1_t->data[YEAR_DATA] < 0 && d2_t->data[YEAR_DATA] < 0)
1015   {
1016     for (int i=1; i<7; i++)
1017     {
1018       if (d1_t->data[i] > d2_t->data[i])
1019         return -1;
1020       else if (d1_t->data[i] < d2_t->data[i])
1021         return 1;
1022     }
1023   }
1024   else
1025   {
1026     for (int i=1; i<7; i++)
1027     {
1028       if (d1_t->data[i] < d2_t->data[i])
1029         return -1;
1030       else if (d1_t->data[i] > d2_t->data[i])
1031         return 1;
1032     }
1033   }
1034 
1035   return 0;
1036 }
1037 
1038 
hash(int implicit_timezone_seconds) const1039 uint32_t DateTime::hash(int implicit_timezone_seconds) const
1040 {
1041   uint32_t hval = 0;
1042   std::auto_ptr<DateTime> dt(normalizeTimeZone(implicit_timezone_seconds));
1043 
1044   hval = hashfun::h32<int>((int)dt->facet, hval);
1045   hval = hashfun::h32<int>(dt->data[YEAR_DATA], hval);
1046   hval = hashfun::h32<int>(dt->data[MONTH_DATA], hval);
1047   hval = hashfun::h32<int>(dt->data[DAY_DATA], hval);
1048   hval = hashfun::h32<int>(dt->data[HOUR_DATA], hval);
1049   hval = hashfun::h32<int>(dt->data[MINUTE_DATA], hval);
1050   hval = hashfun::h32<int>(dt->data[SECONDS_DATA], hval);
1051   hval = hashfun::h32<int>(dt->data[FRACSECONDS_DATA], hval);
1052 
1053   hval = dt->the_time_zone.hash(hval);
1054 
1055   return hval;
1056 }
1057 
1058 
toDayTimeDuration() const1059 Duration* DateTime::toDayTimeDuration() const
1060 {
1061   if (data[YEAR_DATA] >= 0)
1062     return new Duration(Duration::DAYTIMEDURATION_FACET, false, 0, 0,
1063                         365 * (abs<int>(data[YEAR_DATA]) - 1) +
1064                           leap_years_count(data[YEAR_DATA]) +
1065                           DateTime::getDayOfYear(data[YEAR_DATA],
1066                             data[MONTH_DATA],
1067                             data[DAY_DATA])-1,
1068                         data[HOUR_DATA],
1069                         data[MINUTE_DATA],
1070                         data[SECONDS_DATA],
1071                         data[FRACSECONDS_DATA]);
1072   else
1073   {
1074     Duration days(Duration::DAYTIMEDURATION_FACET, true, 0, 0,
1075                          365 * abs<int>(data[YEAR_DATA]) -
1076                          leap_years_count(data[YEAR_DATA]) -
1077                          DateTime::getDayOfYear(data[YEAR_DATA],
1078                                                data[MONTH_DATA],
1079                                                data[DAY_DATA])-1,
1080                          0, 0, 0, 0);
1081 
1082     Duration remainder(Duration::DAYTIMEDURATION_FACET, false, 0, 0, 0,
1083                               data[HOUR_DATA],
1084                               data[MINUTE_DATA],
1085                               data[SECONDS_DATA],
1086                               data[FRACSECONDS_DATA]);
1087 
1088     return days + remainder;
1089   }
1090 }
1091 
1092 
addDuration(const Duration & d,bool adjust_facet) const1093 DateTime* DateTime::addDuration(const Duration& d, bool adjust_facet) const
1094 {
1095   DateTime* new_dt = NULL;
1096   int years, months, days, hours, minutes, int_seconds, frac_seconds, temp_days, carry;
1097   int temp_frac_seconds, total_seconds;
1098 
1099   // For the algorithm, see XML Schema 2 spec, Appendix E
1100   // http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes
1101 
1102   months = modulo<int>(data[MONTH_DATA] + d.getMonths() - 1, 12) + 1;
1103 
1104   years = data[YEAR_DATA] + d.getYears() +
1105           quotient<int>(data[MONTH_DATA] + d.getMonths() - 1, 12);
1106 
1107   //int_seconds = modulo<int>(floor(getSeconds() + d.getSeconds()), 60);
1108   temp_frac_seconds = getFractionalSeconds() + d.getFractionalSeconds();
1109   total_seconds = getIntSeconds() + d.getIntSeconds() + quotient<int>(temp_frac_seconds, DateTime::FRAC_SECONDS_UPPER_LIMIT);
1110   int_seconds = modulo<int>(total_seconds, 60);
1111 
1112   frac_seconds = modulo<int>(temp_frac_seconds, DateTime::FRAC_SECONDS_UPPER_LIMIT);
1113 
1114   minutes = data[MINUTE_DATA] + d.getMinutes() + quotient<int>(total_seconds, 60);
1115 
1116   hours = data[HOUR_DATA] + d.getHours() + quotient<int>(minutes, 60);
1117 
1118   minutes = modulo<int>(minutes, 60);
1119 
1120   carry = quotient<int>(hours, 24);
1121 
1122   hours = modulo<int>(hours, 24);
1123 
1124   if (data[DAY_DATA] > get_last_day(years, months))
1125     temp_days = get_last_day(years, months);
1126   else if (data[DAY_DATA] < 1)
1127     temp_days = 1;
1128   else
1129     temp_days = data[DAY_DATA];
1130 
1131   days = d.getDays() + temp_days + carry;
1132   while (1)
1133   {
1134     if (days <1)
1135     {
1136       days = days + get_last_day(years,months-1);
1137       carry = -1;
1138     }
1139     else if (days > get_last_day(years, months))
1140     {
1141       days = days - get_last_day(years, months);
1142       carry = 1;
1143     }
1144     else
1145       break;
1146 
1147     years = years + quotient<int>(months + carry-1, 12);
1148     months = modulo<int>(months + carry -1, 12) + 1;
1149   }
1150 
1151   if (data[YEAR_DATA] > 0 && d.isNegative() && years <= 0)
1152     years--;
1153   if (data[YEAR_DATA] < 0 && !d.isNegative() && years >= 0)
1154     years++;
1155 
1156   new_dt = new DateTime();
1157 
1158   if (DateTime::createDateTime(years, months, days, hours, minutes,
1159                                int_seconds, frac_seconds, &the_time_zone,
1160                                *new_dt))
1161     assert(0);
1162 
1163   new_dt->facet = facet;
1164   if (adjust_facet)
1165     new_dt->adjustToFacet();
1166 
1167   return new_dt;
1168 }
1169 
1170 
subtractDuration(const Duration & d,bool adjust_facet) const1171 DateTime* DateTime::subtractDuration(const Duration& d, bool adjust_facet) const
1172 {
1173   std::auto_ptr<Duration> negD(d.toNegDuration());
1174   return addDuration(*negD, adjust_facet);
1175 }
1176 
1177 
subtractDateTime(const DateTime * dt,int implicit_timezone_seconds) const1178 Duration* DateTime::subtractDateTime(
1179     const DateTime* dt,
1180     int implicit_timezone_seconds) const
1181 {
1182   std::auto_ptr<DateTime> dt1(normalizeTimeZone(implicit_timezone_seconds));
1183   std::auto_ptr<DateTime> dt2(dt->normalizeTimeZone(implicit_timezone_seconds));
1184   std::auto_ptr<Duration> dur1(dt1->toDayTimeDuration());
1185   std::auto_ptr<Duration> dur2(dt2->toDayTimeDuration());
1186   return *dur1 - *dur2;
1187 }
1188 
1189 
normalizeTimeZone(int tz_seconds) const1190 DateTime* DateTime::normalizeTimeZone(int tz_seconds) const
1191 {
1192   DateTime* dt;
1193   Duration d;
1194 
1195   if( the_time_zone.timeZoneNotSet() )
1196   {
1197     // validate timezone value (-14 .. +14 H)
1198     if (tz_seconds > 14*3600 || tz_seconds < -14*3600)
1199       throw InvalidTimezoneException();
1200 
1201     d = Duration(Duration::DAYTIMEDURATION_FACET,
1202                  (tz_seconds < 0), 0, 0, 0, 0, 0, tz_seconds, 0);
1203   }
1204   else
1205   {
1206     if (0 != Duration::fromTimezone(the_time_zone, d))
1207       assert(0);
1208   }
1209 
1210   dt = subtractDuration(d, false); // do not adjust to facet
1211   dt->the_time_zone = TimeZone(0);
1212 
1213   return dt;
1214 }
1215 
1216 
adjustToTimeZone(int tz_seconds) const1217 DateTime* DateTime::adjustToTimeZone(int tz_seconds) const
1218 {
1219   std::auto_ptr<Duration> dtduration;
1220   std::auto_ptr<Duration> context_tz;
1221   std::auto_ptr<DateTime> dt;
1222 
1223   // validate timezone value (-14 .. +14 H)
1224   if (tz_seconds > 14*3600 || tz_seconds < -14*3600)
1225     throw InvalidTimezoneException();
1226 
1227   // If $timezone is not specified, then $timezone is the value of the implicit timezone in the dynamic context.
1228   context_tz = std::auto_ptr<Duration>(new Duration(Duration::DAYTIMEDURATION_FACET, (tz_seconds<0), 0, 0, 0, 0, 0, tz_seconds, 0));
1229 
1230   dt = std::auto_ptr<DateTime>(new DateTime(*this));
1231 
1232   // If $arg does not have a timezone component and $timezone is not the empty sequence,
1233   // then the result is $arg with $timezone as the timezone component.
1234   if (the_time_zone.timeZoneNotSet())
1235   {
1236     if (TimeZone::createTimeZone(context_tz->getHours(), context_tz->getMinutes(), context_tz->getIntSeconds(), dt->the_time_zone))
1237       assert(0);
1238   }
1239   else
1240   {
1241     // If $arg has a timezone component and $timezone is not the empty sequence, then
1242     // the result is an xs:dateTime value with a timezone component of $timezone that is equal to $arg.
1243     dtduration = std::auto_ptr<Duration>(new Duration(Duration::DAYTIMEDURATION_FACET,
1244                                                       the_time_zone.isNegative(),
1245                                                       0, 0, 0,
1246                                                       the_time_zone.getHours(),
1247                                                       the_time_zone.getMinutes(),
1248                                                       the_time_zone.getIntSeconds(),
1249                                                       0));
1250 
1251     dtduration = std::auto_ptr<Duration>(*context_tz - *dtduration);
1252     dt = std::auto_ptr<DateTime>(dt->addDuration(*dtduration));
1253     if (TimeZone::createTimeZone(context_tz->getHours(), context_tz->getMinutes(), context_tz->getIntSeconds(), dt->the_time_zone))
1254       assert(0);
1255   }
1256 
1257   return dt.release();
1258 }
1259 
1260 
adjustToTimeZone(const Duration * d) const1261 DateTime* DateTime::adjustToTimeZone(const Duration* d) const
1262 {
1263   std::auto_ptr<Duration> dtduration;
1264   std::auto_ptr<const Duration> context_tz;
1265   std::auto_ptr<DateTime> dt;
1266 
1267   // A dynamic error is raised [err:FODT0003] if $timezone is less than -PT14H
1268   // or greater than PT14H or if does not contain an integral number of minutes.
1269 
1270   dt = std::auto_ptr<DateTime>(new DateTime(*this));
1271 
1272   if (d == NULL)
1273   {
1274     if (!the_time_zone.timeZoneNotSet())
1275       dt->the_time_zone = TimeZone();
1276   }
1277   else
1278   {
1279     // validate timezone value (-14 .. +14 H)
1280     if (d->getYears() != 0 || d->getMonths() != 0 ||
1281         d->getDays() != 0 ||
1282         d->getSeconds() != Integer::zero() ||
1283         d->getHours()*3600 + d->getMinutes()*60 > 14*3600 ||
1284         d->getHours()*3600 + d->getMinutes()*60 < -14*3600)
1285       throw InvalidTimezoneException();
1286 
1287     // If $arg does not have a timezone component and $timezone is not the
1288     // empty sequence, then the result is $arg with $timezone as the timezone
1289     // component.
1290     if (the_time_zone.timeZoneNotSet())
1291     {
1292       if (TimeZone::createTimeZone(d->getHours(), d->getMinutes(), d->getIntSeconds(), dt->the_time_zone))
1293         assert(0);
1294     }
1295     else
1296     {
1297       // If $arg has a timezone component and $timezone is not the empty sequence, then
1298       // the result is an xs:dateTime value with a timezone component of $timezone that is equal to $arg.
1299       dtduration = std::auto_ptr<Duration>(new Duration(Duration::DAYTIMEDURATION_FACET,
1300                                                         the_time_zone.isNegative(),
1301                                                         0, 0, 0,
1302                                                         the_time_zone.getHours(),
1303                                                         the_time_zone.getMinutes(),
1304                                                         the_time_zone.getIntSeconds(),
1305                                                         0));
1306 
1307       context_tz = std::auto_ptr<Duration>(new Duration(*d));
1308       if (context_tz.get() == NULL)
1309         assert(0);
1310 
1311       dtduration = std::auto_ptr<Duration>(*context_tz - *dtduration);
1312       dt.reset(dt->addDuration(*dtduration));
1313 
1314       if (TimeZone::createTimeZone(context_tz->getHours(),
1315                                    context_tz->getMinutes(),
1316                                    context_tz->getIntSeconds(),
1317                                    dt->the_time_zone))
1318         assert(0);
1319     }
1320   }
1321 
1322   return dt.release();
1323 }
1324 
1325 
setFacet(FACET_TYPE a_facet)1326 void DateTime::setFacet(FACET_TYPE a_facet)
1327 {
1328   facet = a_facet;
1329   adjustToFacet();
1330 }
1331 
1332 
adjustToFacet()1333 void DateTime::adjustToFacet()
1334 {
1335   switch (facet)
1336   {
1337   case DATETIME_FACET:
1338     // do nothing;
1339     break;
1340   case DATE_FACET:
1341     for (int i=HOUR_DATA; i<=FRACSECONDS_DATA; i++)
1342       data[i] = 0;
1343     break;
1344   case TIME_FACET:
1345     for (int i=YEAR_DATA; i<=DAY_DATA; i++)
1346       data[i] = 1;
1347     break;
1348   case GYEARMONTH_FACET:
1349     data[DAY_DATA] = 1;
1350     for (int i=HOUR_DATA; i<=FRACSECONDS_DATA; i++)
1351       data[i] = 0;
1352     break;
1353   case GYEAR_FACET:
1354     data[MONTH_DATA] = 1;
1355     data[DAY_DATA] = 1;
1356     for (int i=HOUR_DATA; i<=FRACSECONDS_DATA; i++)
1357       data[i] = 0;
1358     break;
1359   case GMONTH_FACET:
1360     data[YEAR_DATA] = 1;
1361     data[DAY_DATA] = 1;
1362     for (int i=HOUR_DATA; i<=FRACSECONDS_DATA; i++)
1363       data[i] = 0;
1364     break;
1365   case GMONTHDAY_FACET:
1366     data[YEAR_DATA] = 1;
1367     for (int i=HOUR_DATA; i<=FRACSECONDS_DATA; i++)
1368       data[i] = 0;
1369     break;
1370   case GDAY_FACET:
1371     data[YEAR_DATA] = 1;
1372     data[MONTH_DATA] = 1;
1373     for (int i=HOUR_DATA; i<=FRACSECONDS_DATA; i++)
1374       data[i] = 0;
1375     break;
1376   }
1377 }
1378 
1379 
getDayOfWeek(int year,int month,int day)1380 int DateTime::getDayOfWeek(int year, int month, int day)
1381 {
1382   if (month < 3)
1383   {
1384     month = month + 12;
1385     year = year - 1;
1386   }
1387 
1388   return (day
1389       + (2 * month)
1390       + int(6 * (month + 1) / 10)
1391       + year
1392       + int(year / 4)
1393       - int(year / 100)
1394       + int(year / 400)
1395       + 1                     // CalendarSystem, 1 for Gregorian
1396          ) % 7;
1397 }
1398 
1399 
getWeekInYear(int year,int month,int day)1400 int DateTime::getWeekInYear(int year, int month, int day)
1401 {
1402   int day_of_year = DateTime::getDayOfYear(year, month, day);
1403   int year_first_day_of_week = DateTime::getDayOfWeek(year, 1, 1);
1404 
1405   if (year_first_day_of_week > 4 && (year_first_day_of_week + day_of_year) <= 8)
1406     return getWeekInYear(year-1, 12, 31);
1407 
1408   return ((day_of_year + year_first_day_of_week - 2) / 7) + year_first_day_of_week < 5 ? 1 : 0;
1409 }
1410 
1411 
getDayOfYear(int year,int month,int day)1412 int DateTime::getDayOfYear(int year, int month, int day)
1413 {
1414   static const int days[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
1415 
1416   if (month > 12)
1417     return -1;
1418 
1419   if (isLeapYear(year) && month >= 3)
1420     day++;
1421 
1422   return days[month-1] + day;
1423 }
1424 
1425 
isLeapYear(int year)1426 bool DateTime::isLeapYear(int year)
1427 {
1428   if (((year%4 == 0) && (year%100 != 0))
1429         ||
1430         (year%400 == 0))
1431     return true;
1432   else
1433     return false;
1434 }
1435 
1436 
getWeekInMonth(int year,int month,int day)1437 int DateTime::getWeekInMonth(int year, int month, int day)
1438 {
1439   int first_day_of_week = DateTime::getDayOfWeek(year, month, 1);
1440   return ((day + first_day_of_week - 2) / 7) + (first_day_of_week < 5 ? 1 : 0);
1441 }
1442 
1443 
isLeapYear() const1444 bool DateTime::isLeapYear() const
1445 {
1446   return isLeapYear(data[YEAR_DATA]);
1447 }
1448 
1449 
getDayOfWeek() const1450 int DateTime::getDayOfWeek() const
1451 {
1452 	return getDayOfWeek(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);
1453 }
1454 
1455 
getDayOfYear() const1456 int DateTime::getDayOfYear() const
1457 {
1458   return getDayOfYear(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);
1459 }
1460 
1461 
getWeekInYear() const1462 int DateTime::getWeekInYear() const
1463 {
1464   return getWeekInYear(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);
1465 }
1466 
1467 
getWeekInMonth() const1468 int DateTime::getWeekInMonth() const
1469 {
1470   return getWeekInMonth(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);
1471 }
1472 
1473 } // namespace xqp
1474 /* vim:set et sw=2 ts=2: */
1475