~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/temporal.cc

  • Committer: Jay Pipes
  • Date: 2009-01-28 02:39:29 UTC
  • mto: This revision was merged to the branch mainline in revision 815.
  • Revision ID: jpipes@serialcoder-20090128023929-gy7mot4ki11taytg
First function cleanup for temporal handling: YEAR()

* Added source files for calendrical calculations:
 drizzled/calendar.h
 drizzled/calendar.cc
* Added source files for new Temporal classes
 drizzled/temporal.h
 drizzled/temporal.cc
 drizzled/temporal_format.h
 drizzled/temporal_format.cc

Modified drizzled/function/time/year.cc to use the new
Temporal classes instead of the DRIZZLE_TIME struct and 
get_date().

Added new error codes for invalid DATETIME values and ensured
bad datetimes throw errors in calls to YEAR().

Added new test case specifically for the YEAR() function

Modified existing func_time and type_date test cases to expect
errors when calling YEAR() with bad datetimes.

Edited Makefile.am in drizzled/ to ensure libpcre is used during
build and that calendar.cc, temporal.cc and temporal_format.cc are
built.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 Sun Microsystems
 
5
 *
 
6
 *  Authors:
 
7
 *
 
8
 *  Jay Pipes <jay.pipes@sun.com>
 
9
 *
 
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.
 
14
 *
 
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.
 
19
 *
 
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
 
23
 */
 
24
 
 
25
/**
 
26
 * @file 
 
27
 *
 
28
 * Implementation of the server's temporal class API
 
29
 *
 
30
 * @todo
 
31
 *
 
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.
 
35
 */
 
36
 
 
37
#include <vector>
 
38
#include <string.h>
 
39
 
 
40
#include "drizzled/global.h"
 
41
#include "mystrings/m_ctype.h"
 
42
#include "drizzled/my_decimal.h"
 
43
#include "drizzled/temporal.h"
 
44
#include "drizzled/temporal_format.h"
 
45
 
 
46
extern std::vector<drizzled::TemporalFormat *> known_datetime_formats;
 
47
extern std::vector<drizzled::TemporalFormat *> known_date_formats;
 
48
extern std::vector<drizzled::TemporalFormat *> known_time_formats;
 
49
 
 
50
namespace drizzled 
 
51
{
 
52
 
 
53
Temporal::Temporal()
 
54
:
 
55
  _calendar(GREGORIAN)
 
56
, _years(0)
 
57
, _months(0)
 
58
, _days(0)
 
59
, _hours(0)
 
60
, _minutes(0)
 
61
, _seconds(0)
 
62
, _epoch_seconds(0)
 
63
, _useconds(0)
 
64
, _nseconds(0)
 
65
{}
 
66
 
 
67
uint64_t Temporal::_cumulative_seconds_in_time() const
 
68
{
 
69
  return (uint64_t) ((_hours * INT64_C(3600)) 
 
70
      + (_minutes * INT64_C(60)) 
 
71
      + _seconds);
 
72
}
 
73
 
 
74
void Temporal::set_epoch_seconds()
 
75
{
 
76
  /* 
 
77
   * If the temporal is in the range of a timestamp, set 
 
78
   * the epoch_seconds member variable
 
79
   */
 
80
  if (in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds))
 
81
  {
 
82
    time_t result_time;
 
83
    struct tm broken_time;
 
84
 
 
85
    broken_time.tm_sec= _seconds;
 
86
    broken_time.tm_min= _minutes;
 
87
    broken_time.tm_hour= _hours;
 
88
    broken_time.tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
 
89
    broken_time.tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
 
90
    broken_time.tm_year= _years - 1900; /* tm_year expects range of 70 - 38 */
 
91
 
 
92
    result_time= timegm(&broken_time);
 
93
 
 
94
    _epoch_seconds= result_time;
 
95
  }
 
96
}
 
97
 
 
98
bool Date::from_string(const char *from, size_t from_len)
 
99
{
 
100
  /* 
 
101
   * Loop through the known date formats and see if 
 
102
   * there is a match.
 
103
   */
 
104
  bool matched= false;
 
105
  TemporalFormat *current_format;
 
106
  std::vector<TemporalFormat *>::iterator current= known_date_formats.begin();
 
107
 
 
108
  while (current != known_date_formats.end())
 
109
  {
 
110
    current_format= *current;
 
111
    if (current_format->matches(from, from_len, this))
 
112
    {
 
113
      matched= true;
 
114
      break;
 
115
    }
 
116
    current++;
 
117
  }
 
118
 
 
119
  if (! matched)
 
120
    return false;
 
121
 
 
122
  set_epoch_seconds();
 
123
  return is_valid();
 
124
}
 
125
 
 
126
bool DateTime::from_string(const char *from, size_t from_len)
 
127
{
 
128
  /* 
 
129
   * Loop through the known datetime formats and see if 
 
130
   * there is a match.
 
131
   */
 
132
  bool matched= false;
 
133
  TemporalFormat *current_format;
 
134
  std::vector<TemporalFormat *>::iterator current= known_datetime_formats.begin();
 
135
 
 
136
  while (current != known_datetime_formats.end())
 
137
  {
 
138
    current_format= *current;
 
139
    if (current_format->matches(from, from_len, this))
 
140
    {
 
141
      matched= true;
 
142
      break;
 
143
    }
 
144
    current++;
 
145
  }
 
146
 
 
147
  if (! matched)
 
148
    return false;
 
149
 
 
150
  set_epoch_seconds();
 
151
  return is_valid();
 
152
}
 
153
 
 
154
/*
 
155
 * Comparison operators for Time against another Time
 
156
 * are easy.  We simply compare the cumulative time
 
157
 * value of each.
 
158
 */
 
159
bool Time::operator==(const Time& rhs)
 
