1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
8
* Jay Pipes <jay.pipes@sun.com>
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28
* Implementation of the server's temporal class API
32
* Move to completed ValueObject API, which would remove the from_xxx() methods
33
* and replace them with constructors which take other ValueObject instances as
34
* their single parameter.
37
#include "drizzled/global.h"
39
#include "mystrings/m_ctype.h"
40
#include "drizzled/my_decimal.h"
41
#include "drizzled/calendar.h"
42
#include "drizzled/temporal.h"
43
#ifdef NOTYETIMPLEMENTED
44
#include "drizzled/temporal_interval.h"
46
#include "drizzled/temporal_format.h"
54
extern std::vector<drizzled::TemporalFormat *> known_datetime_formats;
55
extern std::vector<drizzled::TemporalFormat *> known_date_formats;
56
extern std::vector<drizzled::TemporalFormat *> known_time_formats;
76
uint64_t Temporal::_cumulative_seconds_in_time() const
78
return (uint64_t) ((_hours * INT64_C(3600))
79
+ (_minutes * INT64_C(60))
83
void Temporal::set_epoch_seconds()
86
* If the temporal is in the range of a timestamp, set
87
* the epoch_seconds member variable
89
if (in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds))
92
struct tm broken_time;
94
broken_time.tm_sec= _seconds;
95
broken_time.tm_min= _minutes;
96
broken_time.tm_hour= _hours;
97
broken_time.tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
98
broken_time.tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
99
broken_time.tm_year= _years - 1900; /* tm_year expects range of 70 - 38 */
101
result_time= timegm(&broken_time);
103
_epoch_seconds= result_time;
107
bool Date::from_string(const char *from, size_t from_len)
110
* Loop through the known date formats and see if
114
TemporalFormat *current_format;
115
std::vector<TemporalFormat *>::iterator current= known_date_formats.begin();
117
while (current != known_date_formats.end())
119
current_format= *current;
120
if (current_format->matches(from, from_len, this))
135
bool DateTime::from_string(const char *from, size_t from_len)
138
* Loop through the known datetime formats and see if
142
TemporalFormat *current_format;
143
std::vector<TemporalFormat *>::iterator current= known_datetime_formats.begin();
145
while (current != known_datetime_formats.end())
147
current_format= *current;
148
if (current_format->matches(from, from_len, this))
164
* Comparison operators for Time against another Time
165
* are easy. We simply compare the cumulative time
168
bool Time::operator==(const Time& rhs)
172
&& _minutes == rhs._minutes
173
&& _seconds == rhs._seconds
174
&& _useconds == rhs._useconds
175
&& _nseconds == rhs._nseconds
178
bool Time::operator!=(const Time& rhs)
180
return ! (*this == rhs);
182
bool Time::operator<(const Time& rhs)
184
return (_cumulative_seconds_in_time() < rhs._cumulative_seconds_in_time());
186
bool Time::operator<=(const Time& rhs)
188
return (_cumulative_seconds_in_time() <= rhs._cumulative_seconds_in_time());
190
bool Time::operator>(const Time& rhs)
192
return (_cumulative_seconds_in_time() > rhs._cumulative_seconds_in_time());
194
bool Time::operator>=(const Time& rhs)
196
return (_cumulative_seconds_in_time() >= rhs._cumulative_seconds_in_time());
200
* Subtracting one Time value from another can yield
201
* a new Time instance.
203
* This operator is called in the following situation:
206
* drizzled::Time lhs;
207
* lhs.from_string("20:00:00");
208
* drizzled::Time rhs;
209
* rhs.from_string("19:00:00");
211
* drizzled::Time result= lhs - rhs;
216
* Subtracting a larger time value from a smaller one
217
* should throw an exception at some point. The result
218
* of such an operator should be a TemporalInterval, not
219
* a Time instance, since a negative time is not possible.
221
const Time Time::operator-(const Time& rhs)
225
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
226
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
227
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
228
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
229
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
230
result._seconds= (uint32_t) second_diff;
234
const Time Time::operator+(const Time& rhs)
237
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
238
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
239
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
240
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
241
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
242
result._seconds= (uint32_t) second_diff;
244
* @TODO Once exceptions are supported, we should raise an error here if
245
* the result Time is not valid?
251
* Variation of + and - operator which returns a reference to the left-hand
252
* side Time object and adds the right-hand side to itself.
254
Time& Time::operator+=(const Time& rhs)
256
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
257
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
258
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
259
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
260
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
261
_seconds= (uint32_t) second_diff;
263
* @TODO Once exceptions are supported, we should raise an error here if
264
* the result Time is not valid?
268
Time& Time::operator-=(const Time& rhs)
270
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
271
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
272
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
273
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
274
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
275
_seconds= (uint32_t) second_diff;
277
* @TODO Once exceptions are supported, we should raise an error here if
278
* the result Time is not valid?
284
* Comparison operators for Date against another Date
285
* are easy. We simply compare the cumulative
288
bool Date::operator==(const Date& rhs)
292
&& _months == rhs._months
293
&& _days == rhs._days
296
bool Date::operator!=(const Date& rhs)
298
return ! (*this == rhs);
300
bool Date::operator<(const Date& rhs)
302
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
303
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
304
return (days_left < days_right);
306
bool Date::operator<=(const Date& rhs)
308
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
309
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
310
return (days_left <= days_right);
312
bool Date::operator>(const Date& rhs)
314
return ! (*this <= rhs);
316
bool Date::operator>=(const Date& rhs)
318
return ! (*this < rhs);
322
* Comparison operators for DateTime against another DateTime
323
* are easy. We simply compare the cumulative time
326
bool Date::operator==(const DateTime& rhs)
330
&& _months == rhs._months
331
&& _days == rhs._days
332
&& _hours == rhs._hours
333
&& _minutes == rhs._minutes
334
&& _seconds == rhs._seconds
335
&& _useconds == rhs._useconds
336
&& _nseconds == rhs._nseconds
339
bool Date::operator!=(const DateTime& rhs)
341
return ! (*this == rhs);
343
bool Date::operator<(const DateTime& rhs)
345
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
346
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
347
if (days_left < days_right)
349
else if (days_left > days_right)
351
/* Here if both dates are the same, so compare times */
352
return (_cumulative_seconds_in_time() < rhs._cumulative_seconds_in_time());
354
bool Date::operator<=(const DateTime& rhs)
356
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
357
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
358
if (days_left < days_right)
360
else if (days_left > days_right)
362
/* Here if both dates are the same, so compare times */
363
return (_cumulative_seconds_in_time() <= rhs._cumulative_seconds_in_time());
365
bool Date::operator>(const DateTime& rhs)
367
return ! (*this <= rhs);
369
bool Date::operator>=(const DateTime& rhs)
371
return ! (*this < rhs);
375
* We can add or subtract a Time value to/from a DateTime value
376
* as well...it always produces a DateTime.
378
const Date Date::operator-(const Time& rhs)
383
* First, we set the resulting DATE pieces equal to our
384
* left-hand side DateTime's DATE components. Then, deal with
385
* the time components.
387
result._years= _years;
388
result._months= _months;
391
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
394
* The resulting diff might be negative. If it is, that means that
395
* we have subtracting a larger time piece from the datetime, like so:
397
* x = DateTime("2007-06-09 09:30:00") - Time("16:30:00");
399
* In these cases, we need to subtract a day from the resulting
405
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
406
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
407
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
408
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
409
result._seconds= (uint32_t) second_diff;
411
/* Handle the microsecond precision */
412
int64_t microsecond_diff= _useconds - rhs._useconds;
413
if (microsecond_diff < 0)
415
microsecond_diff= (-1 * microsecond_diff);
418
result._useconds= (uint32_t) microsecond_diff;
422
const Date Date::operator+(const Time& rhs)
427
* First, we set the resulting DATE pieces equal to our
428
* left-hand side DateTime's DATE components. Then, deal with
429
* the time components.
431
result._years= _years;
432
result._months= _months;
435
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
438
* The resulting seconds might be more than a day. If do,
439
* adjust our resulting days up 1.
441
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
444
second_diff%= DRIZZLE_SECONDS_IN_DAY;
447
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
448
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
449
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
450
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
451
result._seconds= (uint32_t) second_diff;
453
/* Handle the microsecond precision */
454
int64_t microsecond_diff= _useconds - rhs._useconds;
455
if (microsecond_diff < 0)
457
microsecond_diff= (-1 * microsecond_diff);
460
result._useconds= (uint32_t) microsecond_diff;
466
* Variation of + and - operator which returns a reference to the left-hand
467
* side DateTime object and adds the right-hand side Time to itself.
469
Date& Date::operator+=(const Time& rhs)
471
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
473
* The resulting seconds might be more than a day. If do,
474
* adjust our resulting days up 1.
476
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
479
second_diff%= DRIZZLE_SECONDS_IN_DAY;
482
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
483
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
484
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
485
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
486
_seconds= (uint32_t) second_diff;
488
/* Handle the microsecond precision */
489
int64_t microsecond_diff= _useconds - rhs._useconds;
490
if (microsecond_diff < 0)
492
microsecond_diff= (-1 * microsecond_diff);
495
_useconds= (uint32_t) microsecond_diff;
497
* @TODO Once exceptions are supported, we should raise an error here if
498
* the result Time is not valid?
502
Date& Date::operator-=(const Time& rhs)
504
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
507
* The resulting diff might be negative. If it is, that means that
508
* we have subtracting a larger time piece from the datetime, like so:
510
* x = DateTime("2007-06-09 09:30:00");
511
* x-= Time("16:30:00");
513
* In these cases, we need to subtract a day from the resulting
519
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
520
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
521
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
522
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
523
_seconds= (uint32_t) second_diff;
525
/* Handle the microsecond precision */
526
int64_t microsecond_diff= _useconds - rhs._useconds;
527
if (microsecond_diff < 0)
529
microsecond_diff= (-1 * microsecond_diff);
532
_useconds= (uint32_t) microsecond_diff;
534
* @TODO Once exceptions are supported, we should raise an error here if
535
* the result Time is not valid?
541
* We can add/subtract two Dates to/from each other. The result
542
* is always another Date instance.
544
const Date Date::operator-(const Date &rhs)
546
/* Figure out the difference in days between the two dates */
547
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
548
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
549
int64_t day_diff= day_left - day_right;
552
/* Now re-compose the Date's structure from the resulting Julian Day Number */
553
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
556
const Date Date::operator+(const Date &rhs)
559
* Figure out the new Julian Day Number by adding the JDNs of both
562
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
563
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
564
int64_t day_diff= day_left + day_right;
566
/** @TODO Need an exception check here for bounds of JDN... */
569
/* Now re-compose the Date's structure from the resulting Julian Day Number */
570
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
573
/* Similar to the above, but we add/subtract the right side to this object itself */
574
Date& Date::operator-=(const Date &rhs)
576
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
577
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
578
int64_t day_diff= day_left - day_right;
580
/* Now re-compose the Date's structure from the resulting Julian Day Number */
581
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
584
Date& Date::operator+=(const Date &rhs)
587
* Figure out the new Julian Day Number by adding the JDNs of both
590
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
591
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
592
int64_t day_diff= day_left + day_right;
594
/** @TODO Need an exception check here for bounds of JDN... */
596
/* Now re-compose the Date's structure from the resulting Julian Day Number */
597
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
601
Date& Date::operator=(const DateTime &rhs)
603
/* Only copy the Date components of the assigned DateTime... */
605
_months= rhs._months;
607
/* Zero-out everything else.. */
608
_hours= _minutes= _seconds= _useconds= _nseconds= 0;
613
* We can add/subtract two DateTimes to/from each other. The result
614
* is always another DateTime instance.
616
const Date Date::operator-(const DateTime &rhs)
618
/* Figure out the difference in days between the two dates. */
619
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
620
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
621
int64_t day_diff= day_left - day_right;
624
/* Now re-compose the Date's structure from the resulting Julian Day Number */
625
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
627
/* And now handle the time components */
628
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
631
* The resulting diff might be negative. If it is, that means that
632
* we have subtracting a larger time piece from the datetime, like so:
634
* x = DateTime("2007-06-09 09:30:00");
635
* x-= Time("16:30:00");
637
* In these cases, we need to subtract a day from the resulting
643
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
644
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
645
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
646
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
647
result._seconds= (uint32_t) second_diff;
649
/* Handle the microsecond precision */
650
int64_t microsecond_diff= _useconds - rhs._useconds;
651
if (microsecond_diff < 0)
653
microsecond_diff= (-1 * microsecond_diff);
656
result._useconds= (uint32_t) microsecond_diff;
660
const Date Date::operator+(const DateTime &rhs)
663
* Figure out the new Julian Day Number by adding the JDNs of both
666
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
667
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
668
int64_t day_diff= day_left + day_right;
670
/** @TODO Need an exception check here for bounds of JDN... */
673
/* Now re-compose the Date's structure from the resulting Julian Day Number */
674
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
676
/* And now handle the time components */
677
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
680
* The resulting seconds might be more than a day. If do,
681
* adjust our resulting days up 1.
683
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
686
second_diff%= DRIZZLE_SECONDS_IN_DAY;
689
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
690
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
691
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
692
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
693
result._seconds= (uint32_t) second_diff;
695
/* Handle the microsecond precision */
696
int64_t microsecond_diff= _useconds - rhs._useconds;
697
if (microsecond_diff < 0)
699
microsecond_diff= (-1 * microsecond_diff);
702
result._useconds= (uint32_t) microsecond_diff;
706
/* Similar to the above, but we add/subtract the right side to this object itself */
707
Date& Date::operator-=(const DateTime &rhs)
709
/* Figure out the difference in days between the two dates. */
710
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
711
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
712
int64_t day_diff= day_left - day_right;
714
/* Now re-compose the Date's structure from the ng Julian Day Number */
715
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
717
/* And now handle the time components */
718
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
721
* The resulting diff might be negative. If it is, that means that
722
* we have subtracting a larger time piece from the datetime, like so:
724
* x = DateTime("2007-06-09 09:30:00");
725
* x-= Time("16:30:00");
727
* In these cases, we need to subtract a day from the ng
733
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
734
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
735
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
736
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
737
_seconds= (uint32_t) second_diff;
739
/* Handle the microsecond precision */
740
int64_t microsecond_diff= _useconds - rhs._useconds;
741
if (microsecond_diff < 0)
743
microsecond_diff= (-1 * microsecond_diff);
746
_useconds= (uint32_t) microsecond_diff;
750
Date& Date::operator+=(const DateTime &rhs)
753
* Figure out the new Julian Day Number by adding the JDNs of both
756
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
757
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
758
int64_t day_diff= day_left + day_right;
760
/** @TODO Need an exception check here for bounds of JDN... */
762
/* Now re-compose the Date's structure from the ng Julian Day Number */
763
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
765
/* And now handle the time components */
766
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
769
* The resulting seconds might be more than a day. If do,
770
* adjust our ng days up 1.
772
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
775
second_diff%= DRIZZLE_SECONDS_IN_DAY;
778
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
779
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
780
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
781
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
782
_seconds= (uint32_t) second_diff;
784
/* Handle the microsecond precision */
785
int64_t microsecond_diff= _useconds - rhs._useconds;
786
if (microsecond_diff < 0)
788
microsecond_diff= (-1 * microsecond_diff);
791
_useconds= (uint32_t) microsecond_diff;
795
#ifdef NOTYETIMPLEMENTED
796
Date& Date::operator+=(const TemporalIntervalYear &rhs)
798
/* Simple one...add the years and adjust for any leaps */
799
int64_t new_years= _years;
800
new_years+= rhs._years;
801
if (new_years > DRIZZLE_MAX_YEARS_SQL)
804
* Set everything to zero. We got an overflow.
805
* @TODO Exceptions would be great here...
811
_years= (uint32_t) new_years;
812
if (_months == 2 && _days == 29 && days_in_gregorian_year_month(_years, _months) != 366)
817
Date& Date::operator-=(const TemporalIntervalYear &rhs)
819
/* Simple one...subtract the years and adjust for any leaps */
820
int64_t new_years= _years;
821
new_years-= rhs._years;
825
* Set everything to zero. We got an overflow.
826
* @TODO Exceptions would be great here...
832
_years= (uint32_t) new_years;
833
if (_months == 2 && _days == 29 && days_in_gregorian_year_month(_years, _months) != 366)
838
Date& Date::operator+=(const TemporalIntervalDayOrWeek &rhs)
840
/* Simple one...add the days */
841
int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, _days) + rhs._days;
842
gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
846
Date& Date::operator-=(const TemporalIntervalDayOrWeek &rhs)
848
/* Simple one...subtract the days */
849
int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, _days) - rhs._days;
850
gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
854
Date& Date::operator+=(const TemporalIntervalYearMonth &rhs)
856
/* Simple one...add the months in the period adjust */
857
int64_t period= (_years * 12) + (rhs._years * 12) + (_months - 1) + rhs._months;
858
int64_t new_years= (period / 12);
859
if (new_years > DRIZZLE_MAX_YEARS_SQL)
862
* Set everything to zero. We got an overflow.
863
* @TODO Exceptions would be great here...
869
_years= (uint32_t) new_years;
870
_months= (uint32_t) (period % 12) + 1;
872
/* Adjust day if the new month doesn't have enough days */
873
uint32_t days_in_new_month= days_in_gregorian_year_month(_years, _months);
874
if (_days > days_in_new_month)
875
_days= days_in_new_month;
879
Date& Date::operator-=(const TemporalIntervalYearMonth &rhs)
881
/* Simple one...subtract the months in the period and adjust */
882
int64_t period= (_years * 12) - (rhs._years * 12) + (_months - 1) - rhs._months;
883
int64_t new_years= (period / 12);
887
* Set everything to zero. We got an overflow.
888
* @TODO Exceptions would be great here...
894
_years= (uint32_t) (period / 12);
895
_months= (uint32_t) (period % 12) + 1;
897
/* Adjust day if the new month doesn't have enough days */
898
uint32_t days_in_new_month= days_in_gregorian_year_month(_years, _months);
899
if (_days > days_in_new_month)
900
_days= days_in_new_month;
904
Date& Date::operator+=(const TemporalIntervalDayOrLess &rhs)
907
* Convert the temporal and the interval into a number of
908
* microseconds, then add them together and convert the
909
* resulting microseconds back into a broken-down temporal
913
int64_t new_microseconds;
916
new_microseconds= _useconds + rhs._useconds;
917
extra_sec= new_microseconds / INT64_C(1000000);
918
new_microseconds= new_microseconds % INT64_C(1000000);
920
new_seconds= ((_days - 1) * 3600 * 24) + (_hours * 3600) + (_minutes * 60) + _seconds;
921
new_seconds+= (rhs._days * 3600 * 24) + (rhs._hours * 3600) + (rhs._minutes * 60) + rhs._seconds;
922
new_seconds+= extra_sec;
924
if (new_microseconds < 0)
926
new_microseconds+= INT64_C(1000000);
930
new_days= new_seconds / (3600 * 24L);
931
new_seconds-= new_days * 3600 * 24L;
935
new_seconds+= 3600 * 24L;
937
_useconds= (uint32_t) new_microseconds;
938
_seconds= (uint32_t) (new_seconds % 60);
939
_minutes= (uint32_t) ((new_seconds / 60) % 60);
940
_hours= (uint32_t) (new_seconds / 3600);
941
int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, 1) + new_days;
942
gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
946
Date& Date::operator-=(const TemporalIntervalDayOrLess &rhs)
949
* Convert the temporal and the interval into a number of
950
* microseconds, then subtract them from each other and convert
951
* the resulting microseconds back into a broken-down temporal
955
int64_t new_microseconds;
958
new_microseconds= _useconds - rhs._useconds;
959
extra_sec= new_microseconds / INT64_C(1000000);
960
new_microseconds= new_microseconds % INT64_C(1000000);
962
new_seconds= ((_days - 1) * 3600 * 24) + (_hours * 3600) + (_minutes * 60) + _seconds;
963
new_seconds-= (rhs._days * 3600 * 24) + (rhs._hours * 3600) + (rhs._minutes * 60) + rhs._seconds;
964
new_seconds+= extra_sec;
966
if (new_microseconds < 0)
968
new_microseconds+= INT64_C(1000000);
972
new_days= new_seconds / (3600 * 24L);
973
new_seconds-= new_days * 3600 * 24L;
977
new_seconds+= 3600 * 24L;
979
_useconds= (uint32_t) new_microseconds;
980
_seconds= (uint32_t) (new_seconds % 60);
981
_minutes= (uint32_t) ((new_seconds / 60) % 60);
982
_hours= (uint32_t) (new_seconds / 3600);
983
int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, 1) + new_days;
984
gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
987
#endif /* NOTYETIMPLEMENTED */
989
* Comparison operators between a Date and a Timestamp
991
bool Date::operator==(const Timestamp& rhs)
993
return (_years == rhs._years && _months == rhs._months && _days == rhs._days);
995
bool Date::operator!=(const Timestamp& rhs)
997
return ! (*this == rhs);
999
bool Date::operator<(const Timestamp& rhs)
1001
if (_years < rhs._years)
1003
if (_years > rhs._years)
1006
if (_months < rhs._months)
1008
if (_months > rhs._months)
1011
return _days < rhs._days;
1013
bool Date::operator<=(const Timestamp& rhs)
1015
return (*this < rhs || *this == rhs);
1017
bool Date::operator>(const Timestamp& rhs)
1019
return ! (*this < rhs);
1021
bool Date::operator>=(const Timestamp& rhs)
1023
return ! (*this <= rhs);
1026
* Comparison operators between a Timestamp and a Date
1028
bool Timestamp::operator==(const Date& rhs)
1030
return (_years == rhs._years && _months == rhs._months && _days == rhs._days);
1032
bool Timestamp::operator!=(const Date& rhs)
1034
return ! (*this == rhs);
1036
bool Timestamp::operator<(const Date& rhs)
1038
if (_years < rhs._years)
1040
if (_years > rhs._years)
1043
if (_months < rhs._months)
1045
if (_months > rhs._months)
1048
return _days < rhs._days;
1050
bool Timestamp::operator<=(const Date& rhs)
1052
return (*this < rhs || *this == rhs);
1054
bool Timestamp::operator>(const Date& rhs)
1056
return ! (*this < rhs);
1058
bool Timestamp::operator>=(const Date& rhs)
1060
return ! (*this <= rhs);
1063
* Comparison operators between a Timestamp and a DateTime
1065
bool Timestamp::operator==(const DateTime& rhs)
1067
return (_years == rhs._years && _months == rhs._months && _days == rhs._days
1068
&& _hours == rhs._hours && _minutes == rhs._minutes && _seconds == rhs._seconds);
1070
bool Timestamp::operator!=(const DateTime& rhs)
1072
return ! (*this == rhs);
1074
bool Timestamp::operator<(const DateTime& rhs)
1076
if (_years < rhs._years)
1078
if (_years > rhs._years)
1081
if (_months < rhs._months)
1083
if (_months > rhs._months)
1086
if (_days < rhs._days)
1088
if (_days > rhs._days)
1091
if (_hours < rhs._hours)
1093
if (_hours > rhs._hours)
1096
if (_minutes < rhs._minutes)
1098
if (_minutes > rhs._minutes)
1101
return _seconds < rhs._seconds;
1103
bool Timestamp::operator<=(const DateTime& rhs)
1105
return (*this < rhs || *this == rhs);
1107
bool Timestamp::operator>(const DateTime& rhs)
1109
return ! (*this < rhs);
1111
bool Timestamp::operator>=(const DateTime& rhs)
1113
return ! (*this <= rhs);
1116
* Comparison operators between two Timestamps
1118
bool Timestamp::operator==(const Timestamp& rhs)
1120
return (_epoch_seconds == rhs._epoch_seconds);
1122
bool Timestamp::operator!=(const Timestamp& rhs)
1124
return ! (*this == rhs);
1126
bool Timestamp::operator<(const Timestamp& rhs)
1128
return (_epoch_seconds < rhs._epoch_seconds);
1130
bool Timestamp::operator<=(const Timestamp& rhs)
1132
return (_epoch_seconds <= rhs._epoch_seconds);
1134
bool Timestamp::operator>(const Timestamp& rhs)
1136
return ! (*this < rhs);
1138
bool Timestamp::operator>=(const Timestamp& rhs)
1140
return ! (*this <= rhs);
1144
* Push the contents of the timestamp into the output stream
1145
* as a formatted Timestamp value.
1147
* @TODO This unfortunately fails in a weird way...even with std::noskipws,
1148
* the output stream only reads up to the space in the string... :(
1150
std::ostream& operator<<(std::ostream& os, const Timestamp& subject)
1152
return os << subject.years() << '-'
1153
<< std::setw(2) << std::setfill('0') << subject.months() << '-'
1154
<< std::setw(2) << std::setfill('0') << subject.days() << ' '
1155
<< std::setw(2) << std::setfill('0') << subject.hours() << ':'
1156
<< std::setw(2) << std::setfill('0') << subject.minutes() << ':'
1157
<< std::setw(2) << std::setfill('0') << subject.seconds();
1160
bool Time::from_string(const char *from, size_t from_len)
1163
* Loop through the known time formats and see if
1166
bool matched= false;
1167
TemporalFormat *current_format;
1168
std::vector<TemporalFormat *>::iterator current= known_time_formats.begin();
1170
while (current != known_time_formats.end())
1172
current_format= *current;
1173
if (current_format->matches(from, from_len, this))
1187
void Time::to_string(char *to, size_t *to_len) const
1190
, "%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32
1196
void Date::to_string(char *to, size_t *to_len) const
1199
, "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
1205
void DateTime::to_string(char *to, size_t *to_len) const
1207
/* If the temporal has a microsecond component, use a slightly different output */
1211
, "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32 " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32
1222
, "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32 " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32
1233
void MicroTimestamp::to_string(char *to, size_t *to_len) const
1236
, "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32 " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32
1246
void Time::to_decimal(my_decimal *to) const
1248
int64_t time_portion= (((_hours * 100L) + _minutes) * 100L) + _seconds;
1249
(void) int2my_decimal(E_DEC_FATAL_ERROR, time_portion, false, to);
1252
to->buf[(to->intg-1) / 9 + 1]= _useconds * 1000;
1257
void Date::to_decimal(my_decimal *to) const
1259
int64_t date_portion= (((_years * 100L) + _months) * 100L) + _days;
1260
(void) int2my_decimal(E_DEC_FATAL_ERROR, date_portion, false, to);
1263
void DateTime::to_decimal(my_decimal *to) const
1265
int64_t date_portion= (((_years * 100L) + _months) * 100L) + _days;
1266
int64_t time_portion= (((((date_portion * 100L) + _hours) * 100L) + _minutes) * 100L) + _seconds;
1267
(void) int2my_decimal(E_DEC_FATAL_ERROR, time_portion, false, to);
1270
to->buf[(to->intg-1) / 9 + 1]= _useconds * 1000;
1275
void Date::to_int64_t(int64_t *to) const
1277
*to= (_years * INT32_C(10000))
1278
+ (_months * INT32_C(100))
1282
void Date::to_int32_t(int32_t *to) const
1284
*to= (_years * INT32_C(10000))
1285
+ (_months * INT32_C(100))
1289
void Time::to_int32_t(int32_t *to) const
1291
*to= (_hours * INT32_C(10000))
1292
+ (_minutes * INT32_C(100))
1296
void DateTime::to_int64_t(int64_t *to) const
1299
(_years * INT64_C(10000))
1300
+ (_months * INT64_C(100))
1302
) * INT64_C(1000000))
1304
(_hours * INT64_C(10000))
1305
+ (_minutes * INT64_C(100) )
1310
void Date::to_tm(struct tm *to) const
1315
to->tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
1316
to->tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
1317
to->tm_year= _years - 1900;
1320
void DateTime::to_tm(struct tm *to) const
1322
to->tm_sec= _seconds;
1323
to->tm_min= _minutes;
1324
to->tm_hour= _hours;
1325
to->tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
1326
to->tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
1327
to->tm_year= _years - 1900;
1330
bool Date::from_julian_day_number(const int64_t from)
1332
gregorian_date_from_julian_day_number(from, &_years, &_months, &_days);
1336
void Date::to_julian_day_number(int64_t *to) const
1338
*to= julian_day_number_from_gregorian_date(_years, _months, _days);
1342
* Ignore overflow and pass-through to DateTime::from_int64_t()
1344
bool Date::from_int32_t(const int32_t from)
1346
return ((DateTime *) this)->from_int64_t((int64_t) from);
1350
* Attempt to interpret the supplied 4-byte integer as
1351
* a TIME value in the format HHmmSS
1353
bool Time::from_int32_t(const int32_t from)
1355
uint32_t copy_from= (uint32_t) from;
1356
_hours= copy_from % INT32_C(10000);
1357
_minutes= copy_from % INT32_C(100);
1358
_seconds= copy_from & 3; /* Masks off all but last 2 digits */
1363
* We try to intepret the incoming number as a datetime "string".
1364
* This is pretty much a hack for usability, but keeps us compatible
1367
bool DateTime::from_int64_t(const int64_t from)
1369
int64_t copy_from= from;
1373
if (copy_from == 0LL)
1376
if (copy_from < 10000101000000LL)
1378
if (copy_from < 101)
1380
else if (copy_from <= (DRIZZLE_YY_PART_YEAR-1)*10000L+1231L)
1381
copy_from= (copy_from+20000000L)*1000000L; /* YYMMDD, year: 2000-2069 */
1382
else if (copy_from < (DRIZZLE_YY_PART_YEAR)*10000L+101L)
1384
else if (copy_from <= 991231L)
1385
copy_from= (copy_from+19000000L)*1000000L; /* YYMMDD, year: 1970-1999 */
1386
else if (copy_from < 10000101L)
1388
else if (copy_from <= 99991231L)
1389
copy_from= copy_from*1000000L;
1390
else if (copy_from < 101000000L)
1392
else if (copy_from <= (DRIZZLE_YY_PART_YEAR-1) * 10000000000LL + 1231235959LL)
1393
copy_from= copy_from + 20000000000000LL; /* YYMMDDHHMMSS, 2000-2069 */
1394
else if (copy_from < DRIZZLE_YY_PART_YEAR * 10000000000LL + 101000000LL)
1396
else if (copy_from <= 991231235959LL)
1397
copy_from= copy_from + 19000000000000LL; /* YYMMDDHHMMSS, 1970-1999 */
1400
part1= (int64_t) (copy_from / 1000000LL);
1401
part2= (int64_t) (copy_from - (int64_t) part1 * 1000000LL);
1402
_years= (uint32_t) (part1/10000L);
1405
_months= (uint32_t) part1 / 100;
1406
_days= (uint32_t) part1 % 100;
1407
_hours= (uint32_t) (part2/10000L);
1410
_minutes= (uint32_t) part2 / 100;
1411
_seconds= (uint32_t) part2 % 100;
1413
set_epoch_seconds();
1417
bool Date::in_unix_epoch() const
1419
return in_unix_epoch_range(_years, _months, _days, 0, 0, 0);
1422
bool DateTime::in_unix_epoch() const
1424
return in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds);
1427
bool Date::from_tm(const struct tm *from)
1429
_years= 1900 + from->tm_year;
1430
_months= 1 + from->tm_mon; /* Month is NOT ordinal for struct tm! */
1431
_days= from->tm_mday; /* Day IS ordinal for struct tm */
1432
_hours= from->tm_hour;
1433
_minutes= from->tm_min;
1434
_seconds= from->tm_sec;
1435
/* Set hires precision to zero */
1439
set_epoch_seconds();
1444
* We convert as if it's a Datetime, then simply
1445
* drop the date portions...
1447
bool Time::from_time_t(const time_t from)
1449
struct tm broken_time;
1452
result= gmtime_r(&from, &broken_time);
1458
_hours= broken_time.tm_hour;
1459
_minutes= broken_time.tm_min;
1460
_seconds= broken_time.tm_sec;
1461
_epoch_seconds= 0; /* Don't store the time_t, since we only use part of it */
1462
/* Set hires precision to zero */
1465
return true; /* Always true... */
1471
bool Date::from_time_t(const time_t from)
1473
struct tm broken_time;
1476
result= gmtime_r(&from, &broken_time);
1479
_years= 1900 + broken_time.tm_year;
1480
_months= 1 + broken_time.tm_mon; /* Month is NOT ordinal for struct tm! */
1481
_days= broken_time.tm_mday; /* Day IS ordinal for struct tm */
1485
_epoch_seconds= 0; /* Don't store the time_t, since we only use part of it */
1486
/* Set hires precision to zero */
1495
bool DateTime::from_time_t(const time_t from)
1497
struct tm broken_time;
1500
result= gmtime_r(&from, &broken_time);
1503
_years= 1900 + broken_time.tm_year;
1504
_months= 1 + broken_time.tm_mon; /* Month is NOT ordinal for struct tm! */
1505
_days= broken_time.tm_mday; /* Day IS ordinal for struct tm */
1506
_hours= broken_time.tm_hour;
1507
_minutes= broken_time.tm_min;
1508
_seconds= broken_time.tm_sec;
1509
_epoch_seconds= from;
1510
/* Set hires precision to zero */
1519
void Date::to_time_t(time_t *to) const
1521
if (in_unix_epoch())
1522
*to= _epoch_seconds;
1526
void Timestamp::to_time_t(time_t *to) const
1528
*to= _epoch_seconds;
1531
void MicroTimestamp::to_timeval(struct timeval *to) const
1533
to->tv_sec= _epoch_seconds;
1534
to->tv_usec= _useconds;
1537
void NanoTimestamp::to_timespec(struct timespec *to) const
1539
to->tv_sec= _epoch_seconds;
1540
to->tv_nsec= _nseconds;
1543
bool Date::is_valid() const
1545
return (_years >= DRIZZLE_MIN_YEARS_SQL && _years <= DRIZZLE_MAX_YEARS_SQL)
1546
&& (_months >= 1 && _months <= 12)
1547
&& (_days >= 1 && _days <= days_in_gregorian_year_month(_years, _months));
1550
bool Time::is_valid() const
1552
return (_years == 0)
1557
&& (_seconds <= 59); /* No Leap second... TIME is for elapsed time... */
1560
bool DateTime::is_valid() const
1562
return (_years >= DRIZZLE_MIN_YEARS_SQL && _years <= DRIZZLE_MAX_YEARS_SQL)
1563
&& (_months >= 1 && _months <= 12)
1564
&& (_days >= 1 && _days <= days_in_gregorian_year_month(_years, _months))
1567
&& (_seconds <= 61); /* Leap second... */
1570
bool Timestamp::is_valid() const
1572
return DateTime::is_valid()
1573
&& in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds);
1576
bool MicroTimestamp::is_valid() const
1578
return Timestamp::is_valid()
1579
&& (_useconds <= UINT32_C(999999));
1582
bool NanoTimestamp::is_valid() const
1584
return Timestamp::is_valid()
1585
&& (_useconds <= UINT32_C(999999))
1586
&& (_nseconds <= UINT32_C(999999999));
1589
} /* end namespace drizzled */