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.
39
#include "drizzled/charset_info.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"
47
#include "drizzled/time_functions.h"
57
extern std::vector<drizzled::TemporalFormat *> known_datetime_formats;
58
extern std::vector<drizzled::TemporalFormat *> known_date_formats;
59
extern std::vector<drizzled::TemporalFormat *> known_time_formats;
79
uint64_t Temporal::_cumulative_seconds_in_time() const
81
return (uint64_t) ((_hours * INT64_C(3600))
82
+ (_minutes * INT64_C(60))
86
void Temporal::set_epoch_seconds()
89
* If the temporal is in the range of a timestamp, set
90
* the epoch_seconds member variable
92
if (in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds))
95
struct tm broken_time;
97
broken_time.tm_sec= _seconds;
98
broken_time.tm_min= _minutes;
99
broken_time.tm_hour= _hours;
100
broken_time.tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
101
broken_time.tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
102
broken_time.tm_year= _years - 1900; /* tm_year expects range of 70 - 38 */
104
result_time= timegm(&broken_time);
106
_epoch_seconds= result_time;
110
bool Date::from_string(const char *from, size_t from_len)
113
* Loop through the known date formats and see if
117
TemporalFormat *current_format;
118
std::vector<TemporalFormat *>::iterator current= known_date_formats.begin();
120
while (current != known_date_formats.end())
122
current_format= *current;
123
if (current_format->matches(from, from_len, this))
138
bool DateTime::from_string(const char *from, size_t from_len)
141
* Loop through the known datetime formats and see if
145
TemporalFormat *current_format;
146
std::vector<TemporalFormat *>::iterator current= known_datetime_formats.begin();
148
while (current != known_datetime_formats.end())
150
current_format= *current;
151
if (current_format->matches(from, from_len, this))
167
* Comparison operators for Time against another Time
168
* are easy. We simply compare the cumulative time
171
bool Time::operator==(const Time& rhs)
175
&& _minutes == rhs._minutes
176
&& _seconds == rhs._seconds
177
&& _useconds == rhs._useconds
178
&& _nseconds == rhs._nseconds
181
bool Time::operator!=(const Time& rhs)
183
return ! (*this == rhs);
185
bool Time::operator<(const Time& rhs)
187
return (_cumulative_seconds_in_time() < rhs._cumulative_seconds_in_time());
189
bool Time::operator<=(const Time& rhs)
191
return (_cumulative_seconds_in_time() <= rhs._cumulative_seconds_in_time());
193
bool Time::operator>(const Time& rhs)
195
return (_cumulative_seconds_in_time() > rhs._cumulative_seconds_in_time());
197
bool Time::operator>=(const Time& rhs)
199
return (_cumulative_seconds_in_time() >= rhs._cumulative_seconds_in_time());
203
* Subtracting one Time value from another can yield
204
* a new Time instance.
206
* This operator is called in the following situation:
209
* drizzled::Time lhs;
210
* lhs.from_string("20:00:00");
211
* drizzled::Time rhs;
212
* rhs.from_string("19:00:00");
214
* drizzled::Time result= lhs - rhs;
219
* Subtracting a larger time value from a smaller one
220
* should throw an exception at some point. The result
221
* of such an operator should be a TemporalInterval, not
222
* a Time instance, since a negative time is not possible.
224
const Time Time::operator-(const Time& rhs)
228
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
229
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
230
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
231
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
232
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
233
result._seconds= (uint32_t) second_diff;
237
const Time Time::operator+(const Time& rhs)
240
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
241
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
242
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
243
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
244
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
245
result._seconds= (uint32_t) second_diff;
247
* @TODO Once exceptions are supported, we should raise an error here if
248
* the result Time is not valid?
254
* Variation of + and - operator which returns a reference to the left-hand
255
* side Time object and adds the right-hand side to itself.
257
Time& Time::operator+=(const Time& rhs)
259
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
260
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
261
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
262
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
263
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
264
_seconds= (uint32_t) second_diff;
266
* @TODO Once exceptions are supported, we should raise an error here if
267
* the result Time is not valid?
271
Time& Time::operator-=(const Time& rhs)
273
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
274
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
275
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
276
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
277
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
278
_seconds= (uint32_t) second_diff;
280
* @TODO Once exceptions are supported, we should raise an error here if
281
* the result Time is not valid?
287
* Comparison operators for Date against another Date
288
* are easy. We simply compare the cumulative
291
bool Date::operator==(const Date& rhs)
295
&& _months == rhs._months
296
&& _days == rhs._days
299
bool Date::operator!=(const Date& rhs)
301
return ! (*this == rhs);
303
bool Date::operator<(const Date& rhs)
305
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
306
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
307
return (days_left < days_right);
309
bool Date::operator<=(const Date& rhs)
311
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
312
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
313
return (days_left <= days_right);
315
bool Date::operator>(const Date& rhs)
317
return ! (*this <= rhs);
319
bool Date::operator>=(const Date& rhs)
321
return ! (*this < rhs);
325
* Comparison operators for DateTime against another DateTime
326
* are easy. We simply compare the cumulative time
329
bool Date::operator==(const DateTime& rhs)
333
&& _months == rhs._months
334
&& _days == rhs._days
335
&& _hours == rhs._hours
336
&& _minutes == rhs._minutes
337
&& _seconds == rhs._seconds
338
&& _useconds == rhs._useconds
339
&& _nseconds == rhs._nseconds
342
bool Date::operator!=(const DateTime& rhs)
344
return ! (*this == rhs);
346
bool Date::operator<(const DateTime& rhs)
348
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
349
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
350
if (days_left < days_right)
352
else if (days_left > days_right)
354
/* Here if both dates are the same, so compare times */
355
return (_cumulative_seconds_in_time() < rhs._cumulative_seconds_in_time());
357
bool Date::operator<=(const DateTime& rhs)
359
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
360
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
361
if (days_left < days_right)
363
else if (days_left > days_right)
365
/* Here if both dates are the same, so compare times */
366
return (_cumulative_seconds_in_time() <= rhs._cumulative_seconds_in_time());
368
bool Date::operator>(const DateTime& rhs)
370
return ! (*this <= rhs);
372
bool Date::operator>=(const DateTime& rhs)
374
return ! (*this < rhs);
378
* We can add or subtract a Time value to/from a DateTime value
379
* as well...it always produces a DateTime.
381
const Date Date::operator-(const Time& rhs)
386
* First, we set the resulting DATE pieces equal to our
387
* left-hand side DateTime's DATE components. Then, deal with
388
* the time components.
390
result._years= _years;
391
result._months= _months;
394
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
397
* The resulting diff might be negative. If it is, that means that
398
* we have subtracting a larger time piece from the datetime, like so:
400
* x = DateTime("2007-06-09 09:30:00") - Time("16:30:00");
402
* In these cases, we need to subtract a day from the resulting
408
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
409
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
410
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
411
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
412
result._seconds= (uint32_t) second_diff;
414
/* Handle the microsecond precision */
415
int64_t microsecond_diff= _useconds - rhs._useconds;
416
if (microsecond_diff < 0)
418
microsecond_diff= (-1 * microsecond_diff);
421
result._useconds= (uint32_t) microsecond_diff;
425
const Date Date::operator+(const Time& rhs)
430
* First, we set the resulting DATE pieces equal to our
431
* left-hand side DateTime's DATE components. Then, deal with
432
* the time components.
434
result._years= _years;
435
result._months= _months;
438
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
441
* The resulting seconds might be more than a day. If do,
442
* adjust our resulting days up 1.
444
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
447
second_diff%= DRIZZLE_SECONDS_IN_DAY;
450
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
451
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
452
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
453
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
454
result._seconds= (uint32_t) second_diff;
456
/* Handle the microsecond precision */
457
int64_t microsecond_diff= _useconds - rhs._useconds;
458
if (microsecond_diff < 0)
460
microsecond_diff= (-1 * microsecond_diff);
463
result._useconds= (uint32_t) microsecond_diff;
469
* Variation of + and - operator which returns a reference to the left-hand
470
* side DateTime object and adds the right-hand side Time to itself.
472
Date& Date::operator+=(const Time& rhs)
474
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
476
* The resulting seconds might be more than a day. If do,
477
* adjust our resulting days up 1.
479
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
482
second_diff%= DRIZZLE_SECONDS_IN_DAY;
485
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
486
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
487
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
488
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
489
_seconds= (uint32_t) second_diff;
491
/* Handle the microsecond precision */
492
int64_t microsecond_diff= _useconds - rhs._useconds;
493
if (microsecond_diff < 0)
495
microsecond_diff= (-1 * microsecond_diff);
498
_useconds= (uint32_t) microsecond_diff;
500
* @TODO Once exceptions are supported, we should raise an error here if
501
* the result Time is not valid?
505
Date& Date::operator-=(const Time& rhs)
507
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
510
* The resulting diff might be negative. If it is, that means that
511
* we have subtracting a larger time piece from the datetime, like so:
513
* x = DateTime("2007-06-09 09:30:00");
514
* x-= Time("16:30:00");
516
* In these cases, we need to subtract a day from the resulting
522
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
523
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
524
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
525
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
526
_seconds= (uint32_t) second_diff;
528
/* Handle the microsecond precision */
529
int64_t microsecond_diff= _useconds - rhs._useconds;
530
if (microsecond_diff < 0)
532
microsecond_diff= (-1 * microsecond_diff);
535
_useconds= (uint32_t) microsecond_diff;
537
* @TODO Once exceptions are supported, we should raise an error here if
538
* the result Time is not valid?
544
* We can add/subtract two Dates to/from each other. The result
545
* is always another Date instance.
547
const Date Date::operator-(const Date &rhs)
549
/* Figure out the difference in days between the two dates */
550
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
551
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
552
int64_t day_diff= day_left - day_right;
555
/* Now re-compose the Date's structure from the resulting Julian Day Number */
556
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
559
const Date Date::operator+(const Date &rhs)
562
* Figure out the new Julian Day Number by adding the JDNs of both
565
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
566
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
567
int64_t day_diff= day_left + day_right;
569
/** @TODO Need an exception check here for bounds of JDN... */
572
/* Now re-compose the Date's structure from the resulting Julian Day Number */
573
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
576
/* Similar to the above, but we add/subtract the right side to this object itself */
577
Date& Date::operator-=(const Date &rhs)
579
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
580
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
581
int64_t day_diff= day_left - day_right;
583
/* Now re-compose the Date's structure from the resulting Julian Day Number */
584
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
587
Date& Date::operator+=(const Date &rhs)
590
* Figure out the new Julian Day Number by adding the JDNs of both
593
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
594
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
595
int64_t day_diff= day_left + day_right;
597
/** @TODO Need an exception check here for bounds of JDN... */
599
/* Now re-compose the Date's structure from the resulting Julian Day Number */
600
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
604
Date& Date::operator=(const DateTime &rhs)
606
/* Only copy the Date components of the assigned DateTime... */
608
_months= rhs._months;
610
/* Zero-out everything else.. */
611
_hours= _minutes= _seconds= _useconds= _nseconds= 0;
616
* We can add/subtract two DateTimes to/from each other. The result
617
* is always another DateTime instance.
619
const Date Date::operator-(const DateTime &rhs)
621
/* Figure out the difference in days between the two dates. */
622
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
623
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
624
int64_t day_diff= day_left - day_right;
627
/* Now re-compose the Date's structure from the resulting Julian Day Number */
628
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
630
/* And now handle the time components */
631
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
634
* The resulting diff might be negative. If it is, that means that
635
* we have subtracting a larger time piece from the datetime, like so:
637
* x = DateTime("2007-06-09 09:30:00");
638
* x-= Time("16:30:00");
640
* In these cases, we need to subtract a day from the resulting
646
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
647
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
648
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
649
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
650
result._seconds= (uint32_t) second_diff;
652
/* Handle the microsecond precision */
653
int64_t microsecond_diff= _useconds - rhs._useconds;
654
if (microsecond_diff < 0)
656
microsecond_diff= (-1 * microsecond_diff);
659
result._useconds= (uint32_t) microsecond_diff;
663
const Date Date::operator+(const DateTime &rhs)
666
* Figure out the new Julian Day Number by adding the JDNs of both
669
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
670
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
671
int64_t day_diff= day_left + day_right;
673
/** @TODO Need an exception check here for bounds of JDN... */
676
/* Now re-compose the Date's structure from the resulting Julian Day Number */
677
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
679
/* And now handle the time components */
680
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
683
* The resulting seconds might be more than a day. If do,
684
* adjust our resulting days up 1.
686
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
689
second_diff%= DRIZZLE_SECONDS_IN_DAY;
692
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
693
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
694
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
695
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
696
result._seconds= (uint32_t) second_diff;
698
/* Handle the microsecond precision */
699
int64_t microsecond_diff= _useconds - rhs._useconds;
700
if (microsecond_diff < 0)
702
microsecond_diff= (-1 * microsecond_diff);
705
result._useconds= (uint32_t) microsecond_diff;
709
/* Similar to the above, but we add/subtract the right side to this object itself */
710
Date& Date::operator-=(const DateTime &rhs)
712
/* Figure out the difference in days between the two dates. */
713
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
714
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
715
int64_t day_diff= day_left - day_right;
717
/* Now re-compose the Date's structure from the ng Julian Day Number */
718
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
720
/* And now handle the time components */
721
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
724
* The resulting diff might be negative. If it is, that means that
725
* we have subtracting a larger time piece from the datetime, like so:
727
* x = DateTime("2007-06-09 09:30:00");
728
* x-= Time("16:30:00");
730
* In these cases, we need to subtract a day from the ng
736
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
737
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
738
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
739
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
740
_seconds= (uint32_t) second_diff;
742
/* Handle the microsecond precision */
743
int64_t microsecond_diff= _useconds - rhs._useconds;
744
if (microsecond_diff < 0)
746
microsecond_diff= (-1 * microsecond_diff);
749
_useconds= (uint32_t) microsecond_diff;
753
Date& Date::operator+=(const DateTime &rhs)
756
* Figure out the new Julian Day Number by adding the JDNs of both
759
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
760
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
761
int64_t day_diff= day_left + day_right;
763
/** @TODO Need an exception check here for bounds of JDN... */
765
/* Now re-compose the Date's structure from the ng Julian Day Number */
766
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
768
/* And now handle the time components */
769
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
772
* The resulting seconds might be more than a day. If do,
773
* adjust our ng days up 1.
775
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
778
second_diff%= DRIZZLE_SECONDS_IN_DAY;
781
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
782
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
783
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
784
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
785
_seconds= (uint32_t) second_diff;
787
/* Handle the microsecond precision */
788
int64_t microsecond_diff= _useconds - rhs._useconds;
789
if (microsecond_diff < 0)
791
microsecond_diff= (-1 * microsecond_diff);
794
_useconds= (uint32_t) microsecond_diff;
798
#ifdef NOTYETIMPLEMENTED
799
Date& Date::operator+=(const TemporalIntervalYear &rhs)
801
/* Simple one...add the years and adjust for any leaps */
802
int64_t new_years= _years;
803
new_years+= rhs._years;
804
if (new_years > DRIZZLE_MAX_YEARS_SQL)
807
* Set everything to zero. We got an overflow.
808
* @TODO Exceptions would be great here...
814
_years= (uint32_t) new_years;
815
if (_months == 2 && _days == 29 && days_in_gregorian_year_month(_years, _months) != 366)
820
Date& Date::operator-=(const TemporalIntervalYear &rhs)
822
/* Simple one...subtract the years and adjust for any leaps */
823
int64_t new_years= _years;
824
new_years-= rhs._years;
828
* Set everything to zero. We got an overflow.
829
* @TODO Exceptions would be great here...
835
_years= (uint32_t) new_years;
836
if (_months == 2 && _days == 29 && days_in_gregorian_year_month(_years, _months) != 366)
841
Date& Date::operator+=(const TemporalIntervalDayOrWeek &rhs)
843
/* Simple one...add the days */
844
int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, _days) + rhs._days;
845
gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
849
Date& Date::operator-=(const TemporalIntervalDayOrWeek &rhs)
851
/* Simple one...subtract the days */
852
int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, _days) - rhs._days;
853
gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
857
Date& Date::operator+=(const TemporalIntervalYearMonth &rhs)
859
/* Simple one...add the months in the period adjust */
860
int64_t period= (_years * 12) + (rhs._years * 12) + (_months - 1) + rhs._months;
861
int64_t new_years= (period / 12);
862
if (new_years > DRIZZLE_MAX_YEARS_SQL)
865
* Set everything to zero. We got an overflow.
866
* @TODO Exceptions would be great here...
872
_years= (uint32_t) new_years;
873
_months= (uint32_t) (period % 12) + 1;
875
/* Adjust day if the new month doesn't have enough days */
876
uint32_t days_in_new_month= days_in_gregorian_year_month(_years, _months);
877
if (_days > days_in_new_month)
878
_days= days_in_new_month;
882
Date& Date::operator-=(const TemporalIntervalYearMonth &rhs)
884
/* Simple one...subtract the months in the period and adjust */
885
int64_t period= (_years * 12) - (rhs._years * 12) + (_months - 1) - rhs._months;
886
int64_t new_years= (period / 12);
890
* Set everything to zero. We got an overflow.
891
* @TODO Exceptions would be great here...
897
_years= (uint32_t) (period / 12);
898
_months= (uint32_t) (period % 12) + 1;
900
/* Adjust day if the new month doesn't have enough days */
901
uint32_t days_in_new_month= days_in_gregorian_year_month(_years, _months);
902
if (_days > days_in_new_month)
903
_days= days_in_new_month;
907
Date& Date::operator+=(const TemporalIntervalDayOrLess &rhs)
910
* Convert the temporal and the interval into a number of
911
* microseconds, then add them together and convert the
912
* resulting microseconds back into a broken-down temporal
916
int64_t new_microseconds;
919
new_microseconds= _useconds + rhs._useconds;
920
extra_sec= new_microseconds / INT64_C(1000000);
921
new_microseconds= new_microseconds % INT64_C(1000000);
923
new_seconds= ((_days - 1) * 3600 * 24) + (_hours * 3600) + (_minutes * 60) + _seconds;
924
new_seconds+= (rhs._days * 3600 * 24) + (rhs._hours * 3600) + (rhs._minutes * 60) + rhs._seconds;
925
new_seconds+= extra_sec;
927
if (new_microseconds < 0)
929
new_microseconds+= INT64_C(1000000);
933
new_days= new_seconds / (3600 * 24L);
934
new_seconds-= new_days * 3600 * 24L;
938
new_seconds+= 3600 * 24L;
940
_useconds= (uint32_t) new_microseconds;
941
_seconds= (uint32_t) (new_seconds % 60);
942
_minutes= (uint32_t) ((new_seconds / 60) % 60);
943
_hours= (uint32_t) (new_seconds / 3600);
944
int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, 1) + new_days;
945
gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
949
Date& Date::operator-=(const TemporalIntervalDayOrLess &rhs)
952
* Convert the temporal and the interval into a number of
953
* microseconds, then subtract them from each other and convert
954
* the resulting microseconds back into a broken-down temporal
958
int64_t new_microseconds;
961
new_microseconds= _useconds - rhs._useconds;
962
extra_sec= new_microseconds / INT64_C(1000000);
963
new_microseconds= new_microseconds % INT64_C(1000000);
965
new_seconds= ((_days - 1) * 3600 * 24) + (_hours * 3600) + (_minutes * 60) + _seconds;
966
new_seconds-= (rhs._days * 3600 * 24) + (rhs._hours * 3600) + (rhs._minutes * 60) + rhs._seconds;
967
new_seconds+= extra_sec;
969
if (new_microseconds < 0)
971
new_microseconds+= INT64_C(1000000);
975
new_days= new_seconds / (3600 * 24L);
976
new_seconds-= new_days * 3600 * 24L;
980
new_seconds+= 3600 * 24L;
982
_useconds= (uint32_t) new_microseconds;
983
_seconds= (uint32_t) (new_seconds % 60);
984
_minutes= (uint32_t) ((new_seconds / 60) % 60);
985
_hours= (uint32_t) (new_seconds / 3600);
986
int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, 1) + new_days;
987
gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
990
#endif /* NOTYETIMPLEMENTED */
992
* Comparison operators between a Date and a Timestamp
994
bool Date::operator==(const Timestamp& rhs)
996
return (_years == rhs._years && _months == rhs._months && _days == rhs._days);
998
bool Date::operator!=(const Timestamp& rhs)
1000
return ! (*this == rhs);
1002
bool Date::operator<(const Timestamp& rhs)
1004
if (_years < rhs._years)
1006
if (_years > rhs._years)
1009
if (_months < rhs._months)
1011
if (_months > rhs._months)
1014
return _days < rhs._days;
1016
bool Date::operator<=(const Timestamp& rhs)
1018
return (*this < rhs || *this == rhs);
1020
bool Date::operator>(const Timestamp& rhs)
1022
return ! (*this < rhs);
1024
bool Date::operator>=(const Timestamp& rhs)
1026
return ! (*this <= rhs);
1029
* Comparison operators between a Timestamp and a Date
1031
bool Timestamp::operator==(const Date& rhs)
1033
return (_years == rhs._years && _months == rhs._months && _days == rhs._days);
1035
bool Timestamp::operator!=(const Date& rhs)
1037
return ! (*this == rhs);
1039
bool Timestamp::operator<(const Date& rhs)
1041
if (_years < rhs._years)
1043
if (_years > rhs._years)
1046
if (_months < rhs._months)
1048
if (_months > rhs._months)
1051
return _days < rhs._days;
1053
bool Timestamp::operator<=(const Date& rhs)
1055
return (*this < rhs || *this == rhs);
1057
bool Timestamp::operator>(const Date& rhs)
1059
return ! (*this < rhs);
1061
bool Timestamp::operator>=(const Date& rhs)
1063
return ! (*this <= rhs);
1066
* Comparison operators between a Timestamp and a DateTime
1068
bool Timestamp::operator==(const DateTime& rhs)
1070
return (_years == rhs._years && _months == rhs._months && _days == rhs._days
1071
&& _hours == rhs._hours && _minutes == rhs._minutes && _seconds == rhs._seconds);
1073
bool Timestamp::operator!=(const DateTime& rhs)
1075
return ! (*this == rhs);
1077
bool Timestamp::operator<(const DateTime& rhs)
1079
if (_years < rhs._years)
1081
if (_years > rhs._years)
1084
if (_months < rhs._months)
1086
if (_months > rhs._months)
1089
if (_days < rhs._days)
1091
if (_days > rhs._days)
1094
if (_hours < rhs._hours)
1096
if (_hours > rhs._hours)
1099
if (_minutes < rhs._minutes)
1101
if (_minutes > rhs._minutes)
1104
return _seconds < rhs._seconds;
1106
bool Timestamp::operator<=(const DateTime& rhs)
1108
return (*this < rhs || *this == rhs);
1110
bool Timestamp::operator>(const DateTime& rhs)
1112
return ! (*this < rhs);
1114
bool Timestamp::operator>=(const DateTime& rhs)
1116
return ! (*this <= rhs);
1119
* Comparison operators between two Timestamps
1121
bool Timestamp::operator==(const Timestamp& rhs)
1123
return (_epoch_seconds == rhs._epoch_seconds);
1125
bool Timestamp::operator!=(const Timestamp& rhs)
1127
return ! (*this == rhs);
1129
bool Timestamp::operator<(const Timestamp& rhs)
1131
return (_epoch_seconds < rhs._epoch_seconds);
1133
bool Timestamp::operator<=(const Timestamp& rhs)
1135
return (_epoch_seconds <= rhs._epoch_seconds);
1137
bool Timestamp::operator>(const Timestamp& rhs)
1139
return ! (*this < rhs);
1141
bool Timestamp::operator>=(const Timestamp& rhs)
1143
return ! (*this <= rhs);
1147
* Push the contents of the timestamp into the output stream
1148
* as a formatted Timestamp value.
1150
* @TODO This unfortunately fails in a weird way...even with std::noskipws,
1151
* the output stream only reads up to the space in the string... :(
1153
std::ostream& operator<<(std::ostream& os, const Timestamp& subject)
1155
return os << subject.years() << '-'
1156
<< std::setw(2) << std::setfill('0') << subject.months() << '-'
1157
<< std::setw(2) << std::setfill('0') << subject.days() << ' '
1158
<< std::setw(2) << std::setfill('0') << subject.hours() << ':'
1159
<< std::setw(2) << std::setfill('0') << subject.minutes() << ':'
1160
<< std::setw(2) << std::setfill('0') << subject.seconds();
1163
bool Time::from_string(const char *from, size_t from_len)
1166
* Loop through the known time formats and see if
1169
bool matched= false;
1170
TemporalFormat *current_format;
1171
std::vector<TemporalFormat *>::iterator current= known_time_formats.begin();
1173
while (current != known_time_formats.end())
1175
current_format= *current;
1176
if (current_format->matches(from, from_len, this))
1190
int Time::to_string(char *to, size_t to_len) const
1192
return snprintf(to, to_len,
1193
"%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32,
1194
_hours, _minutes, _seconds);
1197
int Date::to_string(char *to, size_t to_len) const
1199
return snprintf(to, to_len,
1200
"%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32,
1201
_years, _months, _days);
1204
int DateTime::to_string(char *to, size_t to_len) const
1206
/* If the temporal has a microsecond component, use a slightly different output */
1209
return snprintf(to, to_len,
1210
"%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
1211
" %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32,
1212
_years, _months, _days,
1213
_hours, _minutes, _seconds);
1217
return snprintf(to, to_len,
1218
"%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
1219
" %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32,
1220
_years, _months, _days,
1221
_hours, _minutes, _seconds, _useconds);
1225
int MicroTimestamp::to_string(char *to, size_t to_len) const
1227
return snprintf(to, to_len,
1228
"%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
1229
" %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32,
1230
_years, _months, _days,
1231
_hours, _minutes, _seconds, _useconds);
1234
void Time::to_decimal(my_decimal *to) const
1236
int64_t time_portion= (((_hours * 100L) + _minutes) * 100L) + _seconds;
1237
(void) int2my_decimal(E_DEC_FATAL_ERROR, time_portion, false, to);
1240
to->buf[(to->intg-1) / 9 + 1]= _useconds * 1000;
1245
void Date::to_decimal(my_decimal *to) const
1247
int64_t date_portion= (((_years * 100L) + _months) * 100L) + _days;
1248
(void) int2my_decimal(E_DEC_FATAL_ERROR, date_portion, false, to);
1251
void DateTime::to_decimal(my_decimal *to) const
1253
int64_t date_portion= (((_years * 100L) + _months) * 100L) + _days;
1254
int64_t time_portion= (((((date_portion * 100L) + _hours) * 100L) + _minutes) * 100L) + _seconds;
1255
(void) int2my_decimal(E_DEC_FATAL_ERROR, time_portion, false, to);
1258
to->buf[(to->intg-1) / 9 + 1]= _useconds * 1000;
1263
void Date::to_int64_t(int64_t *to) const
1265
*to= (_years * INT32_C(10000))
1266
+ (_months * INT32_C(100))
1270
void Date::to_int32_t(int32_t *to) const
1272
*to= (_years * INT32_C(10000))
1273
+ (_months * INT32_C(100))
1277
void Time::to_int32_t(int32_t *to) const
1279
*to= (_hours * INT32_C(10000))
1280
+ (_minutes * INT32_C(100))
1284
void DateTime::to_int64_t(int64_t *to) const
1287
(_years * INT64_C(10000))
1288
+ (_months * INT64_C(100))
1290
) * INT64_C(1000000))
1292
(_hours * INT64_C(10000))
1293
+ (_minutes * INT64_C(100) )
1298
void Date::to_tm(struct tm *to) const
1303
to->tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
1304
to->tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
1305
to->tm_year= _years - 1900;
1308
void DateTime::to_tm(struct tm *to) const
1310
to->tm_sec= _seconds;
1311
to->tm_min= _minutes;
1312
to->tm_hour= _hours;
1313
to->tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
1314
to->tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
1315
to->tm_year= _years - 1900;
1318
bool Date::from_julian_day_number(const int64_t from)
1320
gregorian_date_from_julian_day_number(from, &_years, &_months, &_days);
1324
void Date::to_julian_day_number(int64_t *to) const
1326
*to= julian_day_number_from_gregorian_date(_years, _months, _days);
1330
* Ignore overflow and pass-through to DateTime::from_int64_t()
1332
bool Date::from_int32_t(const int32_t from)
1334
return ((DateTime *) this)->from_int64_t((int64_t) from);
1338
* Attempt to interpret the supplied 4-byte integer as
1339
* a TIME value in the format HHmmSS
1341
bool Time::from_int32_t(const int32_t from)
1343
uint32_t copy_from= (uint32_t) from;
1344
_hours= copy_from % INT32_C(10000);
1345
_minutes= copy_from % INT32_C(100);
1346
_seconds= copy_from & 3; /* Masks off all but last 2 digits */
1351
* We try to intepret the incoming number as a datetime "string".
1352
* This is pretty much a hack for usability, but keeps us compatible
1355
bool DateTime::from_int64_t(const int64_t from, bool convert)
1357
int64_t copy_from= from;
1361
if (copy_from == 0LL)
1364
if (convert && copy_from < 10000101000000LL)
1366
if (copy_from < 101)
1368
else if (copy_from <= (DRIZZLE_YY_PART_YEAR-1)*10000L+1231L)
1369
copy_from= (copy_from+20000000L)*1000000L; /* YYMMDD, year: 2000-2069 */
1370
else if (copy_from < (DRIZZLE_YY_PART_YEAR)*10000L+101L)
1372
else if (copy_from <= 991231L)
1373
copy_from= (copy_from+19000000L)*1000000L; /* YYMMDD, year: 1970-1999 */
1374
else if (copy_from < 10000101L)
1376
else if (copy_from <= 99991231L)
1377
copy_from= copy_from*1000000L;
1378
else if (copy_from < 101000000L)
1380
else if (copy_from <= (DRIZZLE_YY_PART_YEAR-1) * 10000000000LL + 1231235959LL)
1381
copy_from= copy_from + 20000000000000LL; /* YYMMDDHHMMSS, 2000-2069 */
1382
else if (copy_from < DRIZZLE_YY_PART_YEAR * 10000000000LL + 101000000LL)
1384
else if (copy_from <= 991231235959LL)
1385
copy_from= copy_from + 19000000000000LL; /* YYMMDDHHMMSS, 1970-1999 */
1388
part1= (int64_t) (copy_from / 1000000LL);
1389
part2= (int64_t) (copy_from - (int64_t) part1 * 1000000LL);
1390
_years= (uint32_t) (part1/10000L);
1393
_months= (uint32_t) part1 / 100;
1394
_days= (uint32_t) part1 % 100;
1395
_hours= (uint32_t) (part2/10000L);
1398
_minutes= (uint32_t) part2 / 100;
1399
_seconds= (uint32_t) part2 % 100;
1401
set_epoch_seconds();
1405
bool Date::in_unix_epoch() const
1407
return in_unix_epoch_range(_years, _months, _days, 0, 0, 0);
1410
bool DateTime::in_unix_epoch() const
1412
return in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds);
1415
bool Date::from_tm(const struct tm *from)
1417
_years= 1900 + from->tm_year;
1418
_months= 1 + from->tm_mon; /* Month is NOT ordinal for struct tm! */
1419
_days= from->tm_mday; /* Day IS ordinal for struct tm */
1420
_hours= from->tm_hour;
1421
_minutes= from->tm_min;
1422
_seconds= from->tm_sec;
1423
/* Set hires precision to zero */
1427
set_epoch_seconds();
1432
* We convert as if it's a Datetime, then simply
1433
* drop the date portions...
1435
bool Time::from_time_t(const time_t from)
1437
struct tm broken_time;
1440
result= gmtime_r(&from, &broken_time);
1446
_hours= broken_time.tm_hour;
1447
_minutes= broken_time.tm_min;
1448
_seconds= broken_time.tm_sec;
1449
_epoch_seconds= 0; /* Don't store the time_t, since we only use part of it */
1450
/* Set hires precision to zero */
1453
return true; /* Always true... */
1459
bool Date::from_time_t(const time_t from)
1461
struct tm broken_time;
1464
result= gmtime_r(&from, &broken_time);
1467
_years= 1900 + broken_time.tm_year;
1468
_months= 1 + broken_time.tm_mon; /* Month is NOT ordinal for struct tm! */
1469
_days= broken_time.tm_mday; /* Day IS ordinal for struct tm */
1473
_epoch_seconds= 0; /* Don't store the time_t, since we only use part of it */
1474
/* Set hires precision to zero */
1483
bool DateTime::from_time_t(const time_t from)
1485
struct tm broken_time;
1488
result= gmtime_r(&from, &broken_time);
1491
_years= 1900 + broken_time.tm_year;
1492
_months= 1 + broken_time.tm_mon; /* Month is NOT ordinal for struct tm! */
1493
_days= broken_time.tm_mday; /* Day IS ordinal for struct tm */
1494
_hours= broken_time.tm_hour;
1495
_minutes= broken_time.tm_min;
1496
_seconds= broken_time.tm_sec;
1497
_epoch_seconds= from;
1498
/* Set hires precision to zero */
1507
void Date::to_time_t(time_t *to) const
1509
if (in_unix_epoch())
1511
*to= _epoch_seconds;
1517
void Timestamp::to_time_t(time_t *to) const
1519
*to= _epoch_seconds;
1522
void MicroTimestamp::to_timeval(struct timeval *to) const
1524
to->tv_sec= _epoch_seconds;
1525
to->tv_usec= _useconds;
1528
void NanoTimestamp::to_timespec(struct timespec *to) const
1530
to->tv_sec= _epoch_seconds;
1531
to->tv_nsec= _nseconds;
1534
bool Date::is_valid() const
1536
return (_years >= DRIZZLE_MIN_YEARS_SQL && _years <= DRIZZLE_MAX_YEARS_SQL)
1537
&& (_months >= 1 && _months <= 12)
1538
&& (_days >= 1 && _days <= days_in_gregorian_year_month(_years, _months));
1541
bool Time::is_valid() const
1543
return (_years == 0)
1548
&& (_seconds <= 59); /* No Leap second... TIME is for elapsed time... */
1551
bool DateTime::is_valid() const
1553
return (_years >= DRIZZLE_MIN_YEARS_SQL && _years <= DRIZZLE_MAX_YEARS_SQL)
1554
&& (_months >= 1 && _months <= 12)
1555
&& (_days >= 1 && _days <= days_in_gregorian_year_month(_years, _months))
1558
&& (_seconds <= 61); /* Leap second... */
1561
bool Timestamp::is_valid() const
1563
return DateTime::is_valid()
1564
&& in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds);
1567
bool MicroTimestamp::is_valid() const
1569
return Timestamp::is_valid()
1570
&& (_useconds <= UINT32_C(999999));
1573
bool NanoTimestamp::is_valid() const
1575
return Timestamp::is_valid()
1576
&& (_useconds <= UINT32_C(999999))
1577
&& (_nseconds <= UINT32_C(999999999));
1580
} /* end namespace drizzled */