160
{
 
161
  return (
 
162
          _hours == rhs._hours
 
163
       && _minutes == rhs._minutes
 
164
       && _seconds == rhs._seconds
 
165
       && _useconds == rhs._useconds
 
166
       && _nseconds == rhs._nseconds
 
167
      );
 
168
}
 
169
bool Time::operator!=(const Time& rhs)
 
170
{
 
171
  return ! (*this == rhs);
 
172
}
 
173
bool Time::operator<(const Time& rhs)
 
174
{
 
175
  return (_cumulative_seconds_in_time() < rhs._cumulative_seconds_in_time());
 
176
}
 
177
bool Time::operator<=(const Time& rhs)
 
178
{
 
179
  return (_cumulative_seconds_in_time() <= rhs._cumulative_seconds_in_time());
 
180
}
 
181
bool Time::operator>(const Time& rhs)
 
182
{
 
183
  return (_cumulative_seconds_in_time() > rhs._cumulative_seconds_in_time());
 
184
}
 
185
bool Time::operator>=(const Time& rhs)
 
186
{
 
187
  return (_cumulative_seconds_in_time() >= rhs._cumulative_seconds_in_time());
 
188
}
 
189
 
 
190
/** 
 
191
 * Subtracting one Time value from another can yield
 
192
 * a new Time instance.
 
193
 *
 
194
 * This operator is called in the following situation:
 
195
 *
 
196
 * @code
 
197
 * drizzled::Time lhs;
 
198
 * lhs.from_string("20:00:00");
 
199
 * drizzled::Time rhs;
 
200
 * rhs.from_string("19:00:00");
 
201
 *
 
202
 * drizzled::Time result= lhs - rhs;
 
203
 * @endcode
 
204
 *
 
205
 * @note
 
206
 *
 
207
 * Subtracting a larger time value from a smaller one
 
208
 * should throw an exception at some point.  The result
 
209
 * of such an operator should be a TemporalInterval, not
 
210
 * a Time instance, since a negative time is not possible.
 
211
 */
 
212
const Time Time::operator-(const Time& rhs)
 
213
{
 
214
  Time result;
 
215
 
 
216
  int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
 
217
  result._hours= second_diff % DRIZZLE_SECONDS_IN_HOUR;
 
218
  second_diff-= (result._hours * DRIZZLE_SECONDS_IN_HOUR);
 
219
  result._minutes= second_diff % DRIZZLE_SECONDS_IN_MINUTE;
 
220
  second_diff-= (result._minutes * DRIZZLE_SECONDS_IN_MINUTE);
 
221
  result._seconds= second_diff;
 
222
  
 
223
  return result;
 
224
}
 
225
const Time Time::operator+(const Time& rhs)
 
226
{
 
227
  Time result;
 
228
  int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
 
229
  result._hours= second_diff % DRIZZLE_SECONDS_IN_HOUR;
 
230
  second_diff-= (result._hours * DRIZZLE_SECONDS_IN_HOUR);
 
231
  result._minutes= second_diff % DRIZZLE_SECONDS_IN_MINUTE;
 
232
  second_diff-= (result._minutes * DRIZZLE_SECONDS_IN_MINUTE);
 
233
  result._seconds= second_diff;
 
234
  /** 
 
235
   * @TODO Once exceptions are supported, we should raise an error here if
 
236
   *       the result Time is not valid?
 
237
   */
 
238
  return result;
 
239
}
 
240
 
 
241
/*
 
242
 * Variation of + and - operator which returns a reference to the left-hand
 
243
 * side Time object and adds the right-hand side to itself.
 
244
 */
 
245
Time& Time::operator+=(const Time& rhs)
 
246
{
 
247
  int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
 
248
  _hours= second_diff % DRIZZLE_SECONDS_IN_HOUR;
 
249
  second_diff-= (_hours * DRIZZLE_SECONDS_IN_HOUR);
 
250
  _minutes= second_diff % DRIZZLE_SECONDS_IN_MINUTE;
 
251
  second_diff-= (_minutes * DRIZZLE_SECONDS_IN_MINUTE);
 
252
  _seconds= second_diff;
 
253
  /** 
 
254
   * @TODO Once exceptions are supported, we should raise an error here if
 
255
   *       the result Time is not valid?
 
256
   */
 
257
  return *this;
 
258
}
 
259
Time& Time::operator-=(const Time& rhs)
 
260
{
 
261
  int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
 
262
  _hours= second_diff % DRIZZLE_SECONDS_IN_HOUR;
 
263
  second_diff-= (_hours * DRIZZLE_SECONDS_IN_HOUR);
 
264
  _minutes= second_diff % DRIZZLE_SECONDS_IN_MINUTE;
 
265
  second_diff-= (_minutes * DRIZZLE_SECONDS_IN_MINUTE);
 
266
  _seconds= second_diff;
 
267
  /** 
 
268
   * @TODO Once exceptions are supported, we should raise an error here if
 
269
   *       the result Time is not valid?
 
270
   */
 
271
  return *this;
 
272
}
 
273
 
 
274
/*
 
275
 * Comparison operators for Date against another Date
 
276
 * are easy.  We simply compare the cumulative
 
277
 * value of each.
 
278
 */
 
279
bool Date::operator==(const Date& rhs)
 
280
{
 
281
  return (
 
282
          _years == rhs._years
 
283
       && _months == rhs._months
 
284
       && _days == rhs._days
 
285
      );
 
286
}
 
287
bool Date::operator!=(const Date& rhs)
 
288
{
 
289
  return ! (*this == rhs);
 
290
}
 
291
bool Date::operator<(const Date& rhs)
 
292
{
 
293
  int days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
 
294
  int days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
 
295
  return (days_left < days_right);
 
296
}
 
297
bool Date::operator<=(const Date& rhs)
 
298
{
 
299
  int days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
 
300
  int days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
 
301
  return (days_left <= days_right);
 
302
}
 
303
bool Date::operator>(const Date& rhs)
 
