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, Inc.
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/type/decimal.h"
41
#include "drizzled/calendar.h"
42
#include "drizzled/temporal.h"
43
#include "drizzled/temporal_format.h"
44
#include "drizzled/time_functions.h"
47
#include <drizzled/util/gmtime.h>
60
extern std::vector<TemporalFormat *> known_datetime_formats;
61
extern std::vector<TemporalFormat *> known_date_formats;
62
extern std::vector<TemporalFormat *> known_time_formats;
64
Temporal::Temporal() :
78
uint64_t Temporal::_cumulative_seconds_in_time() const
80
return (uint64_t) ((_hours * INT64_C(3600))
81
+ (_minutes * INT64_C(60))
85
#if defined(TARGET_OS_SOLARIS)
86
/* @TODO: Replace this with Boost.DateTime */
87
static time_t timegm(struct tm *my_time)
89
time_t local_secs, gm_secs;
90
struct tm gm__rec, *gm_time;
92
// Interpret 't' as the local time and convert it to seconds since the Epoch
93
local_secs = mktime(my_time);
97
local_secs = mktime (my_time);
103
// Get the gmtime based on the local seconds since the Epoch
104
gm_time = util::gmtime(local_secs, &gm__rec);
105
gm_time->tm_isdst = 0;
107
// Interpret gmtime as the local time and convert it to seconds since the Epoch
108
gm_secs = mktime (gm_time);
112
gm_secs = mktime (gm_time);
118
// Return the local time adjusted by the difference from GM time.
119
return (local_secs - (gm_secs - local_secs));
123
void Temporal::set_epoch_seconds()
126
* If the temporal is in the range of a timestamp, set
127
* the epoch_seconds member variable
129
if (in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds))
132
struct tm broken_time;
134
broken_time.tm_sec= _seconds;
135
broken_time.tm_min= _minutes;
136
broken_time.tm_hour= _hours;
137
broken_time.tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
138
broken_time.tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
139
broken_time.tm_year= _years - 1900; /* tm_year expects range of 70 - 38 */
141
result_time= timegm(&broken_time);
143
_epoch_seconds= result_time;
147
bool Date::from_string(const char *from, size_t from_len)
150
* Loop through the known date formats and see if
154
TemporalFormat *current_format;
155
std::vector<TemporalFormat *>::iterator current= known_date_formats.begin();
157
_useconds= 0; // We may not match on it, so we need to make sure we zero it out.
158
while (current != known_date_formats.end())
160
current_format= *current;
161
if (current_format->matches(from, from_len, this))
176
bool DateTime::from_string(const char *from, size_t from_len)
179
* Loop through the known datetime formats and see if
183
TemporalFormat *current_format;
184
std::vector<TemporalFormat *>::iterator current= known_datetime_formats.begin();
186
while (current != known_datetime_formats.end())
188
current_format= *current;
189
if (current_format->matches(from, from_len, this))
205
* Comparison operators for Time against another Time
206
* are easy. We simply compare the cumulative time
209
bool Time::operator==(const Time& rhs)
213
&& _minutes == rhs._minutes
214
&& _seconds == rhs._seconds
215
&& _useconds == rhs._useconds
216
&& _nseconds == rhs._nseconds
219
bool Time::operator!=(const Time& rhs)
221
return ! (*this == rhs);
223
bool Time::operator<(const Time& rhs)
225
return (_cumulative_seconds_in_time() < rhs._cumulative_seconds_in_time());
227
bool Time::operator<=(const Time& rhs)
229
return (_cumulative_seconds_in_time() <= rhs._cumulative_seconds_in_time());
231
bool Time::operator>(const Time& rhs)
233
return (_cumulative_seconds_in_time() > rhs._cumulative_seconds_in_time());
235
bool Time::operator>=(const Time& rhs)
237
return (_cumulative_seconds_in_time() >= rhs._cumulative_seconds_in_time());
241
* Subtracting one Time value from another can yield
242
* a new Time instance.
244
* This operator is called in the following situation:
248
* lhs.from_string("20:00:00");
250
* rhs.from_string("19:00:00");
252
* Time result= lhs - rhs;
257
* Subtracting a larger time value from a smaller one
258
* should throw an exception at some point. The result
259
* of such an operator should be a TemporalInterval, not
260
* a Time instance, since a negative time is not possible.
262
const Time Time::operator-(const Time& rhs)
266
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
267
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
268
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
269
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
270
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
271
result._seconds= (uint32_t) second_diff;
275
const Time Time::operator+(const Time& rhs)
278
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
279
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
280
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
281
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
282
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
283
result._seconds= (uint32_t) second_diff;
285
* @TODO Once exceptions are supported, we should raise an error here if
286
* the result Time is not valid?
292
* Variation of + and - operator which returns a reference to the left-hand
293
* side Time object and adds the right-hand side to itself.
295
Time& Time::operator+=(const Time& rhs)
297
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
298
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
299
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
300
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
301
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
302
_seconds= (uint32_t) second_diff;
304
* @TODO Once exceptions are supported, we should raise an error here if
305
* the result Time is not valid?
309
Time& Time::operator-=(const Time& rhs)
311
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
312
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
313
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
314
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
315
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
316
_seconds= (uint32_t) second_diff;
318
* @TODO Once exceptions are supported, we should raise an error here if
319
* the result Time is not valid?
325
* Comparison operators for Date against another Date
326
* are easy. We simply compare the cumulative
329
bool Date::operator==(const Date& rhs)
333
&& _months == rhs._months
334
&& _days == rhs._days
337
bool Date::operator!=(const Date& rhs)
339
return ! (*this == rhs);
341
bool Date::operator<(const Date& rhs)
343
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
344
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
345
return (days_left < days_right);
347
bool Date::operator<=(const Date& rhs)
349
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
350
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
351
return (days_left <= days_right);
353
bool Date::operator>(const Date& rhs)
355
return ! (*this <= rhs);
357
bool Date::operator>=(const Date& rhs)
359
return ! (*this < rhs);
363
* Comparison operators for DateTime against another DateTime
364
* are easy. We simply compare the cumulative time
367
bool Date::operator==(const DateTime& rhs)
371
&& _months == rhs._months
372
&& _days == rhs._days
373
&& _hours == rhs._hours
374
&& _minutes == rhs._minutes
375
&& _seconds == rhs._seconds
376
&& _useconds == rhs._useconds
377
&& _nseconds == rhs._nseconds
380
bool Date::operator!=(const DateTime& rhs)
382
return ! (*this == rhs);
384
bool Date::operator<(const DateTime& rhs)
386
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
387
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
388
if (days_left < days_right)
390
else if (days_left > days_right)
392
/* Here if both dates are the same, so compare times */
393
return (_cumulative_seconds_in_time() < rhs._cumulative_seconds_in_time());
395
bool Date::operator<=(const DateTime& rhs)
397
int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
398
int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
399
if (days_left < days_right)
401
else if (days_left > days_right)
403
/* Here if both dates are the same, so compare times */
404
return (_cumulative_seconds_in_time() <= rhs._cumulative_seconds_in_time());
406
bool Date::operator>(const DateTime& rhs)
408
return ! (*this <= rhs);
410
bool Date::operator>=(const DateTime& rhs)
412
return ! (*this < rhs);
416
* We can add or subtract a Time value to/from a DateTime value
417
* as well...it always produces a DateTime.
419
const Date Date::operator-(const Time& rhs)
424
* First, we set the resulting DATE pieces equal to our
425
* left-hand side DateTime's DATE components. Then, deal with
426
* the time components.
428
result._years= _years;
429
result._months= _months;
432
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
435
* The resulting diff might be negative. If it is, that means that
436
* we have subtracting a larger time piece from the datetime, like so:
438
* x = DateTime("2007-06-09 09:30:00") - Time("16:30:00");
440
* In these cases, we need to subtract a day from the resulting
446
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
447
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
448
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
449
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
450
result._seconds= (uint32_t) second_diff;
452
/* Handle the microsecond precision */
453
int64_t microsecond_diff= _useconds - rhs._useconds;
454
if (microsecond_diff < 0)
456
microsecond_diff= (-1 * microsecond_diff);
459
result._useconds= (uint32_t) microsecond_diff;
463
const Date Date::operator+(const Time& rhs)
468
* First, we set the resulting DATE pieces equal to our
469
* left-hand side DateTime's DATE components. Then, deal with
470
* the time components.
472
result._years= _years;
473
result._months= _months;
476
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
479
* The resulting seconds might be more than a day. If do,
480
* adjust our resulting days up 1.
482
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
485
second_diff%= DRIZZLE_SECONDS_IN_DAY;
488
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
489
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
490
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
491
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
492
result._seconds= (uint32_t) second_diff;
494
/* Handle the microsecond precision */
495
int64_t microsecond_diff= _useconds - rhs._useconds;
496
if (microsecond_diff < 0)
498
microsecond_diff= (-1 * microsecond_diff);
501
result._useconds= (uint32_t) microsecond_diff;
507
* Variation of + and - operator which returns a reference to the left-hand
508
* side DateTime object and adds the right-hand side Time to itself.
510
Date& Date::operator+=(const Time& rhs)
512
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
514
* The resulting seconds might be more than a day. If do,
515
* adjust our resulting days up 1.
517
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
520
second_diff%= DRIZZLE_SECONDS_IN_DAY;
523
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
524
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
525
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
526
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
527
_seconds= (uint32_t) second_diff;
529
/* Handle the microsecond precision */
530
int64_t microsecond_diff= _useconds - rhs._useconds;
531
if (microsecond_diff < 0)
533
microsecond_diff= (-1 * microsecond_diff);
536
_useconds= (uint32_t) microsecond_diff;
538
* @TODO Once exceptions are supported, we should raise an error here if
539
* the result Time is not valid?
543
Date& Date::operator-=(const Time& rhs)
545
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
548
* The resulting diff might be negative. If it is, that means that
549
* we have subtracting a larger time piece from the datetime, like so:
551
* x = DateTime("2007-06-09 09:30:00");
552
* x-= Time("16:30:00");
554
* In these cases, we need to subtract a day from the resulting
560
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
561
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
562
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
563
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
564
_seconds= (uint32_t) second_diff;
566
/* Handle the microsecond precision */
567
int64_t microsecond_diff= _useconds - rhs._useconds;
568
if (microsecond_diff < 0)
570
microsecond_diff= (-1 * microsecond_diff);
573
_useconds= (uint32_t) microsecond_diff;
575
* @TODO Once exceptions are supported, we should raise an error here if
576
* the result Time is not valid?
582
* We can add/subtract two Dates to/from each other. The result
583
* is always another Date instance.
585
const Date Date::operator-(const Date &rhs)
587
/* Figure out the difference in days between the two dates */
588
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
589
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
590
int64_t day_diff= day_left - day_right;
593
/* Now re-compose the Date's structure from the resulting Julian Day Number */
594
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
597
const Date Date::operator+(const Date &rhs)
600
* Figure out the new Julian Day Number by adding the JDNs of both
603
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
604
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
605
int64_t day_diff= day_left + day_right;
607
/** @TODO Need an exception check here for bounds of JDN... */
610
/* Now re-compose the Date's structure from the resulting Julian Day Number */
611
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
614
/* Similar to the above, but we add/subtract the right side to this object itself */
615
Date& Date::operator-=(const Date &rhs)
617
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
618
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
619
int64_t day_diff= day_left - day_right;
621
/* Now re-compose the Date's structure from the resulting Julian Day Number */
622
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
625
Date& Date::operator+=(const Date &rhs)
628
* Figure out the new Julian Day Number by adding the JDNs of both
631
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
632
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
633
int64_t day_diff= day_left + day_right;
635
/** @TODO Need an exception check here for bounds of JDN... */
637
/* Now re-compose the Date's structure from the resulting Julian Day Number */
638
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
642
Date& Date::operator=(const DateTime &rhs)
644
/* Only copy the Date components of the assigned DateTime... */
646
_months= rhs._months;
648
/* Zero-out everything else.. */
649
_hours= _minutes= _seconds= _useconds= _nseconds= 0;
654
* We can add/subtract two DateTimes to/from each other. The result
655
* is always another DateTime instance.
657
const Date Date::operator-(const DateTime &rhs)
659
/* Figure out the difference in days between the two dates. */
660
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
661
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
662
int64_t day_diff= day_left - day_right;
665
/* Now re-compose the Date's structure from the resulting Julian Day Number */
666
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
668
/* And now handle the time components */
669
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
672
* The resulting diff might be negative. If it is, that means that
673
* we have subtracting a larger time piece from the datetime, like so:
675
* x = DateTime("2007-06-09 09:30:00");
676
* x-= Time("16:30:00");
678
* In these cases, we need to subtract a day from the resulting
684
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
685
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
686
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
687
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
688
result._seconds= (uint32_t) second_diff;
690
/* Handle the microsecond precision */
691
int64_t microsecond_diff= _useconds - rhs._useconds;
692
if (microsecond_diff < 0)
694
microsecond_diff= (-1 * microsecond_diff);
697
result._useconds= (uint32_t) microsecond_diff;
701
const Date Date::operator+(const DateTime &rhs)
704
* Figure out the new Julian Day Number by adding the JDNs of both
707
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
708
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
709
int64_t day_diff= day_left + day_right;
711
/** @TODO Need an exception check here for bounds of JDN... */
714
/* Now re-compose the Date's structure from the resulting Julian Day Number */
715
gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._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 seconds might be more than a day. If do,
722
* adjust our resulting days up 1.
724
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
727
second_diff%= DRIZZLE_SECONDS_IN_DAY;
730
result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
731
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
732
result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
733
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
734
result._seconds= (uint32_t) second_diff;
736
/* Handle the microsecond precision */
737
int64_t microsecond_diff= _useconds - rhs._useconds;
738
if (microsecond_diff < 0)
740
microsecond_diff= (-1 * microsecond_diff);
743
result._useconds= (uint32_t) microsecond_diff;
747
/* Similar to the above, but we add/subtract the right side to this object itself */
748
Date& Date::operator-=(const DateTime &rhs)
750
/* Figure out the difference in days between the two dates. */
751
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
752
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
753
int64_t day_diff= day_left - day_right;
755
/* Now re-compose the Date's structure from the ng Julian Day Number */
756
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
758
/* And now handle the time components */
759
int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
762
* The resulting diff might be negative. If it is, that means that
763
* we have subtracting a larger time piece from the datetime, like so:
765
* x = DateTime("2007-06-09 09:30:00");
766
* x-= Time("16:30:00");
768
* In these cases, we need to subtract a day from the ng
774
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
775
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
776
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
777
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
778
_seconds= (uint32_t) second_diff;
780
/* Handle the microsecond precision */
781
int64_t microsecond_diff= _useconds - rhs._useconds;
782
if (microsecond_diff < 0)
784
microsecond_diff= (-1 * microsecond_diff);
787
_useconds= (uint32_t) microsecond_diff;
791
Date& Date::operator+=(const DateTime &rhs)
794
* Figure out the new Julian Day Number by adding the JDNs of both
797
int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
798
int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
799
int64_t day_diff= day_left + day_right;
801
/** @TODO Need an exception check here for bounds of JDN... */
803
/* Now re-compose the Date's structure from the ng Julian Day Number */
804
gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
806
/* And now handle the time components */
807
int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
810
* The resulting seconds might be more than a day. If do,
811
* adjust our ng days up 1.
813
if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
816
second_diff%= DRIZZLE_SECONDS_IN_DAY;
819
_hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
820
second_diff%= DRIZZLE_SECONDS_IN_HOUR;
821
_minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
822
second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
823
_seconds= (uint32_t) second_diff;
825
/* Handle the microsecond precision */
826
int64_t microsecond_diff= _useconds - rhs._useconds;
827
if (microsecond_diff < 0)
829
microsecond_diff= (-1 * microsecond_diff);
832
_useconds= (uint32_t) microsecond_diff;
838
* Comparison operators between a Date and a Timestamp
840
bool Date::operator==(const Timestamp& rhs)
842
return (_years == rhs._years && _months == rhs._months && _days == rhs._days);
844
bool Date::operator!=(const Timestamp& rhs)
846
return ! (*this == rhs);
848
bool Date::operator<(const Timestamp& rhs)
850
if (_years < rhs._years)
852
if (_years > rhs._years)
855
if (_months < rhs._months)
857
if (_months > rhs._months)
860
return _days < rhs._days;
862
bool Date::operator<=(const Timestamp& rhs)
864
return (*this < rhs || *this == rhs);
866
bool Date::operator>(const Timestamp& rhs)
868
return ! (*this <= rhs);
870
bool Date::operator>=(const Timestamp& rhs)
872
return ! (*this < rhs);
875
* Comparison operators between a Timestamp and a Date
877
bool Timestamp::operator==(const Date& rhs)
879
return (_years == rhs._years && _months == rhs._months && _days == rhs._days);
881
bool Timestamp::operator!=(const Date& rhs)
883
return ! (*this == rhs);
885
bool Timestamp::operator<(const Date& rhs)
887
if (_years < rhs._years)
889
if (_years > rhs._years)
892
if (_months < rhs._months)
894
if (_months > rhs._months)
897
return _days < rhs._days;
899
bool Timestamp::operator<=(const Date& rhs)
901
return (*this < rhs || *this == rhs);
903
bool Timestamp::operator>(const Date& rhs)
905
return ! (*this <= rhs);
907
bool Timestamp::operator>=(const Date& rhs)
909
return ! (*this < rhs);
912
* Comparison operators between a Timestamp and a DateTime
914
bool Timestamp::operator==(const DateTime& rhs)
916
return (_years == rhs._years && _months == rhs._months && _days == rhs._days
917
&& _hours == rhs._hours && _minutes == rhs._minutes && _seconds == rhs._seconds);
919
bool Timestamp::operator!=(const DateTime& rhs)
921
return ! (*this == rhs);
923
bool Timestamp::operator<(const DateTime& rhs)
925
if (_years < rhs._years)
927
if (_years > rhs._years)
930
if (_months < rhs._months)
932
if (_months > rhs._months)
935
if (_days < rhs._days)
937
if (_days > rhs._days)
940
if (_hours < rhs._hours)
942
if (_hours > rhs._hours)
945
if (_minutes < rhs._minutes)
947
if (_minutes > rhs._minutes)
950
return _seconds < rhs._seconds;
952
bool Timestamp::operator<=(const DateTime& rhs)
954
return (*this < rhs || *this == rhs);
956
bool Timestamp::operator>(const DateTime& rhs)
958
return ! (*this <= rhs);
960
bool Timestamp::operator>=(const DateTime& rhs)
962
return ! (*this < rhs);
965
* Comparison operators between two Timestamps
967
bool Timestamp::operator==(const Timestamp& rhs)
969
return (_epoch_seconds == rhs._epoch_seconds);
971
bool Timestamp::operator!=(const Timestamp& rhs)
973
return ! (*this == rhs);
975
bool Timestamp::operator<(const Timestamp& rhs)
977
return (_epoch_seconds < rhs._epoch_seconds);
979
bool Timestamp::operator<=(const Timestamp& rhs)
981
return (_epoch_seconds <= rhs._epoch_seconds);
983
bool Timestamp::operator>(const Timestamp& rhs)
985
return ! (*this <= rhs);
987
bool Timestamp::operator>=(const Timestamp& rhs)
989
return ! (*this < rhs);
993
* Push the contents of the timestamp into the output stream
994
* as a formatted Timestamp value.
996
* @TODO This unfortunately fails in a weird way...even with std::noskipws,
997
* the output stream only reads up to the space in the string... :(
999
std::ostream& operator<<(std::ostream& os, const Timestamp& subject)
1001
return os << subject.years() << '-'
1002
<< std::setw(2) << std::setfill('0') << subject.months() << '-'
1003
<< std::setw(2) << std::setfill('0') << subject.days() << ' '
1004
<< std::setw(2) << std::setfill('0') << subject.hours() << ':'
1005
<< std::setw(2) << std::setfill('0') << subject.minutes() << ':'
1006
<< std::setw(2) << std::setfill('0') << subject.seconds();
1009
bool Time::from_string(const char *from, size_t from_len)
1012
* Loop through the known time formats and see if
1015
bool matched= false;
1016
TemporalFormat *current_format;
1017
std::vector<TemporalFormat *>::iterator current= known_time_formats.begin();
1019
while (current != known_time_formats.end())
1021
current_format= *current;
1022
if (current_format->matches(from, from_len, this))
1033
return is_fuzzy_valid();
1036
int Time::to_string(char *to, size_t to_len) const
1038
return snprintf(to, to_len,
1039
"%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32,
1040
_hours, _minutes, _seconds);
1043
int Date::to_string(char *to, size_t to_len) const
1045
return snprintf(to, to_len,
1046
"%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32,
1047
_years, _months, _days);
1050
int DateTime::to_string(char *to, size_t to_len) const
1052
/* If the temporal has a microsecond component, use a slightly different output */
1055
return snprintf(to, to_len,
1056
"%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
1057
" %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32,
1058
_years, _months, _days,
1059
_hours, _minutes, _seconds);
1063
return snprintf(to, to_len,
1064
"%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
1065
" %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32,
1066
_years, _months, _days,
1067
_hours, _minutes, _seconds, _useconds);
1071
int MicroTimestamp::to_string(char *to, size_t to_len) const
1073
return snprintf(to, to_len,
1074
"%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
1075
" %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32,
1076
_years, _months, _days,
1077
_hours, _minutes, _seconds, _useconds);
1080
void Time::to_decimal(type::Decimal *to) const
1082
int64_t time_portion= (((_hours * 100L) + _minutes) * 100L) + _seconds;
1083
(void) int2_class_decimal(E_DEC_FATAL_ERROR, time_portion, false, to);
1086
to->buf[(to->intg-1) / 9 + 1]= _useconds * 1000;
1091
void Date::to_decimal(type::Decimal *to) const
1093
int64_t date_portion= (((_years * 100L) + _months) * 100L) + _days;
1094
(void) int2_class_decimal(E_DEC_FATAL_ERROR, date_portion, false, to);
1097
void DateTime::to_decimal(type::Decimal *to) const
1099
int64_t date_portion= (((_years * 100L) + _months) * 100L) + _days;
1100
int64_t time_portion= (((((date_portion * 100L) + _hours) * 100L) + _minutes) * 100L) + _seconds;
1101
(void) int2_class_decimal(E_DEC_FATAL_ERROR, time_portion, false, to);
1104
to->buf[(to->intg-1) / 9 + 1]= _useconds * 1000;
1109
void Date::to_int64_t(int64_t *to) const
1111
*to= (_years * INT32_C(10000))
1112
+ (_months * INT32_C(100))
1116
void Date::to_int32_t(int32_t *to) const
1118
*to= (_years * INT32_C(10000))
1119
+ (_months * INT32_C(100))
1123
void Time::to_int32_t(int32_t *to) const
1125
*to= (_hours * INT32_C(10000))
1126
+ (_minutes * INT32_C(100))
1130
// We fill the structure based on just int
1131
void Time::to_uint64_t(uint64_t &to) const
1138
void DateTime::to_int64_t(int64_t *to) const
1141
(_years * INT64_C(10000))
1142
+ (_months * INT64_C(100))
1144
) * INT64_C(1000000))
1146
(_hours * INT64_C(10000))
1147
+ (_minutes * INT64_C(100) )
1152
void Date::to_tm(struct tm *to) const
1157
to->tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
1158
to->tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
1159
to->tm_year= _years - 1900;
1162
void DateTime::to_tm(struct tm *to) const
1164
to->tm_sec= _seconds;
1165
to->tm_min= _minutes;
1166
to->tm_hour= _hours;
1167
to->tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
1168
to->tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
1169
to->tm_year= _years - 1900;
1172
bool Date::from_julian_day_number(const int64_t from)
1174
gregorian_date_from_julian_day_number(from, &_years, &_months, &_days);
1178
void Date::to_julian_day_number(int64_t *to) const
1180
*to= julian_day_number_from_gregorian_date(_years, _months, _days);
1184
* Ignore overflow and pass-through to DateTime::from_int64_t()
1186
bool Date::from_int32_t(const int32_t from)
1188
return ((DateTime *) this)->from_int64_t((int64_t) from);
1192
* Attempt to interpret the supplied 4-byte integer as
1193
* a TIME value in the format HHmmSS
1195
bool Time::from_int32_t(const int32_t from)
1197
uint32_t copy_from= (uint32_t) from;
1198
_hours= copy_from / INT32_C(10000);
1199
_minutes= (copy_from % INT32_C(10000)) / INT32_C(100);
1200
_seconds= copy_from % INT32_C(100); /* Masks off all but last 2 digits */
1205
* We try to intepret the incoming number as a datetime "string".
1206
* This is pretty much a hack for usability, but keeps us compatible
1209
bool DateTime::from_int64_t(const int64_t from, bool convert)
1211
int64_t copy_from= from;
1215
if (copy_from == 0LL)
1218
if (convert && copy_from < 10000101000000LL)
1220
if (copy_from < 101)
1222
else if (copy_from <= (DRIZZLE_YY_PART_YEAR-1)*10000L+1231L)
1223
copy_from= (copy_from+20000000L)*1000000L; /* YYMMDD, year: 2000-2069 */
1224
else if (copy_from < (DRIZZLE_YY_PART_YEAR)*10000L+101L)
1226
else if (copy_from <= 991231L)
1227
copy_from= (copy_from+19000000L)*1000000L; /* YYMMDD, year: 1970-1999 */
1228
else if (copy_from < 10000101L)
1230
else if (copy_from <= 99991231L)
1231
copy_from= copy_from*1000000L;
1232
else if (copy_from < 101000000L)
1234
else if (copy_from <= (DRIZZLE_YY_PART_YEAR-1) * 10000000000LL + 1231235959LL)
1235
copy_from= copy_from + 20000000000000LL; /* YYMMDDHHMMSS, 2000-2069 */
1236
else if (copy_from < DRIZZLE_YY_PART_YEAR * 10000000000LL + 101000000LL)
1238
else if (copy_from <= 991231235959LL)
1239
copy_from= copy_from + 19000000000000LL; /* YYMMDDHHMMSS, 1970-1999 */
1242
part1= (int64_t) (copy_from / 1000000LL);
1243
part2= (int64_t) (copy_from - (int64_t) part1 * 1000000LL);
1244
_years= (uint32_t) (part1/10000L);
1247
_months= (uint32_t) part1 / 100;
1248
_days= (uint32_t) part1 % 100;
1249
_hours= (uint32_t) (part2/10000L);
1252
_minutes= (uint32_t) part2 / 100;
1253
_seconds= (uint32_t) part2 % 100;
1255
set_epoch_seconds();
1259
bool Date::in_unix_epoch() const
1261
return in_unix_epoch_range(_years, _months, _days, 0, 0, 0);
1264
bool DateTime::in_unix_epoch() const
1266
return in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds);
1269
bool Date::from_tm(const struct tm *from)
1271
_years= 1900 + from->tm_year;
1272
_months= 1 + from->tm_mon; /* Month is NOT ordinal for struct tm! */
1273
_days= from->tm_mday; /* Day IS ordinal for struct tm */
1274
_hours= from->tm_hour;
1275
_minutes= from->tm_min;
1276
_seconds= from->tm_sec;
1277
/* Set hires precision to zero */
1281
set_epoch_seconds();
1286
* We convert as if it's a Datetime, then simply
1287
* drop the date portions...
1289
bool Time::from_time_t(const time_t from)
1291
struct tm broken_time;
1294
result= util::gmtime(from, &broken_time);
1300
_hours= broken_time.tm_hour;
1301
_minutes= broken_time.tm_min;
1302
_seconds= broken_time.tm_sec;
1303
_epoch_seconds= 0; /* Don't store the time_t, since we only use part of it */
1304
/* Set hires precision to zero */
1307
return true; /* Always true... */
1313
bool Date::from_time_t(const time_t from)
1315
struct tm broken_time;
1318
result= util::gmtime(from, &broken_time);
1321
_years= 1900 + broken_time.tm_year;
1322
_months= 1 + broken_time.tm_mon; /* Month is NOT ordinal for struct tm! */
1323
_days= broken_time.tm_mday; /* Day IS ordinal for struct tm */
1327
_epoch_seconds= 0; /* Don't store the time_t, since we only use part of it */
1328
/* Set hires precision to zero */
1337
bool DateTime::from_timeval(struct timeval &timeval_arg)
1339
struct tm broken_time;
1342
result= util::gmtime(timeval_arg.tv_sec, &broken_time);
1345
_years= 1900 + broken_time.tm_year;
1346
_months= 1 + broken_time.tm_mon; /* Month is NOT ordinal for struct tm! */
1347
_days= broken_time.tm_mday; /* Day IS ordinal for struct tm */
1348
_hours= broken_time.tm_hour;
1349
_minutes= broken_time.tm_min;
1350
_seconds= broken_time.tm_sec;
1351
_epoch_seconds= timeval_arg.tv_sec;
1352
/* Set hires precision to zero */
1353
_useconds= timeval_arg.tv_usec;
1363
bool DateTime::from_time_t(const time_t from)
1365
struct tm broken_time;
1368
result= util::gmtime(from, &broken_time);
1371
_years= 1900 + broken_time.tm_year;
1372
_months= 1 + broken_time.tm_mon; /* Month is NOT ordinal for struct tm! */
1373
_days= broken_time.tm_mday; /* Day IS ordinal for struct tm */
1374
_hours= broken_time.tm_hour;
1375
_minutes= broken_time.tm_min;
1376
_seconds= broken_time.tm_sec;
1377
_epoch_seconds= from;
1378
/* Set hires precision to zero */
1389
void Date::to_time_t(time_t &to) const
1391
if (in_unix_epoch())
1401
void Timestamp::to_time_t(time_t &to) const
1406
void MicroTimestamp::to_timeval(struct timeval &to) const
1408
to.tv_sec= _epoch_seconds;
1409
to.tv_usec= _useconds;
1412
void NanoTimestamp::to_timespec(struct timespec *to) const
1414
to->tv_sec= _epoch_seconds;
1415
to->tv_nsec= _nseconds;
1418
bool Date::is_valid() const
1420
return (_years >= DRIZZLE_MIN_YEARS_SQL && _years <= DRIZZLE_MAX_YEARS_SQL)
1421
&& (_months >= 1 && _months <= 12)
1422
&& (_days >= 1 && _days <= days_in_gregorian_year_month(_years, _months));
1425
bool Time::is_valid() const
1427
return (_years == 0)
1432
&& (_seconds <= 59); /* No Leap second... TIME is for elapsed time... */
1435
bool Time::is_fuzzy_valid() const
1440
return (_years >= DRIZZLE_MIN_YEARS_SQL && _years <= DRIZZLE_MAX_YEARS_SQL)
1441
&& (_months >= 1 && _months <= 12)
1442
&& (_days >= 1 && _days <= days_in_gregorian_year_month(_years, _months))
1445
&& (_seconds <= 59); /* No Leap second... TIME is for elapsed time... */
1448
bool DateTime::is_valid() const
1450
return (_years >= DRIZZLE_MIN_YEARS_SQL && _years <= DRIZZLE_MAX_YEARS_SQL)
1451
&& (_months >= 1 && _months <= 12)
1452
&& (_days >= 1 && _days <= days_in_gregorian_year_month(_years, _months))
1455
&& (_seconds <= 61); /* Leap second... */
1458
bool Timestamp::is_valid() const
1460
return DateTime::is_valid()
1461
&& in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds)
1462
&& (_seconds <= 59);
1465
bool MicroTimestamp::is_valid() const
1467
return Timestamp::is_valid()
1468
&& (_useconds <= UINT32_C(999999));
1471
bool NanoTimestamp::is_valid() const
1473
return Timestamp::is_valid()
1474
&& (_useconds <= UINT32_C(999999))
1475
&& (_nseconds <= UINT32_C(999999999));
1478
} /* namespace drizzled */