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"
53
/* time.h may already have been included in global.h, but we
54
need to pick up the extra defs as well, after the global time.h */
55
#ifndef HAVE_DECL_TIMEGM
56
# include <gnulib/time.h>
59
extern std::vector<drizzled::TemporalFormat *> known_datetime_formats;
60
extern std::vector<drizzled::TemporalFormat *> known_date_formats;
61
extern std::vector<drizzled::TemporalFormat *> known_time_formats;
81
uint64_t Temporal::_cumulative_seconds_in_time() const
83
return (uint64_t) ((_hours * INT64_C(3600))
84
+ (_minutes * INT64_C(60))
88
void Temporal::set_epoch_seconds()
91
* If the temporal is in the range of a timestamp, set
92
* the epoch_seconds member variable
94
if (in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds))
97
struct tm broken_time;
99
broken_time.tm_sec= _seconds;
100
broken_time.tm_min= _minutes;
101
broken_time.tm_hour= _hours;
102
broken_time.tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
103
broken_time.tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
104
broken_time.tm_year= _years - 1900; /* tm_year expects range of 70 - 38 */
106
result_time= timegm(&broken_time);
108
_epoch_seconds= result_time;
112
bool Date::from_string(const char *from, size_t from_len)
115
* Loop through the known date formats and see if
119
TemporalFormat *current_format;
120
std::vector<TemporalFormat *>::iterator current= known_date_formats.begin();
122
while (current != known_date_formats.end())
124
current_format= *current;
125
if (current_format->matches(from, from_len, this))
140
bool DateTime::from_string(const char *from, size_t from_len)
143
* Loop through the known datetime formats and see if
147
TemporalFormat *current_format;
148
std::vector<TemporalFormat *>::iterator current= known_datetime_formats.begin();
150
while (current != known_datetime_formats.end())
152
current_format= *current;
153
if (current_format->matches(from, from_len, this))
169
* Comparison operators for Time against another Time
170
* are easy. We simply compare the cumulative time
173
bool Time::operator==(const Time& rhs)
177
&& _minutes == rhs._minutes
178
&& _seconds == rhs._seconds
179
&& _useconds == rhs._useconds
180
&& _nseconds == rhs._nseconds
183
bool Time::operator!=(const Time& rhs)
185
return ! (*this == rhs);
187
bool Time::operator<(const Time& rhs)
189
return (_cumulative_seconds_in_time() < rhs._cumulative_seconds_in_time());
191
bool Time::operator<=(const Time& rhs)
193
return (_cumulative_seconds_in_time() <= rhs._cumulative_seconds_in_time());
195
bool Time::operator>(const Time& rhs)
197
return (_cumulative_seconds_in_time() > rhs._cumulative_seconds_in_time());
199
bool Time::operator>=(const Time& rhs)
201
return (_cumulative_seconds_in_time() >= rhs._cumulative_seconds_in_time());
205
* Subtracting one Time value from another can yield
206
* a new Time instance.
208
* This operator is called in the following situation:
211
* drizzled::Time lhs;
212
* lhs.from_string("20:00:00");
213
* drizzled::Time rhs;
214
* rhs.from_string("19:00:00");
216
* drizzled::Time result= lhs - rhs;
221
* Subtracting a larger time value from a smaller one
222
* should throw an exception at some point. The result
223
* of such an operator should be a TemporalInterval, not
224
* a Time instance, since a negative time is not possible.
226
const Time Time::operator-(const Time& rhs)
230
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
231
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
232
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
233
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
234
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
235
result._seconds= (uint32_t) second_diff;
239
const Time Time::operator+(const Time& rhs)
242
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
243
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
244
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
245
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
246
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
247
result._seconds= (uint32_t) second_diff;
249
* @TODO Once exceptions are supported, we should raise an error here if
250
* the result Time is not valid?
256
* Variation of + and - operator which returns a reference to the left-hand
257
* side Time object and adds the right-hand side to itself.
259
Time& Time::operator+=(const Time& rhs)
261
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
262
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
263
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
264
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
265
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
266
_seconds= (uint32_t) second_diff;
268
* @TODO Once exceptions are supported, we should raise an error here if
269
* the result Time is not valid?
273
Time& Time::operator-=(const Time& rhs)
275
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
276
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
277
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
278
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
279
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
280
_seconds= (uint32_t) second_diff;
282
* @TODO Once exceptions are supported, we should raise an error here if
283
* the result Time is not valid?
289
* Comparison operators for Date against another Date
290
* are easy. We simply compare the cumulative
293
bool Date::operator==(const Date& rhs)
297
&& _months == rhs._months
298
&& _days == rhs._days
301
bool Date::operator!=(const Date& rhs)
303
return ! (*this == rhs);
305
bool Date::operator<(const Date& rhs)
307
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
308
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
309
return (days_left < days_right);
311
bool Date::operator<=(const Date& rhs)
313
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
314
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
315
return (days_left <= days_right);
317
bool Date::operator>(const Date& rhs)
319
return ! (*this <= rhs);
321
bool Date::operator>=(const Date& rhs)
323
return ! (*this < rhs);
327
* Comparison operators for DateTime against another DateTime
328
* are easy. We simply compare the cumulative time
331
bool Date::operator==(const DateTime& rhs)
335
&& _months == rhs._months
336
&& _days == rhs._days
337
&& _hours == rhs._hours
338
&& _minutes == rhs._minutes
339
&& _seconds == rhs._seconds
340
&& _useconds == rhs._useconds
341
&& _nseconds == rhs._nseconds
344
bool Date::operator!=(const DateTime& rhs)
346
return ! (*this == rhs);
348
bool Date::operator<(const DateTime& rhs)
350
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
351
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
352
if (days_left < days_right)
354
else if (days_left > days_right)
356
/* Here if both dates are the same, so compare times */
357
return (_cumulative_seconds_in_time() < rhs._cumulative_seconds_in_time());
359
bool Date::operator<=(const DateTime& rhs)
361
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
362
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
363
if (days_left < days_right)
365
else if (days_left > days_right)
367
/* Here if both dates are the same, so compare times */
368
return (_cumulative_seconds_in_time() <= rhs._cumulative_seconds_in_time());
370
bool Date::operator>(const DateTime& rhs)
372
return ! (*this <= rhs);
374
bool Date::operator>=(const DateTime& rhs)
376
return ! (*this < rhs);
380
* We can add or subtract a Time value to/from a DateTime value
381
* as well...it always produces a DateTime.
383
const Date Date::operator-(const Time& rhs)
388
* First, we set the resulting DATE pieces equal to our
389
* left-hand side DateTime's DATE components. Then, deal with
390
* the time components.
392
result._years= _years;
393
result._months= _months;
396
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
399
* The resulting diff might be negative. If it is, that means that
400
* we have subtracting a larger time piece from the datetime, like so:
402
* x = DateTime("2007-06-09 09:30:00") - Time("16:30:00");
404
* In these cases, we need to subtract a day from the resulting
410
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
411
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
412
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
413
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
414
result._seconds= (uint32_t) second_diff;
416
/* Handle the microsecond precision */
417
int64_t microsecond_diff= _useconds - rhs._useconds;
418
if (microsecond_diff < 0)
420
microsecond_diff= (-1 * microsecond_diff);
423
result._useconds= (uint32_t) microsecond_diff;
427
const Date Date::operator+(const Time& rhs)
432
* First, we set the resulting DATE pieces equal to our
433
* left-hand side DateTime's DATE components. Then, deal with
434
* the time components.
436
result._years= _years;
437
result._months= _months;
440
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
443
* The resulting seconds might be more than a day. If do,
444
* adjust our resulting days up 1.
446
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
449
second_diff%= DRIZZLE_SECONDS_IN_DAY;
452
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
453
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
454
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
455
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
456
result._seconds= (uint32_t) second_diff;
458
/* Handle the microsecond precision */
459
int64_t microsecond_diff= _useconds - rhs._useconds;
460
if (microsecond_diff < 0)
462
microsecond_diff= (-1 * microsecond_diff);
465
result._useconds= (uint32_t) microsecond_diff;
471
* Variation of + and - operator which returns a reference to the left-hand
472
* side DateTime object and adds the right-hand side Time to itself.
474
Date& Date::operator+=(const Time& rhs)
476
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
478
* The resulting seconds might be more than a day. If do,
479
* adjust our resulting days up 1.
481
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
484
second_diff%= DRIZZLE_SECONDS_IN_DAY;
487
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
488
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
489
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
490
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
491
_seconds= (uint32_t) second_diff;
493
/* Handle the microsecond precision */
494
int64_t microsecond_diff= _useconds - rhs._useconds;
495
if (microsecond_diff < 0)
497
microsecond_diff= (-1 * microsecond_diff);
500
_useconds= (uint32_t) microsecond_diff;
502
* @TODO Once exceptions are supported, we should raise an error here if
503
* the result Time is not valid?
507
Date& Date::operator-=(const Time& rhs)
509
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
512
* The resulting diff might be negative. If it is, that means that
513
* we have subtracting a larger time piece from the datetime, like so:
515
* x = DateTime("2007-06-09 09:30:00");
516
* x-= Time("16:30:00");
518
* In these cases, we need to subtract a day from the resulting
524
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
525
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
526
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
527
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
528
_seconds= (uint32_t) second_diff;
530
/* Handle the microsecond precision */
531
int64_t microsecond_diff= _useconds - rhs._useconds;
532
if (microsecond_diff < 0)
534
microsecond_diff= (-1 * microsecond_diff);
537
_useconds= (uint32_t) microsecond_diff;
539
* @TODO Once exceptions are supported, we should raise an error here if
540
* the result Time is not valid?
546
* We can add/subtract two Dates to/from each other. The result
547
* is always another Date instance.
549
const Date Date::operator-(const Date &rhs)
551
/* Figure out the difference in days between the two dates */
552
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
553
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
554
int64_t day_diff= day_left - day_right;
557
/* Now re-compose the Date's structure from the resulting Julian Day Number */
558
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
561
const Date Date::operator+(const Date &rhs)
564
* Figure out the new Julian Day Number by adding the JDNs of both
567
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
568
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
569
int64_t day_diff= day_left + day_right;
571
/** @TODO Need an exception check here for bounds of JDN... */
574
/* Now re-compose the Date's structure from the resulting Julian Day Number */
575
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
578
/* Similar to the above, but we add/subtract the right side to this object itself */
579
Date& Date::operator-=(const Date &rhs)
581
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
582
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
583
int64_t day_diff= day_left - day_right;
585
/* Now re-compose the Date's structure from the resulting Julian Day Number */
586
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
589
Date& Date::operator+=(const Date &rhs)
592
* Figure out the new Julian Day Number by adding the JDNs of both
595
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
596
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
597
int64_t day_diff= day_left + day_right;
599
/** @TODO Need an exception check here for bounds of JDN... */
601
/* Now re-compose the Date's structure from the resulting Julian Day Number */
602
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
606
Date& Date::operator=(const DateTime &rhs)
608
/* Only copy the Date components of the assigned DateTime... */
610
_months= rhs._months;
612
/* Zero-out everything else.. */
613
_hours= _minutes= _seconds= _useconds= _nseconds= 0;
618
* We can add/subtract two DateTimes to/from each other. The result
619
* is always another DateTime instance.
621
const Date Date::operator-(const DateTime &rhs)
623
/* Figure out the difference in days between the two dates. */
624
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
625
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
626
int64_t day_diff= day_left - day_right;
629
/* Now re-compose the Date's structure from the resulting Julian Day Number */
630
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
632
/* And now handle the time components */
633
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
636
* The resulting diff might be negative. If it is, that means that
637
* we have subtracting a larger time piece from the datetime, like so:
639
* x = DateTime("2007-06-09 09:30:00");
640
* x-= Time("16:30:00");
642
* In these cases, we need to subtract a day from the resulting
648
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
649
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
650
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
651
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
652
result._seconds= (uint32_t) second_diff;
654
/* Handle the microsecond precision */
655
int64_t microsecond_diff= _useconds - rhs._useconds;
656
if (microsecond_diff < 0)
658
microsecond_diff= (-1 * microsecond_diff);
661
result._useconds= (uint32_t) microsecond_diff;
665
const Date Date::operator+(const DateTime &rhs)
668
* Figure out the new Julian Day Number by adding the JDNs of both
671
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
672
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
673
int64_t day_diff= day_left + day_right;
675
/** @TODO Need an exception check here for bounds of JDN... */
678
/* Now re-compose the Date's structure from the resulting Julian Day Number */
679
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
681
/* And now handle the time components */
682
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
685
* The resulting seconds might be more than a day. If do,
686
* adjust our resulting days up 1.
688
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
691
second_diff%= DRIZZLE_SECONDS_IN_DAY;
694
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
695
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
696
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
697
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
698
result._seconds= (uint32_t) second_diff;
700
/* Handle the microsecond precision */
701
int64_t microsecond_diff= _useconds - rhs._useconds;
702
if (microsecond_diff < 0)
704
microsecond_diff= (-1 * microsecond_diff);
707
result._useconds= (uint32_t) microsecond_diff;
711
/* Similar to the above, but we add/subtract the right side to this object itself */
712
Date& Date::operator-=(const DateTime &rhs)
714
/* Figure out the difference in days between the two dates. */
715
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
716
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
717
int64_t day_diff= day_left - day_right;
719
/* Now re-compose the Date's structure from the ng Julian Day Number */
720
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
722
/* And now handle the time components */
723
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
726
* The resulting diff might be negative. If it is, that means that
727
* we have subtracting a larger time piece from the datetime, like so:
729
* x = DateTime("2007-06-09 09:30:00");
730
* x-= Time("16:30:00");
732
* In these cases, we need to subtract a day from the ng
738
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
739
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
740
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
741
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
742
_seconds= (uint32_t) second_diff;
744
/* Handle the microsecond precision */
745
int64_t microsecond_diff= _useconds - rhs._useconds;
746
if (microsecond_diff < 0)
748
microsecond_diff= (-1 * microsecond_diff);
751
_useconds= (uint32_t) microsecond_diff;
755
Date& Date::operator+=(const DateTime &rhs)
758
* Figure out the new Julian Day Number by adding the JDNs of both
761
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
762
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
763
int64_t day_diff= day_left + day_right;
765
/** @TODO Need an exception check here for bounds of JDN... */
767
/* Now re-compose the Date's structure from the ng Julian Day Number */
768
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
770
/* And now handle the time components */
771
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
774
* The resulting seconds might be more than a day. If do,
775
* adjust our ng days up 1.
777
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
780
second_diff%= DRIZZLE_SECONDS_IN_DAY;
783
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
784
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
785
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
786
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
787
_seconds= (uint32_t) second_diff;
789
/* Handle the microsecond precision */
790
int64_t microsecond_diff= _useconds - rhs._useconds;
791
if (microsecond_diff < 0)
793
microsecond_diff= (-1 * microsecond_diff);
796
_useconds= (uint32_t) microsecond_diff;
800
#ifdef NOTYETIMPLEMENTED
801
Date& Date::operator+=(const TemporalIntervalYear &rhs)
803
/* Simple one...add the years and adjust for any leaps */
804
int64_t new_years= _years;
805
new_years+= rhs._years;
806
if (new_years > DRIZZLE_MAX_YEARS_SQL)
809
* Set everything to zero. We got an overflow.
810
* @TODO Exceptions would be great here...
816
_years= (uint32_t) new_years;
817
if (_months == 2 && _days == 29 && days_in_gregorian_year_month(_years, _months) != 366)
822
Date& Date::operator-=(const TemporalIntervalYear &rhs)
824
/* Simple one...subtract the years and adjust for any leaps */
825
int64_t new_years= _years;
826
new_years-= rhs._years;
830
* Set everything to zero. We got an overflow.
831
* @TODO Exceptions would be great here...
837
_years= (uint32_t) new_years;
838
if (_months == 2 && _days == 29 && days_in_gregorian_year_month(_years, _months) != 366)
843
Date& Date::operator+=(const TemporalIntervalDayOrWeek &rhs)
845
/* Simple one...add the days */
846
int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, _days) + rhs._days;
847
gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
851
Date& Date::operator-=(const TemporalIntervalDayOrWeek &rhs)
853
/* Simple one...subtract the days */
854
int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, _days) - rhs._days;
855
gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
859
Date& Date::operator+=(const TemporalIntervalYearMonth &rhs)
861
/* Simple one...add the months in the period adjust */
862
int64_t period= (_years * 12) + (rhs._years * 12) + (_months - 1) + rhs._months;
863
int64_t new_years= (period / 12);
864
if (new_years > DRIZZLE_MAX_YEARS_SQL)
867
* Set everything to zero. We got an overflow.
868
* @TODO Exceptions would be great here...
874
_years= (uint32_t) new_years;
875
_months= (uint32_t) (period % 12) + 1;
877
/* Adjust day if the new month doesn't have enough days */
878
uint32_t days_in_new_month= days_in_gregorian_year_month(_years, _months);
879
if (_days > days_in_new_month)
880
_days= days_in_new_month;
884
Date& Date::operator-=(const TemporalIntervalYearMonth &rhs)
886
/* Simple one...subtract the months in the period and adjust */
887
int64_t period= (_years * 12) - (rhs._years * 12) + (_months - 1) - rhs._months;
888
int64_t new_years= (period / 12);
892
* Set everything to zero. We got an overflow.
893
* @TODO Exceptions would be great here...
899
_years= (uint32_t) (period / 12);
900
_months= (uint32_t) (period % 12) + 1;
902
/* Adjust day if the new month doesn't have enough days */
903
uint32_t days_in_new_month= days_in_gregorian_year_month(_years, _months);
904
if (_days > days_in_new_month)
905
_days= days_in_new_month;
909
Date& Date::operator+=(const TemporalIntervalDayOrLess &rhs)
912
* Convert the temporal and the interval into a number of
913
* microseconds, then add them together and convert the
914
* resulting microseconds back into a broken-down temporal
918
int64_t new_microseconds;
921
new_microseconds= _useconds + rhs._useconds;
922
extra_sec= new_microseconds / INT64_C(1000000);
923
new_microseconds= new_microseconds % INT64_C(1000000);
925
new_seconds= ((_days - 1) * 3600 * 24) + (_hours * 3600) + (_minutes * 60) + _seconds;
926
new_seconds+= (rhs._days * 3600 * 24) + (rhs._hours * 3600) + (rhs._minutes * 60) + rhs._seconds;
927
new_seconds+= extra_sec;
929
if (new_microseconds < 0)
931
new_microseconds+= INT64_C(1000000);
935
new_days= new_seconds / (3600 * 24L);
936
new_seconds-= new_days * 3600 * 24L;
940
new_seconds+= 3600 * 24L;
942
_useconds= (uint32_t) new_microseconds;
943
_seconds= (uint32_t) (new_seconds % 60);
944
_minutes= (uint32_t) ((new_seconds / 60) % 60);
945
_hours= (uint32_t) (new_seconds / 3600);
946
int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, 1) + new_days;
947
gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
951
Date& Date::operator-=(const TemporalIntervalDayOrLess &rhs)
954
* Convert the temporal and the interval into a number of
955
* microseconds, then subtract them from each other and convert
956
* the resulting microseconds back into a broken-down temporal
960
int64_t new_microseconds;
963
new_microseconds= _useconds - rhs._useconds;
964
extra_sec= new_microseconds / INT64_C(1000000);
965
new_microseconds= new_microseconds % INT64_C(1000000);
967
new_seconds= ((_days - 1) * 3600 * 24) + (_hours * 3600) + (_minutes * 60) + _seconds;
968
new_seconds-= (rhs._days * 3600 * 24) + (rhs._hours * 3600) + (rhs._minutes * 60) + rhs._seconds;
969
new_seconds+= extra_sec;
971
if (new_microseconds < 0)
973
new_microseconds+= INT64_C(1000000);
977
new_days= new_seconds / (3600 * 24L);
978
new_seconds-= new_days * 3600 * 24L;
982
new_seconds+= 3600 * 24L;
984
_useconds= (uint32_t) new_microseconds;
985
_seconds= (uint32_t) (new_seconds % 60);
986
_minutes= (uint32_t) ((new_seconds / 60) % 60);
987
_hours= (uint32_t) (new_seconds / 3600);
988
int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, 1) + new_days;
989
gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
992
#endif /* NOTYETIMPLEMENTED */
994
* Comparison operators between a Date and a Timestamp
996
bool Date::operator==(const Timestamp& rhs)
998
return (_years == rhs._years && _months == rhs._months && _days == rhs._days);
1000
bool Date::operator!=(const Timestamp& rhs)
1002
return ! (*this == rhs);
1004
bool Date::operator<(const Timestamp& rhs)
1006
if (_years < rhs._years)
1008
if (_years > rhs._years)
1011
if (_months < rhs._months)
1013
if (_months > rhs._months)
1016
return _days < rhs._days;
1018
bool Date::operator<=(const Timestamp& rhs)
1020
return (*this < rhs || *this == rhs);
1022
bool Date::operator>(const Timestamp& rhs)
1024
return ! (*this < rhs);
1026
bool Date::operator>=(const Timestamp& rhs)
1028
return ! (*this <= rhs);
1031
* Comparison operators between a Timestamp and a Date
1033
bool Timestamp::operator==(const Date& rhs)
1035
return (_years == rhs._years && _months == rhs._months && _days == rhs._days);
1037
bool Timestamp::operator!=(const Date& rhs)
1039
return ! (*this == rhs);
1041
bool Timestamp::operator<(const Date& rhs)
1043
if (_years < rhs._years)
1045
if (_years > rhs._years)
1048
if (_months < rhs._months)
1050
if (_months > rhs._months)
1053
return _days < rhs._days;
1055
bool Timestamp::operator<=(const Date& rhs)
1057
return (*this < rhs || *this == rhs);
1059
bool Timestamp::operator>(const Date& rhs)
1061
return ! (*this < rhs);
1063
bool Timestamp::operator>=(const Date& rhs)
1065
return ! (*this <= rhs);
1068
* Comparison operators between a Timestamp and a DateTime
1070
bool Timestamp::operator==(const DateTime& rhs)
1072
return (_years == rhs._years && _months == rhs._months && _days == rhs._days
1073
&& _hours == rhs._hours && _minutes == rhs._minutes && _seconds == rhs._seconds);
1075
bool Timestamp::operator!=(const DateTime& rhs)
1077
return ! (*this == rhs);
1079
bool Timestamp::operator<(const DateTime& rhs)
1081
if (_years < rhs._years)
1083
if (_years > rhs._years)
1086
if (_months < rhs._months)
1088
if (_months > rhs._months)
1091
if (_days < rhs._days)
1093
if (_days > rhs._days)
1096
if (_hours < rhs._hours)
1098
if (_hours > rhs._hours)
1101
if (_minutes < rhs._minutes)
1103
if (_minutes > rhs._minutes)
1106
return _seconds < rhs._seconds;
1108
bool Timestamp::operator<=(const DateTime& rhs)
1110
return (*this < rhs || *this == rhs);
1112
bool Timestamp::operator>(const DateTime& rhs)
1114
return ! (*this < rhs);
1116
bool Timestamp::operator>=(const DateTime& rhs)
1118
return ! (*this <= rhs);
1121
* Comparison operators between two Timestamps
1123
bool Timestamp::operator==(const Timestamp& rhs)
1125
return (_epoch_seconds == rhs._epoch_seconds);
1127
bool Timestamp::operator!=(const Timestamp& rhs)
1129
return ! (*this == rhs);
1131
bool Timestamp::operator<(const Timestamp& rhs)
1133
return (_epoch_seconds < rhs._epoch_seconds);
1135
bool Timestamp::operator<=(const Timestamp& rhs)
1137
return (_epoch_seconds <= rhs._epoch_seconds);
1139
bool Timestamp::operator>(const Timestamp& rhs)
1141
return ! (*this < rhs);
1143
bool Timestamp::operator>=(const Timestamp& rhs)
1145
return ! (*this <= rhs);
1149
* Push the contents of the timestamp into the output stream
1150
* as a formatted Timestamp value.
1152
* @TODO This unfortunately fails in a weird way...even with std::noskipws,
1153
* the output stream only reads up to the space in the string... :(
1155
std::ostream& operator<<(std::ostream& os, const Timestamp& subject)
1157
return os << subject.years() << '-'
1158
<< std::setw(2) << std::setfill('0') << subject.months() << '-'
1159
<< std::setw(2) << std::setfill('0') << subject.days() << ' '
1160
<< std::setw(2) << std::setfill('0') << subject.hours() << ':'
1161
<< std::setw(2) << std::setfill('0') << subject.minutes() << ':'
1162
<< std::setw(2) << std::setfill('0') << subject.seconds();
1165
bool Time::from_string(const char *from, size_t from_len)
1168
* Loop through the known time formats and see if
1171
bool matched= false;
1172
TemporalFormat *current_format;
1173
std::vector<TemporalFormat *>::iterator current= known_time_formats.begin();
1175
while (current != known_time_formats.end())
1177
current_format= *current;
1178
if (current_format->matches(from, from_len, this))
1192
void Time::to_string(char *to, size_t *to_len) const
1195
, "%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32
1201
void Date::to_string(char *to, size_t *to_len) const
1204
, "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
1210
void DateTime::to_string(char *to, size_t *to_len) const
1212
/* If the temporal has a microsecond component, use a slightly different output */
1216
, "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32 " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32
1227
, "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32 " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32
1238
void MicroTimestamp::to_string(char *to, size_t *to_len) const
1241
, "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32 " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32
1251
void Time::to_decimal(my_decimal *to) const
1253
int64_t time_portion= (((_hours * 100L) + _minutes) * 100L) + _seconds;
1254
(void) int2my_decimal(E_DEC_FATAL_ERROR, time_portion, false, to);
1257
to->buf[(to->intg-1) / 9 + 1]= _useconds * 1000;
1262
void Date::to_decimal(my_decimal *to) const
1264
int64_t date_portion= (((_years * 100L) + _months) * 100L) + _days;
1265
(void) int2my_decimal(E_DEC_FATAL_ERROR, date_portion, false, to);
1268
void DateTime::to_decimal(my_decimal *to) const
1270
int64_t date_portion= (((_years * 100L) + _months) * 100L) + _days;
1271
int64_t time_portion= (((((date_portion * 100L) + _hours) * 100L) + _minutes) * 100L) + _seconds;
1272
(void) int2my_decimal(E_DEC_FATAL_ERROR, time_portion, false, to);
1275
to->buf[(to->intg-1) / 9 + 1]= _useconds * 1000;
1280
void Date::to_int64_t(int64_t *to) const
1282
*to= (_years * INT32_C(10000))
1283
+ (_months * INT32_C(100))
1287
void Date::to_int32_t(int32_t *to) const
1289
*to= (_years * INT32_C(10000))
1290
+ (_months * INT32_C(100))
1294
void Time::to_int32_t(int32_t *to) const
1296
*to= (_hours * INT32_C(10000))
1297
+ (_minutes * INT32_C(100))
1301
void DateTime::to_int64_t(int64_t *to) const
1304
(_years * INT64_C(10000))
1305
+ (_months * INT64_C(100))
1307
) * INT64_C(1000000))
1309
(_hours * INT64_C(10000))
1310
+ (_minutes * INT64_C(100) )
1315
void Date::to_tm(struct tm *to) const
1320
to->tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
1321
to->tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
1322
to->tm_year= _years - 1900;
1325
void DateTime::to_tm(struct tm *to) const
1327
to->tm_sec= _seconds;
1328
to->tm_min= _minutes;
1329
to->tm_hour= _hours;
1330
to->tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
1331
to->tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
1332
to->tm_year= _years - 1900;
1335
bool Date::from_julian_day_number(const int64_t from)
1337
gregorian_date_from_julian_day_number(from, &_years, &_months, &_days);
1341
void Date::to_julian_day_number(int64_t *to) const
1343
*to= julian_day_number_from_gregorian_date(_years, _months, _days);
1347
* Ignore overflow and pass-through to DateTime::from_int64_t()
1349
bool Date::from_int32_t(const int32_t from)
1351
return ((DateTime *) this)->from_int64_t((int64_t) from);
1355
* Attempt to interpret the supplied 4-byte integer as
1356
* a TIME value in the format HHmmSS
1358
bool Time::from_int32_t(const int32_t from)
1360
uint32_t copy_from= (uint32_t) from;
1361
_hours= copy_from % INT32_C(10000);
1362
_minutes= copy_from % INT32_C(100);
1363
_seconds= copy_from & 3; /* Masks off all but last 2 digits */
1368
* We try to intepret the incoming number as a datetime "string".
1369
* This is pretty much a hack for usability, but keeps us compatible
1372
bool DateTime::from_int64_t(const int64_t from)
1374
int64_t copy_from= from;
1378
if (copy_from == 0LL)
1381
if (copy_from < 10000101000000LL)
1383
if (copy_from < 101)
1385
else if (copy_from <= (DRIZZLE_YY_PART_YEAR-1)*10000L+1231L)
1386
copy_from= (copy_from+20000000L)*1000000L; /* YYMMDD, year: 2000-2069 */
1387
else if (copy_from < (DRIZZLE_YY_PART_YEAR)*10000L+101L)
1389
else if (copy_from <= 991231L)
1390
copy_from= (copy_from+19000000L)*1000000L; /* YYMMDD, year: 1970-1999 */
1391
else if (copy_from < 10000101L)
1393
else if (copy_from <= 99991231L)
1394
copy_from= copy_from*1000000L;
1395
else if (copy_from < 101000000L)
1397
else if (copy_from <= (DRIZZLE_YY_PART_YEAR-1) * 10000000000LL + 1231235959LL)
1398
copy_from= copy_from + 20000000000000LL; /* YYMMDDHHMMSS, 2000-2069 */
1399
else if (copy_from < DRIZZLE_YY_PART_YEAR * 10000000000LL + 101000000LL)
1401
else if (copy_from <= 991231235959LL)
1402
copy_from= copy_from + 19000000000000LL; /* YYMMDDHHMMSS, 1970-1999 */
1405
part1= (int64_t) (copy_from / 1000000LL);
1406
part2= (int64_t) (copy_from - (int64_t) part1 * 1000000LL);
1407
_years= (uint32_t) (part1/10000L);
1410
_months= (uint32_t) part1 / 100;
1411
_days= (uint32_t) part1 % 100;
1412
_hours= (uint32_t) (part2/10000L);
1415
_minutes= (uint32_t) part2 / 100;
1416
_seconds= (uint32_t) part2 % 100;
1418
set_epoch_seconds();
1422
bool Date::in_unix_epoch() const
1424
return in_unix_epoch_range(_years, _months, _days, 0, 0, 0);
1427
bool DateTime::in_unix_epoch() const
1429
return in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds);
1432
bool Date::from_tm(const struct tm *from)
1434
_years= 1900 + from->tm_year;
1435
_months= 1 + from->tm_mon; /* Month is NOT ordinal for struct tm! */
1436
_days= from->tm_mday; /* Day IS ordinal for struct tm */
1437
_hours= from->tm_hour;
1438
_minutes= from->tm_min;
1439
_seconds= from->tm_sec;
1440
/* Set hires precision to zero */
1444
set_epoch_seconds();
1449
* We convert as if it's a Datetime, then simply
1450
* drop the date portions...
1452
bool Time::from_time_t(const time_t from)
1454
struct tm broken_time;
1457
result= gmtime_r(&from, &broken_time);
1463
_hours= broken_time.tm_hour;
1464
_minutes= broken_time.tm_min;
1465
_seconds= broken_time.tm_sec;
1466
_epoch_seconds= 0; /* Don't store the time_t, since we only use part of it */
1467
/* Set hires precision to zero */
1470
return true; /* Always true... */
1476
bool Date::from_time_t(const time_t from)
1478
struct tm broken_time;
1481
result= gmtime_r(&from, &broken_time);
1484
_years= 1900 + broken_time.tm_year;
1485
_months= 1 + broken_time.tm_mon; /* Month is NOT ordinal for struct tm! */
1486
_days= broken_time.tm_mday; /* Day IS ordinal for struct tm */
1490
_epoch_seconds= 0; /* Don't store the time_t, since we only use part of it */
1491
/* Set hires precision to zero */
1500
bool DateTime::from_time_t(const time_t from)
1502
struct tm broken_time;
1505
result= gmtime_r(&from, &broken_time);
1508
_years= 1900 + broken_time.tm_year;
1509
_months= 1 + broken_time.tm_mon; /* Month is NOT ordinal for struct tm! */
1510
_days= broken_time.tm_mday; /* Day IS ordinal for struct tm */
1511
_hours= broken_time.tm_hour;
1512
_minutes= broken_time.tm_min;
1513
_seconds= broken_time.tm_sec;
1514
_epoch_seconds= from;
1515
/* Set hires precision to zero */
1524
void Date::to_time_t(time_t *to) const
1526
if (in_unix_epoch())
1527
*to= _epoch_seconds;
1531
void Timestamp::to_time_t(time_t *to) const
1533
*to= _epoch_seconds;
1536
void MicroTimestamp::to_timeval(struct timeval *to) const
1538
to->tv_sec= _epoch_seconds;
1539
to->tv_usec= _useconds;
1542
void NanoTimestamp::to_timespec(struct timespec *to) const
1544
to->tv_sec= _epoch_seconds;
1545
to->tv_nsec= _nseconds;
1548
bool Date::is_valid() const
1550
return (_years >= DRIZZLE_MIN_YEARS_SQL && _years <= DRIZZLE_MAX_YEARS_SQL)
1551
&& (_months >= 1 && _months <= 12)
1552
&& (_days >= 1 && _days <= days_in_gregorian_year_month(_years, _months));
1555
bool Time::is_valid() const
1557
return (_years == 0)
1562
&& (_seconds <= 59); /* No Leap second... TIME is for elapsed time... */
1565
bool DateTime::is_valid() const
1567
return (_years >= DRIZZLE_MIN_YEARS_SQL && _years <= DRIZZLE_MAX_YEARS_SQL)
1568
&& (_months >= 1 && _months <= 12)
1569
&& (_days >= 1 && _days <= days_in_gregorian_year_month(_years, _months))
1572
&& (_seconds <= 61); /* Leap second... */
1575
bool Timestamp::is_valid() const
1577
return DateTime::is_valid()
1578
&& in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds);
1581
bool MicroTimestamp::is_valid() const
1583
return Timestamp::is_valid()
1584
&& (_useconds <= UINT32_C(999999));
1587
bool NanoTimestamp::is_valid() const
1589
return Timestamp::is_valid()
1590
&& (_useconds <= UINT32_C(999999))
1591
&& (_nseconds <= UINT32_C(999999999));
1594
} /* end namespace drizzled */