304
{
 
305
  return ! (*this <= rhs);
 
306
}
 
307
bool Date::operator>=(const Date& rhs)
 
308
{
 
309
  return ! (*this < rhs);
 
310
}
 
311
 
 
312
/*
 
313
 * Comparison operators for DateTime against another DateTime
 
314
 * are easy.  We simply compare the cumulative time
 
315
 * value of each.
 
316
 */
 
317
bool DateTime::operator==(const DateTime& rhs)
 
318
{
 
319
  return (
 
320
          _years == rhs._years
 
321
       && _months == rhs._months
 
322
       && _days == rhs._days
 
323
       && _hours == rhs._hours
 
324
       && _minutes == rhs._minutes
 
325
       && _seconds == rhs._seconds
 
326
       && _useconds == rhs._useconds
 
327
       && _nseconds == rhs._nseconds
 
328
      );
 
329
}
 
330
bool DateTime::operator!=(const DateTime& rhs)
 
331
{
 
332
  return ! (*this == rhs);
 
333
}
 
334
bool DateTime::operator<(const DateTime& rhs)
 
335
{
 
336
  int days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
 
337
  int days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
 
338
  if (days_left < days_right)
 
339
    return true;
 
340
  else if (days_left > days_right)
 
341
    return false;
 
342
  /* Here if both dates are the same, so compare times */
 
343
  return (_cumulative_seconds_in_time() < rhs._cumulative_seconds_in_time());
 
344
}
 
345
bool DateTime::operator<=(const DateTime& rhs)
 
346
{
 
347
  int days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
 
348
  int days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
 
349
  if (days_left < days_right)
 
350
    return true;
 
351
  else if (days_left > days_right)
 
352
    return false;
 
353
  /* Here if both dates are the same, so compare times */
 
354
  return (_cumulative_seconds_in_time() <= rhs._cumulative_seconds_in_time());
 
355
}
 
356
bool DateTime::operator>(const DateTime& rhs)
 
357
{
 
358
  return ! (*this <= rhs);
 
359
}
 
360
bool DateTime::operator>=(const DateTime& rhs)
 
361
{
 
362
  return ! (*this < rhs);
 
363
}
 
364
 
 
365
/** 
 
366
 * We can add or subtract a Time value to/from a DateTime value 
 
367
 * as well...it always produces a DateTime.
 
368
 */
 
369
const DateTime DateTime::operator-(const Time& rhs)
 
370
{
 
371
  DateTime result;
 
372
 
 
373
  /* 
 
374
   * First, we set the resulting DATE pieces equal to our 
 
375
   * left-hand side DateTime's DATE components. Then, deal with 
 
376
   * the time components.
 
377
   */
 
378
  result._years= _years;
 
379
  result._months= _months;
 
380
  result._days= _days;
 
381
 
 
382
  int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
 
383
 
 
384
  /* 
 
385
   * The resulting diff might be negative.  If it is, that means that 
 
386
   * we have subtracting a larger time piece from the datetime, like so:
 
387
   *
 
388
   * x = DateTime("2007-06-09 09:30:00") - Time("16:30:00");
 
389
   *
 
390
   * In these cases, we need to subtract a day from the resulting
 
391
   * DateTime.
 
392
   */
 
393
  if (second_diff < 0)
 
394
    result._days--;
 
395
 
 
396
  result._hours= second_diff % DRIZZLE_SECONDS_IN_HOUR;
 
397
  second_diff-= (result._hours * DRIZZLE_SECONDS_IN_HOUR);
 
398
  result._minutes= second_diff % DRIZZLE_SECONDS_IN_MINUTE;
 
399
  second_diff-= (result._minutes * DRIZZLE_SECONDS_IN_MINUTE);
 
400
  result._seconds= second_diff;
 
401
 
 
402
  /* Handle the microsecond precision */
 
403
  int64_t microsecond_diff= _useconds - rhs._useconds;
 
404
  if (microsecond_diff < 0)
 
405
  {
 
406
    microsecond_diff= (-1 * microsecond_diff);
 
407
    result._seconds--;
 
408
  }
 
409
  result._useconds= microsecond_diff;
 
410
 
 
411
  return result;
 
412
}
 
413
const DateTime DateTime::operator+(const Time& rhs)
 
414
{
 
415
  DateTime result;
 
416
 
 
417
  /* 
 
418
   * First, we set the resulting DATE pieces equal to our 
 
419
   * left-hand side DateTime's DATE components. Then, deal with 
 
420
   * the time components.
 
421
   */
 
422
  result._years= _years;
 
423
  result._months= _months;
 
424
  result._days= _days;
 
425
 
 
426
  int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
 
427
 
 
428
  /* 
 
429
   * The resulting seconds might be more than a day.  If do, 
 
430
   * adjust our resulting days up 1.
 
431
   */
 
432
  if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
 
433
  {
 
434
    result._days++;
 
435
    second_diff-= (result._days * DRIZZLE_SECONDS_IN_DAY);
 
436
  }
 
437
 
 
438
  result._hours= second_diff % DRIZZLE_SECONDS_IN_HOUR;
 
439
  second_diff-= (result._hours * DRIZZLE_SECONDS_IN_HOUR);
 
440
  result._minutes= second_diff % DRIZZLE_SECONDS_IN_MINUTE;
 
441
  second_diff-= (result._minutes * DRIZZLE_SECONDS_IN_MINUTE);
 
442
  result._seconds= second_diff;
 
443
 
 
444
  /* Handle the microsecond precision */
 
445
  int64_t microsecond_diff= _useconds - rhs._useconds;
 
446
  if (microsecond_diff < 0)
 
447
  {
 
448
    microsecond_diff= (-1 * microsecond_diff);
 
449
    result._seconds--;
 
450
  }
 
451
  result._useconds= microsecond_diff;
 
452
 
 
453
  return result;
 
454
}
 
455
 
 
456
/*
 
457
 * Variation of + and - operator which returns a reference to the left-hand
 
458
 * side DateTime object and adds the right-hand side Time to itself.
 
459
 */
 
460
DateTime& DateTime::operator+=(const Time& rhs)
 
461
{
 
462
  int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
 
463
  /* 
 
464
   * The resulting seconds might be more than a day.  If do, 
 
465
   * adjust our resulting days up 1.
 
466
   */
 
467
  if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
 
468
  {
 
469
    _days++;
 
470
    second_diff-= (_days * DRIZZLE_SECONDS_IN_DAY);
 
471
  }
 
472
 
 
473
  _hours= second_diff % DRIZZLE_SECONDS_IN_HOUR;
 
474
  second_diff-= (_hours * DRIZZLE_SECONDS_IN_HOUR);
 
475
  _minutes= second_diff % DRIZZLE_SECONDS_IN_MINUTE;
 
476
  second_diff-= (_minutes * DRIZZLE_SECONDS_IN_MINUTE);
 
477
  _seconds= second_diff;
 
478
 
 
479
  /* Handle the microsecond precision */
 
480
  int64_t microsecond_diff= _useconds - rhs._useconds;
 
481
  if (microsecond_diff < 0)
 
482
  {
 
483
    microsecond_diff= (-1 * microsecond_diff);
 
484
    _seconds--;
 
485
  }
 
486
  _useconds= microsecond_diff;
 
487
  /** 
 
488
   * @TODO Once exceptions are supported, we should raise an error here if
 
489
   *       the result Time is not valid?
 
490
   */
 
491
  return *this;
 
492
}
 
493
DateTime& DateTime::operator-=(const Time& rhs)
 
494
{
 
495
  int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
 
496
 
 
497
  /* 
 
498
   * The resulting diff might be negative.  If it is, that means that 
 
499
   * we have subtracting a larger time piece from the datetime, like so:
 
500
   *
 
501
   * x = DateTime("2007-06-09 09:30:00");
 
502
   * x-= Time("16:30:00");
 
503
   *
 
504
   * In these cases, we need to subtract a day from the resulting
 
505
   * DateTime.
 
506
   */
 
507
  if (second_diff < 0)
 
508
    _days--;
 
509
 
 
510
  _hours= second_diff % DRIZZLE_SECONDS_IN_HOUR;
 
511
  second_diff-= (_hours * DRIZZLE_SECONDS_IN_HOUR);
 
512
  _minutes= second_diff % DRIZZLE_SECONDS_IN_MINUTE;
 
513
  second_diff-= (_minutes * DRIZZLE_SECONDS_IN_MINUTE);
 
514
  _seconds= second_diff;
 
515
 
 
516
  /* Handle the microsecond precision */
 
517
  int64_t microsecond_diff= _useconds - rhs._useconds;
 
518
  if (microsecond_diff < 0)
 
519
  {
 
520
    microsecond_diff= (-1 * microsecond_diff);
 
521
    _seconds--;
 
522
  }
 
523
  _useconds= microsecond_diff;
 
524
  /** 
 
525
   * @TODO Once exceptions are supported, we should raise an error here if
 
526
   *       the result Time is not valid?
 
527
   */
 
528
  return *this;
 
529
}
 
530
 
 
531
/**
 
532
 * We can add/subtract two Dates to/from each other.  The result
 
533
 * is always another Date instance.
 
534
 */
 
535
const Date Date::operator-(const Date &rhs)
 
536
{
 
537
  /* Figure out the difference in days between the two dates */
 
538
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
 
539
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
 
540
  int64_t day_diff= day_left - day_right;
 
541
 
 
542
  Date result;
 
543
  /* Now re-compose the Date's structure from the resulting Julian Day Number */
 
544
  gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
 
545
  return result;
 
546
}
 
547
const Date Date::operator+(const Date &rhs)
 
548
{
 
549
  /* 
 
550
   * Figure out the new Julian Day Number by adding the JDNs of both
 
551
   * dates together.
 
552
   */
 
553
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
 
554
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
 
555
  int64_t day_diff= day_left + day_right;
 
556
 
 
557
  /** @TODO Need an exception check here for bounds of JDN... */
 
558
 
 
559
  Date result;
 
560
  /* Now re-compose the Date's structure from the resulting Julian Day Number */
 
561
  gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
 
562
  return result;
 
563
}
 
564
/* Similar to the above, but we add/subtract the right side to this object itself */
 
565
Date& Date::operator-=(const Date &rhs)
 
566
{
 
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;
 
570
 
 
571
  /* Now re-compose the Date's structure from the resulting Julian Day Number */
 
572
  gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
 
573
  return *this;
 
574
}
 
575
Date& Date::operator+=(const Date &rhs)
 
576
{
 
577
  /* 
 
578
   * Figure out the new Julian Day Number by adding the JDNs of both
 
579
   * dates together.
 
580
   */
 
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;
 
584
 
 
585
  /** @TODO Need an exception check here for bounds of JDN... */
 
586
 
 
587
  /* Now re-compose the Date's structure from the resulting Julian Day Number */
 
588
  gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
 
589
  return *this;
 
590
}
 
591
 
 
592
/**
 
593
 * We can add/subtract two DateTimes to/from each other.  The result
 
594
 * is always another DateTime instance.
 
595
 */
 
596
const DateTime DateTime::operator-(const DateTime &rhs)
 
597
{
 
598
  /* Figure out the difference in days between the two dates. */
 
599
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
 
600
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
 
601
  int64_t day_diff= day_left - day_right;
 
602
 
 
603
  DateTime result;
 
604
  /* Now re-compose the Date's structure from the resulting Julian Day Number */
 
605
  gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
 
606
 
 
607
  /* And now handle the time components */
 
608
  int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
 
609
 
 
610
  /* 
 
611
   * The resulting diff might be negative.  If it is, that means that 
 
612
   * we have subtracting a larger time piece from the datetime, like so:
 
613
   *
 
614
   * x = DateTime("2007-06-09 09:30:00");
 
615
   * x-= Time("16:30:00");
 
616
   *
 
617
   * In these cases, we need to subtract a day from the resulting
 
618
   * DateTime.
 
619
   */
 
620
  if (second_diff < 0)
 
621
    _days--;
 
622
 
 
623
  result._hours= second_diff % DRIZZLE_SECONDS_IN_HOUR;
 
624
  second_diff-= (result._hours * DRIZZLE_SECONDS_IN_HOUR);
 
625
  result._minutes= second_diff % DRIZZLE_SECONDS_IN_MINUTE;
 
626
  second_diff-= (result._minutes * DRIZZLE_SECONDS_IN_MINUTE);
 
627
  result._seconds= second_diff;
 
628
 
 
629
  /* Handle the microsecond precision */
 
630
  int64_t microsecond_diff= _useconds - rhs._useconds;
 
631
  if (microsecond_diff < 0)
 
632
  {
 
633
    microsecond_diff= (-1 * microsecond_diff);
 
634
    result._seconds--;
 
635
  }
 
636
  result._useconds= microsecond_diff;
 
637
 
 
638
  return result;
 
639
}
 
640
const DateTime DateTime::operator+(const DateTime &rhs)
 
641
{
 
642
  /* 
 
643
   * Figure out the new Julian Day Number by adding the JDNs of both
 
644
   * dates together.
 
645
   */
 
646
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
 
647
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
 
648
  int64_t day_diff= day_left + day_right;
 
649
 
 
650
  /** @TODO Need an exception check here for bounds of JDN... */
 
651
 
 
652
  DateTime result;
 
653
  /* Now re-compose the Date's structure from the resulting Julian Day Number */
 
654
  gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
 
655
 
 
656
  /* And now handle the time components */
 
657
  int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
 
658
 
 
659
  /* 
 
660
   * The resulting seconds might be more than a day.  If do, 
 
661
   * adjust our resulting days up 1.
 
662
   */
 
663
  if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
 
664
  {
 
665
    result._days++;
 
666
    second_diff-= (result._days * DRIZZLE_SECONDS_IN_DAY);
 
667
  }
 
668
 
 
669
  result._hours= second_diff % DRIZZLE_SECONDS_IN_HOUR;
 
670
  second_diff-= (result._hours * DRIZZLE_SECONDS_IN_HOUR);
 
671
  result._minutes= second_diff % DRIZZLE_SECONDS_IN_MINUTE;
 
672
  second_diff-= (result._minutes * DRIZZLE_SECONDS_IN_MINUTE);
 
673
  result._seconds= second_diff;
 
674
 
 
675
  /* Handle the microsecond precision */
 
676
  int64_t microsecond_diff= _useconds - rhs._useconds;
 
677
  if (microsecond_diff < 0)
 
678
  {
 
679
    microsecond_diff= (-1 * microsecond_diff);
 
680
    result._seconds--;
 
681
  }
 
682
  result._useconds= microsecond_diff;
 
683
 
 
684
  return result;
 
685
}
 
686
/* Similar to the above, but we add/subtract the right side to this object itself */
 
687
DateTime& DateTime::operator-=(const DateTime &rhs)
 
688
{
 
689
  /* Figure out the difference in days between the two dates.  */
 
690
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
 
691
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
 
692
  int64_t day_diff= day_left - day_right;
 
693
 
 
694
  /* Now re-compose the Date's structure from the ng Julian Day Number */
 
695
  gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
 
696
 
 
697
  /* And now handle the time components */
 
698
  int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
 
699
 
 
700
  /* 
 
701
   * The resulting diff might be negative.  If it is, that means that 
 
702
   * we have subtracting a larger time piece from the datetime, like so:
 
703
   *
 
704
   * x = DateTime("2007-06-09 09:30:00");
 
705
   * x-= Time("16:30:00");
 
706
   *
 
707
   * In these cases, we need to subtract a day from the ng
 
708
   * DateTime.
 
709
   */
 
710
  if (second_diff < 0)
 
711
    _days--;
 
712
 
 
713
  _hours= second_diff % DRIZZLE_SECONDS_IN_HOUR;
 
714
  second_diff-= (_hours * DRIZZLE_SECONDS_IN_HOUR);
 
715
  _minutes= second_diff % DRIZZLE_SECONDS_IN_MINUTE;
 
716
  second_diff-= (_minutes * DRIZZLE_SECONDS_IN_MINUTE);
 
717
  _seconds= second_diff;
 
718
 
 
719
  /* Handle the microsecond precision */
 
720
  int64_t microsecond_diff= _useconds - rhs._useconds;
 
721
  if (microsecond_diff < 0)
 
722
  {
 
723
    microsecond_diff= (-1 * microsecond_diff);
 
724
    _seconds--;
 
725
  }
 
726
  _useconds= microsecond_diff;
 
727
 
 
728
  return *this;
 
729
}
 
730
DateTime& DateTime::operator+=(const DateTime &rhs)
 
731
{
 
732
  /* 
 
733
   * Figure out the new Julian Day Number by adding the JDNs of both
 
734
   * dates together.
 
735
   */
 
736
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
 
737
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
 
738
  int64_t day_diff= day_left + day_right;
 
739
 
 
740
  /** @TODO Need an exception check here for bounds of JDN... */
 
741
 
 
742
  /* Now re-compose the Date's structure from the ng Julian Day Number */
 
743
  gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
 
744
 
 
745
  /* And now handle the time components */
 
746
  int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
 
747
 
 
748
  /* 
 
749
   * The resulting seconds might be more than a day.  If do, 
 
750
   * adjust our ng days up 1.
 
751
   */
 
752
  if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
 
753
  {
 
754
    _days++;
 
755
    second_diff-= (_days * DRIZZLE_SECONDS_IN_DAY);
 
756
  }
 
757
 
 
758
  _hours= second_diff % DRIZZLE_SECONDS_IN_HOUR;
 
759
  second_diff-= (_hours * DRIZZLE_SECONDS_IN_HOUR);
 
760
  _minutes= second_diff % DRIZZLE_SECONDS_IN_MINUTE;
 
761
  second_diff-= (_minutes * DRIZZLE_SECONDS_IN_MINUTE);
 
762
  _seconds= second_diff;
 
763
 
 
764
  /* Handle the microsecond precision */
 
765
  int64_t microsecond_diff= _useconds - rhs._useconds;
 
766
  if (microsecond_diff < 0)
 
767
  {
 
768
    microsecond_diff= (-1 * microsecond_diff);
 
769
    _seconds--;
 
770
  }
 
771
  _useconds= microsecond_diff;
 
772
 
 
773
  return *this;
 
774
}
 
775
 
 
776
/*
 
777
 * Comparison operators between two Timestamps
 
778
 */
 
779
bool Timestamp::operator==(const Timestamp& rhs)
 
780
{
 
781
  return (_epoch_seconds == rhs._epoch_seconds);
 
782
}
 
783
bool Timestamp::operator!=(const Timestamp& rhs)
 
784
{
 
785
  return ! (*this == rhs);
 
786
}
 
787
bool Timestamp::operator<(const Timestamp& rhs)
 
788
{
 
789
  return (_epoch_seconds < rhs._epoch_seconds);
 
790
}
 
791
bool Timestamp::operator<=(const Timestamp& rhs)
 
792
{
 
793
  return (_epoch_seconds <= rhs._epoch_seconds);
 
794
}
 
795
bool Timestamp::operator>(const Timestamp& rhs)
 
796
{
 
797
  return ! (*this < rhs);
 
798
}
 
799
bool Timestamp::operator>=(const Timestamp& rhs)
 
800
{
 
801
  return ! (*this <= rhs);
 
802
}
 
803
 
 
804
 
 
805
bool Time::from_string(const char *from, size_t from_len)
 
806
{
 
807
  /* 
 
808
   * Loop through the known time formats and see if 
 
809
   * there is a match.
 
810
   */
 
811
  bool matched= false;
 
812
  TemporalFormat *current_format;
 
813
  std::vector<TemporalFormat *>::iterator current= known_time_formats.begin();
 
814
 
 
815
  while (current != known_time_formats.end())
 
816
  {
 
817
    current_format= *current;
 
818
    if (current_format->matches(from, from_len, this))
 
819
    {
 
820
      matched= true;
 
821
      break;
 
822
    }
 
823
    current++;
 
824
  }
 
825
 
 
826
  if (! matched)
 
827
    return false;
 
828
  else
 
829
    return is_valid();
 
830
}
 
831
 
 
832
void Time::to_string(char *to, size_t *to_len) const
 
833
{
 
834
  *to_len= sprintf(to
 
835
                 , "%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32
 
836
                 , _hours
 
837
                 , _minutes
 
838
                 , _seconds);
 
839
}
 
840
 
 
841
void Date::to_string(char *to, size_t *to_len) const
 
842
{
 
843
  *to_len= sprintf(to
 
844
                 , "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
 
845
                 , _years
 
846
                 , _months
 
847
                 , _days);
 
848
}
 
849
 
 
850
void DateTime::to_string(char *to, size_t *to_len) const
 
851
{
 
852
  *to_len= sprintf(to
 
853
                 , "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32 " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32
 
854
                 , _years
 
855
                 , _months
 
856
                 , _days
 
857
                 , _hours
 
858
                 , _minutes
 
859
                 , _seconds);
 
860
}
 
861
 
 
862
void MicroTimestamp::to_string(char *to, size_t *to_len) const
 
863
{
 
864
  *to_len= sprintf(to
 
865
                 , "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32 " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32
 
866
                 , _years
 
867
                 , _months
 
868
                 , _days
 
869
                 , _hours
 
870
                 , _minutes
 
871
                 , _seconds
 
872
                 , _useconds);
 
873
}
 
874
 
 
875
void Time::to_decimal(my_decimal *to) const
 
876
{
 
877
  int64_t time_portion= (((_hours * 100L) + _minutes) * 100L) + _seconds;
 
878
  (void) int2my_decimal(E_DEC_FATAL_ERROR, time_portion, false, to);
 
879
  if (_useconds > 0)
 
880
  {
 
881
    to->buf[(to->intg-1) / 9 + 1]= _useconds * 1000;
 
882
    to->frac= 6;
 
883
  }
 
884
}
 
885
 
 
886
void Date::to_decimal(my_decimal *to) const
 
887
{
 
888
  int64_t date_portion= (((_years * 100L) + _months) * 100L) + _days;
 
889
  (void) int2my_decimal(E_DEC_FATAL_ERROR, date_portion, false, to);
 
890
}
 
891
 
 
892
void DateTime::to_decimal(my_decimal *to) const
 
893
{
 
894
  int64_t date_portion= (((_years * 100L) + _months) * 100L) + _days;
 
895
  int64_t time_portion= (((((date_portion * 100L) + _hours) * 100L) + _minutes) * 100L) + _seconds;
 
896
  (void) int2my_decimal(E_DEC_FATAL_ERROR, time_portion, false, to);
 
897
  if (_useconds > 0)
 
898
  {
 
899
    to->buf[(to->intg-1) / 9 + 1]= _useconds * 1000;
 
900
    to->frac= 6;
 
901
  }
 
902
}
 
903
 
 
904
void Date::to_int64_t(int64_t *to) const
 
905
{
 
906
  *to= (_years * INT32_C(10000)) 
 
907
     + (_months * INT32_C(100)) 
 
908
     + _days;
 
909
}
 
910
 
 
911
void Date::to_int32_t(int32_t *to) const
 
912
{
 
913
  *to= (_years * INT32_C(10000)) 
 
914
     + (_months * INT32_C(100)) 
 
915
     + _days;
 
916
}
 
917
 
 
918
void Time::to_int32_t(int32_t *to) const
 
919
{
 
920
  *to= (_hours * INT32_C(10000)) 
 
921
     + (_minutes * INT32_C(100)) 
 
922
     + _seconds;
 
923
}
 
924
 
 
925
void DateTime::to_int64_t(int64_t *to) const
 
926
{
 
927
  *to= ((
 
928
       (_years * INT64_C(10000)) 
 
929
     + (_months * INT64_C(100)) 
 
930
     + _days
 
931
       ) * INT64_C(1000000))
 
932
     + (
 
933
       (_hours * INT64_C(10000)) 
 
934
     + (_minutes * INT64_C(100) )
 
935
     + _seconds
 
936
     );
 
937
}
 
938
 
 
939
void Date::to_tm(struct tm *to) const
 
940
{
 
941
  to->tm_sec= 0;
 
942
  to->tm_min= 0;
 
943
  to->tm_hour= 0;
 
944
  to->tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
 
945
  to->tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
 
946
  to->tm_year= _years - 1900;
 
947
}
 
948
 
 
949
void DateTime::to_tm(struct tm *to) const
 
950
{
 
951
  to->tm_sec= _seconds;
 
952
  to->tm_min= _minutes;
 
953
  to->tm_hour= _hours;
 
954
  to->tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
 
955
  to->tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
 
956
  to->tm_year= _years - 1900;
 
957
}
 
958
 
 
959
/**
 
960
 * We assume that the supplied integer is an
 
961
 * absolute day number (for instance, from the FROM_DAYS()
 
962
 * SQL function.
 
963
 */
 
964
bool Date::from_julian_day_number(const int64_t from)
 
965
{
 
966
  /* 
 
967
   * First convert the absolute day number into a Julian
 
968
   * Day Number and then run a standard conversion on the
 
969
   * JDN.
 
970
   */
 
971
  gregorian_date_from_julian_day_number(from, &_years, &_months, &_days);
 
972
  return is_valid();
 
973
}
 
974
 
 
975
/**
 
976
 * Ignore overflow and pass-through to DateTime::from_int64_t()
 
977
 */
 
978
bool Date::from_int32_t(const int32_t from)
 
979
{
 
980
  return ((DateTime *) this)->from_int64_t((int64_t) from);
 
981
}
 
982
 
 
983
/**
 
984
 * Attempt to interpret the supplied 4-byte integer as
 
985
 * a TIME value in the format HHmmSS
 
986
 */
 
987
bool Time::from_int32_t(const int32_t from)
 
988
{
 
989
  int32_t copy_from= from;
 
990
  _hours= copy_from % INT32_C(10000);
 
991
  _minutes= copy_from % INT32_C(100);
 
992
  _seconds= copy_from & 3; /* Masks off all but last 2 digits */
 
993
  return is_valid();
 
994
}
 
995
 
 
996
/**
 
997
 * We try to intepret the incoming number as a datetime "string".
 
998
 * This is pretty much a hack for usability, but keeps us compatible
 
999
 * with MySQL.
 
1000
 */
 
1001
bool DateTime::from_int64_t(const int64_t from)
 
1002
{
 
1003
  int64_t copy_from= from;
 
1004
  int64_t part1;
 
1005
  int64_t part2;
 
1006
 
 
1007
  if (! (copy_from == 0LL || copy_from >= 10000101000000LL))
 
1008
  {
 
1009
    if (copy_from < 101)
 
1010
      return false;
 
1011
    if (copy_from <= (DRIZZLE_YY_PART_YEAR-1)*10000L+1231L)
 
1012
      copy_from= (copy_from+20000000L)*1000000L;                 /* YYMMDD, year: 2000-2069 */
 
1013
    if (copy_from < (DRIZZLE_YY_PART_YEAR)*10000L+101L)
 
1014
      return false;
 
1015
    if (copy_from <= 991231L)
 
1016
      copy_from= (copy_from+19000000L)*1000000L;                 /* YYMMDD, year: 1970-1999 */
 
1017
    if (copy_from < 10000101L)
 
1018
      return false;
 
1019
    if (copy_from <= 99991231L)
 
1020
      copy_from= copy_from*1000000L;
 
1021
    if (copy_from < 101000000L)
 
1022
      return false;
 
1023
    if (copy_from <= (DRIZZLE_YY_PART_YEAR-1) * 10000000000LL + 1231235959LL)
 
1024
      copy_from= copy_from + 20000000000000LL;                   /* YYMMDDHHMMSS, 2000-2069 */
 
1025
    if (copy_from <  DRIZZLE_YY_PART_YEAR * 10000000000LL + 101000000LL)
 
1026
      return false;
 
1027
    if (copy_from <= 991231235959LL)
 
1028
      copy_from= copy_from + 19000000000000LL;          /* YYMMDDHHMMSS, 1970-1999 */
 
1029
  }
 
1030
 
 
1031
  part1= (int64_t) (copy_from / 1000000LL);
 
1032
  part2= (int64_t) (copy_from - (int64_t) part1 * 1000000LL);
 
1033
  _years=  (uint32_t) (part1/10000L);  
 
1034
  
 
1035
  part1%=10000L;
 
1036
  _months= (uint32_t) part1 / 100;
 
1037
  _days=   (uint32_t) part1 % 100;
 
1038
  _hours=  (uint32_t) (part2/10000L);  
 
1039
 
 
1040
  part2%=10000L;
 
1041
  _minutes= (uint32_t) part2 / 100;
 
1042
  _seconds= (uint32_t) part2 % 100;
 
1043
 
 
1044
  set_epoch_seconds();
 
1045
  return is_valid();
 
1046
}
 
1047
 
 
1048
bool Date::in_unix_epoch() const
 
1049
{
 
1050
  return in_unix_epoch_range(_years, _months, _days, 0, 0, 0);
 
1051
}
 
1052
 
 
1053
bool DateTime::in_unix_epoch() const
 
1054
{
 
1055
  return in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds);
 
1056
}
 
1057
 
 
1058
bool Date::from_tm(const struct tm *from)
 
1059
{
 
1060
  _years= 1900 + from->tm_year;
 
1061
  _months= 1 + from->tm_mon; /* Month is NOT ordinal for struct tm! */
 
1062
  _days= from->tm_mday; /* Day IS ordinal for struct tm */
 
1063
  _hours= from->tm_hour;
 
1064
  _minutes= from->tm_min;
 
1065
  _seconds= from->tm_sec;
 
1066
  /* Set hires precision to zero */
 
1067
  _useconds= 0;
 
1068
  _nseconds= 0;
 
1069
 
 
1070
  set_epoch_seconds();
 
1071
  return is_valid();
 
1072
}
 
1073
 
 
1074
bool Date::from_time_t(const time_t from)
 
1075
{
 
1076
  struct tm broken_time;
 
1077
  struct tm *result;
 
1078
 
 
1079
  result= gmtime_r(&from, &broken_time);
 
1080
  if (result != NULL)
 
1081
  {
 
1082
    _years= 1900 + broken_time.tm_year;
 
1083
    _months= 1 + broken_time.tm_mon; /* Month is NOT ordinal for struct tm! */
 
1084
    _days= broken_time.tm_mday; /* Day IS ordinal for struct tm */
 
1085
    _hours= 0;
 
1086
    _minutes= 0;
 
1087
    _seconds= 0;
 
1088
    _epoch_seconds= 0;
 
1089
    /* Set hires precision to zero */
 
1090
    _useconds= 0;
 
1091
    _nseconds= 0;
 
1092
    return is_valid();
 
1093
  }
 
1094
  else 
 
1095
    return false;
 
1096
}
 
1097
 
 
1098
bool DateTime::from_time_t(const time_t from)
 
1099
{
 
1100
  struct tm broken_time;
 
1101
  struct tm *result;
 
1102
 
 
1103
  result= gmtime_r(&from, &broken_time);
 
1104
  if (result != NULL)
 
1105
  {
 
1106
    _years= 1900 + broken_time.tm_year;
 
1107
    _months= 1 + broken_time.tm_mon; /* Month is NOT ordinal for struct tm! */
 
1108
    _days= broken_time.tm_mday; /* Day IS ordinal for struct tm */
 
1109
    _hours= broken_time.tm_hour;
 
1110
    _minutes= broken_time.tm_min;
 
1111
    _seconds= broken_time.tm_sec;
 
1112
    _epoch_seconds= from;
 
1113
    /* Set hires precision to zero */
 
1114
    _useconds= 0;
 
1115
    _nseconds= 0;
 
1116
    return is_valid();
 
1117
  }
 
1118
  else 
 
1119
    return false;
 
1120
}
 
1121
 
 
1122
void Date::to_time_t(time_t *to) const
 
1123
{
 
1124
  if (in_unix_epoch())
 
1125
    *to= _epoch_seconds;
 
1126
  *to= 0;
 
1127
}
 
1128
 
 
1129
void Timestamp::to_time_t(time_t *to) const
 
1130
{
 
1131
  *to= _epoch_seconds;
 
1132
}
 
1133
 
 
1134
void MicroTimestamp::to_timeval(struct timeval *to) const
 
1135
{
 
1136
  to->tv_sec= _epoch_seconds;
 
1137
  to->tv_usec= _useconds;
 
1138
}
 
1139
 
 
1140
void NanoTimestamp::to_timespec(struct timespec *to) const
 
1141
{
 
1142
  to->tv_sec= _epoch_seconds;
 
1143
  to->tv_nsec= _nseconds;
 
1144
}
 
1145
 
 
1146
bool Date::is_valid() const
 
1147
{
 
1148
  return (_years >= DRIZZLE_MIN_YEARS_SQL && _years <= DRIZZLE_MAX_YEARS_SQL)
 
1149
      && (_months >= 1 && _months <= 12)
 
1150
      && (_days >= 1 && _days <= days_in_gregorian_year_month(_years, _months));
 
1151
}
 
1152
 
 
1153
bool Time::is_valid() const
 
1154
{
 
1155
  return (_years == 0)
 
1156
      && (_months == 0)
 
1157
      && (_days == 0)
 
1158
      && (_hours <= 23)
 
1159
      && (_minutes <= 59)
 
1160
      && (_seconds <= 59); /* No Leap second... TIME is for elapsed time... */
 
1161
}
 
1162
 
 
1163
bool DateTime::is_valid() const
 
1164
{
 
1165
  return (_years >= DRIZZLE_MIN_YEARS_SQL && _years <= DRIZZLE_MAX_YEARS_SQL)
 
1166
      && (_months >= 1 && _months <= 12)
 
1167
      && (_days >= 1 && _days <= days_in_gregorian_year_month(_years, _months))
 
1168
      && (_hours <= 23)
 
1169
      && (_minutes <= 59)
 
1170
      && (_seconds <= 61); /* Leap second... */
 
1171
}
 
1172
 
 
1173
bool Timestamp::is_valid() const
 
1174
{
 
1175
  return in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds);
 
1176
}
 
1177
 
 
1178
bool MicroTimestamp::is_valid() const
 
1179
{
 
1180
  return in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds)
 
1181
      && (_useconds <= UINT32_C(999999));
 
1182
}
 
1183
 
 
1184
bool NanoTimestamp::is_valid() const
 
1185
{
 
1186
  return in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds)
 
1187
      && (_useconds <= UINT32_C(999999))
 
1188
      && (_nseconds <= UINT32_C(999999999));
 
1189
}
 
1190
 
 
1191
} /* end namespace drizzled */