~drizzle-trunk/drizzle/development

813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
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
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
37
#include "config.h"
813.1.12 by Jay Pipes
Fixes for SECOND() function to use new Temporal system. Because
38
1241.9.61 by Monty Taylor
No more mystrings in drizzled/
39
#include "drizzled/charset_info.h"
1410.3.1 by Djellel E. Difallah
merge my_decimal and decimal
40
#include "drizzled/decimal.h"
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
41
#include "drizzled/calendar.h"
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
42
#include "drizzled/temporal.h"
43
#include "drizzled/temporal_format.h"
1237.9.8 by Monty Taylor
Fixed solaris build.
44
#include "drizzled/time_functions.h"
45
#include "time.h"
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
46
1238.1.3 by Brian Aker
ICC fixes/fix for solaris.
47
#include <time.h>
48
1502.3.1 by iwamatsu at nigauri
Add cstdio include to files needing it. Fixes the build on some debian
49
#include <cstdio>
907.1.7 by Jay Pipes
Merged in remove-timezone work
50
#include <ostream>
51
#include <iomanip>
779.4.3 by Monty Taylor
Fixed include order compile thing.
52
#include <vector>
53
#include <string.h>
54
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
55
namespace drizzled 
56
{
57
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
58
extern std::vector<TemporalFormat *> known_datetime_formats;
59
extern std::vector<TemporalFormat *> known_date_formats;
60
extern std::vector<TemporalFormat *> known_time_formats;
61
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
62
Temporal::Temporal()
63
:
64
  _calendar(GREGORIAN)
65
, _years(0)
66
, _months(0)
67
, _days(0)
68
, _hours(0)
69
, _minutes(0)
70
, _seconds(0)
71
, _epoch_seconds(0)
72
, _useconds(0)
73
, _nseconds(0)
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
74
, _overflow(false)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
75
{}
76
77
uint64_t Temporal::_cumulative_seconds_in_time() const
78
{
79
  return (uint64_t) ((_hours * INT64_C(3600)) 
80
      + (_minutes * INT64_C(60)) 
81
      + _seconds);
82
}
83
84
void Temporal::set_epoch_seconds()
85
{
86
  /* 
87
   * If the temporal is in the range of a timestamp, set 
88
   * the epoch_seconds member variable
89
   */
90
  if (in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds))
91
  {
92
    time_t result_time;
93
    struct tm broken_time;
94
95
    broken_time.tm_sec= _seconds;
96
    broken_time.tm_min= _minutes;
97
    broken_time.tm_hour= _hours;
98
    broken_time.tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
99
    broken_time.tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
100
    broken_time.tm_year= _years - 1900; /* tm_year expects range of 70 - 38 */
101
102
    result_time= timegm(&broken_time);
103
104
    _epoch_seconds= result_time;
105
  }
106
}
107
108
bool Date::from_string(const char *from, size_t from_len)
109
{
110
  /* 
111
   * Loop through the known date formats and see if 
112
   * there is a match.
113
   */
114
  bool matched= false;
115
  TemporalFormat *current_format;
116
  std::vector<TemporalFormat *>::iterator current= known_date_formats.begin();
117
118
  while (current != known_date_formats.end())
119
  {
120
    current_format= *current;
121
    if (current_format->matches(from, from_len, this))
122
    {
123
      matched= true;
124
      break;
125
    }
126
    current++;
127
  }
128
129
  if (! matched)
130
    return false;
131
132
  set_epoch_seconds();
133
  return is_valid();
134
}
135
136
bool DateTime::from_string(const char *from, size_t from_len)
137
{
138
  /* 
139
   * Loop through the known datetime formats and see if 
140
   * there is a match.
141
   */
142
  bool matched= false;
143
  TemporalFormat *current_format;
144
  std::vector<TemporalFormat *>::iterator current= known_datetime_formats.begin();
145
146
  while (current != known_datetime_formats.end())
147
  {
148
    current_format= *current;
149
    if (current_format->matches(from, from_len, this))
150
    {
151
      matched= true;
152
      break;
153
    }
154
    current++;
155
  }
156
157
  if (! matched)
158
    return false;
159
160
  set_epoch_seconds();
161
  return is_valid();
162
}
163
164
/*
165
 * Comparison operators for Time against another Time
166
 * are easy.  We simply compare the cumulative time
167
 * value of each.
168
 */
169
bool Time::operator==(const Time& rhs)
170
{
171
  return (
172
          _hours == rhs._hours
173
       && _minutes == rhs._minutes
174
       && _seconds == rhs._seconds
175
       && _useconds == rhs._useconds
176
       && _nseconds == rhs._nseconds
177
      );
178
}
179
bool Time::operator!=(const Time& rhs)
180
{
181
  return ! (*this == rhs);
182
}
183
bool Time::operator<(const Time& rhs)
184
{
185
  return (_cumulative_seconds_in_time() < rhs._cumulative_seconds_in_time());
186
}
187
bool Time::operator<=(const Time& rhs)
188
{
189
  return (_cumulative_seconds_in_time() <= rhs._cumulative_seconds_in_time());
190
}
191
bool Time::operator>(const Time& rhs)
192
{
193
  return (_cumulative_seconds_in_time() > rhs._cumulative_seconds_in_time());
194
}
195
bool Time::operator>=(const Time& rhs)
196
{
197
  return (_cumulative_seconds_in_time() >= rhs._cumulative_seconds_in_time());
198
}
199
200
/** 
201
 * Subtracting one Time value from another can yield
202
 * a new Time instance.
203
 *
204
 * This operator is called in the following situation:
205
 *
206
 * @code
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
207
 * Time lhs;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
208
 * lhs.from_string("20:00:00");
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
209
 * Time rhs;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
210
 * rhs.from_string("19:00:00");
211
 *
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
212
 * Time result= lhs - rhs;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
213
 * @endcode
214
 *
215
 * @note
216
 *
217
 * Subtracting a larger time value from a smaller one
218
 * should throw an exception at some point.  The result
219
 * of such an operator should be a TemporalInterval, not
220
 * a Time instance, since a negative time is not possible.
221
 */
222
const Time Time::operator-(const Time& rhs)
223
{
224
  Time result;
225
226
  int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
227
  result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
228
  second_diff%= DRIZZLE_SECONDS_IN_HOUR;
229
  result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
230
  second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
231
  result._seconds= (uint32_t) second_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
232
  
233
  return result;
234
}
235
const Time Time::operator+(const Time& rhs)
236
{
237
  Time result;
238
  int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
239
  result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
240
  second_diff%= DRIZZLE_SECONDS_IN_HOUR;
241
  result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
242
  second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
243
  result._seconds= (uint32_t) second_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
244
  /** 
245
   * @TODO Once exceptions are supported, we should raise an error here if
246
   *       the result Time is not valid?
247
   */
248
  return result;
249
}
250
251
/*
252
 * Variation of + and - operator which returns a reference to the left-hand
253
 * side Time object and adds the right-hand side to itself.
254
 */
255
Time& Time::operator+=(const Time& rhs)
256
{
257
  int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
258
  _hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
259
  second_diff%= DRIZZLE_SECONDS_IN_HOUR;
260
  _minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
261
  second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
262
  _seconds= (uint32_t) second_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
263
  /** 
264
   * @TODO Once exceptions are supported, we should raise an error here if
265
   *       the result Time is not valid?
266
   */
267
  return *this;
268
}
269
Time& Time::operator-=(const Time& rhs)
270
{
271
  int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
272
  _hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
273
  second_diff%= DRIZZLE_SECONDS_IN_HOUR;
274
  _minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
275
  second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
276
  _seconds= (uint32_t) second_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
277
  /** 
278
   * @TODO Once exceptions are supported, we should raise an error here if
279
   *       the result Time is not valid?
280
   */
281
  return *this;
282
}
283
284
/*
285
 * Comparison operators for Date against another Date
286
 * are easy.  We simply compare the cumulative
287
 * value of each.
288
 */
289
bool Date::operator==(const Date& rhs)
290
{
291
  return (
292
          _years == rhs._years
293
       && _months == rhs._months
294
       && _days == rhs._days
295
      );
296
}
297
bool Date::operator!=(const Date& rhs)
298
{
299
  return ! (*this == rhs);
300
}
301
bool Date::operator<(const Date& rhs)
302
{
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
303
  int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
304
  int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
305
  return (days_left < days_right);
306
}
307
bool Date::operator<=(const Date& rhs)
308
{
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
309
  int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
310
  int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
311
  return (days_left <= days_right);
312
}
313
bool Date::operator>(const Date& rhs)
314
{
315
  return ! (*this <= rhs);
316
}
317
bool Date::operator>=(const Date& rhs)
318
{
319
  return ! (*this < rhs);
320
}
321
322
/*
323
 * Comparison operators for DateTime against another DateTime
324
 * are easy.  We simply compare the cumulative time
325
 * value of each.
326
 */
892.2.9 by Monty Taylor
Raped Jay's code.
327
bool Date::operator==(const DateTime& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
328
{
329
  return (
330
          _years == rhs._years
331
       && _months == rhs._months
332
       && _days == rhs._days
333
       && _hours == rhs._hours
334
       && _minutes == rhs._minutes
335
       && _seconds == rhs._seconds
336
       && _useconds == rhs._useconds
337
       && _nseconds == rhs._nseconds
338
      );
339
}
892.2.9 by Monty Taylor
Raped Jay's code.
340
bool Date::operator!=(const DateTime& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
341
{
342
  return ! (*this == rhs);
343
}
892.2.9 by Monty Taylor
Raped Jay's code.
344
bool Date::operator<(const DateTime& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
345
{
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
346
  int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
347
  int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
348
  if (days_left < days_right)
349
    return true;
350
  else if (days_left > days_right)
351
    return false;
352
  /* Here if both dates are the same, so compare times */
353
  return (_cumulative_seconds_in_time() < rhs._cumulative_seconds_in_time());
354
}
892.2.9 by Monty Taylor
Raped Jay's code.
355
bool Date::operator<=(const DateTime& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
356
{
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
357
  int64_t days_left= julian_day_number_from_gregorian_date(_years, _months, _days);
358
  int64_t days_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
359
  if (days_left < days_right)
360
    return true;
361
  else if (days_left > days_right)
362
    return false;
363
  /* Here if both dates are the same, so compare times */
364
  return (_cumulative_seconds_in_time() <= rhs._cumulative_seconds_in_time());
365
}
892.2.9 by Monty Taylor
Raped Jay's code.
366
bool Date::operator>(const DateTime& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
367
{
368
  return ! (*this <= rhs);
369
}
892.2.9 by Monty Taylor
Raped Jay's code.
370
bool Date::operator>=(const DateTime& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
371
{
372
  return ! (*this < rhs);
373
}
374
375
/** 
376
 * We can add or subtract a Time value to/from a DateTime value 
377
 * as well...it always produces a DateTime.
378
 */
892.2.10 by Monty Taylor
More raping of Jay's code.
379
const Date Date::operator-(const Time& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
380
{
381
  DateTime result;
382
383
  /* 
384
   * First, we set the resulting DATE pieces equal to our 
385
   * left-hand side DateTime's DATE components. Then, deal with 
386
   * the time components.
387
   */
388
  result._years= _years;
389
  result._months= _months;
390
  result._days= _days;
391
392
  int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
393
394
  /* 
395
   * The resulting diff might be negative.  If it is, that means that 
396
   * we have subtracting a larger time piece from the datetime, like so:
397
   *
398
   * x = DateTime("2007-06-09 09:30:00") - Time("16:30:00");
399
   *
400
   * In these cases, we need to subtract a day from the resulting
401
   * DateTime.
402
   */
403
  if (second_diff < 0)
404
    result._days--;
405
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
406
  result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
407
  second_diff%= DRIZZLE_SECONDS_IN_HOUR;
408
  result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
409
  second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
410
  result._seconds= (uint32_t) second_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
411
412
  /* Handle the microsecond precision */
413
  int64_t microsecond_diff= _useconds - rhs._useconds;
414
  if (microsecond_diff < 0)
415
  {
416
    microsecond_diff= (-1 * microsecond_diff);
417
    result._seconds--;
418
  }
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
419
  result._useconds= (uint32_t) microsecond_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
420
421
  return result;
422
}
892.2.10 by Monty Taylor
More raping of Jay's code.
423
const Date Date::operator+(const Time& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
424
{
425
  DateTime result;
426
427
  /* 
428
   * First, we set the resulting DATE pieces equal to our 
429
   * left-hand side DateTime's DATE components. Then, deal with 
430
   * the time components.
431
   */
432
  result._years= _years;
433
  result._months= _months;
434
  result._days= _days;
435
436
  int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
437
438
  /* 
439
   * The resulting seconds might be more than a day.  If do, 
440
   * adjust our resulting days up 1.
441
   */
442
  if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
443
  {
444
    result._days++;
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
445
    second_diff%= DRIZZLE_SECONDS_IN_DAY;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
446
  }
447
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
448
  result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
449
  second_diff%= DRIZZLE_SECONDS_IN_HOUR;
450
  result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
451
  second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
452
  result._seconds= (uint32_t) second_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
453
454
  /* Handle the microsecond precision */
455
  int64_t microsecond_diff= _useconds - rhs._useconds;
456
  if (microsecond_diff < 0)
457
  {
458
    microsecond_diff= (-1 * microsecond_diff);
459
    result._seconds--;
460
  }
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
461
  result._useconds= (uint32_t) microsecond_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
462
463
  return result;
464
}
465
466
/*
467
 * Variation of + and - operator which returns a reference to the left-hand
468
 * side DateTime object and adds the right-hand side Time to itself.
469
 */
892.2.10 by Monty Taylor
More raping of Jay's code.
470
Date& Date::operator+=(const Time& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
471
{
472
  int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
473
  /* 
474
   * The resulting seconds might be more than a day.  If do, 
475
   * adjust our resulting days up 1.
476
   */
477
  if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
478
  {
479
    _days++;
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
480
    second_diff%= DRIZZLE_SECONDS_IN_DAY;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
481
  }
482
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
483
  _hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
484
  second_diff%= DRIZZLE_SECONDS_IN_HOUR;
485
  _minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
486
  second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
487
  _seconds= (uint32_t) second_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
488
489
  /* Handle the microsecond precision */
490
  int64_t microsecond_diff= _useconds - rhs._useconds;
491
  if (microsecond_diff < 0)
492
  {
493
    microsecond_diff= (-1 * microsecond_diff);
494
    _seconds--;
495
  }
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
496
  _useconds= (uint32_t) microsecond_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
497
  /** 
498
   * @TODO Once exceptions are supported, we should raise an error here if
499
   *       the result Time is not valid?
500
   */
501
  return *this;
502
}
892.2.10 by Monty Taylor
More raping of Jay's code.
503
Date& Date::operator-=(const Time& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
504
{
505
  int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
506
507
  /* 
508
   * The resulting diff might be negative.  If it is, that means that 
509
   * we have subtracting a larger time piece from the datetime, like so:
510
   *
511
   * x = DateTime("2007-06-09 09:30:00");
512
   * x-= Time("16:30:00");
513
   *
514
   * In these cases, we need to subtract a day from the resulting
515
   * DateTime.
516
   */
517
  if (second_diff < 0)
518
    _days--;
519
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
520
  _hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
521
  second_diff%= DRIZZLE_SECONDS_IN_HOUR;
522
  _minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
523
  second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
524
  _seconds= (uint32_t) second_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
525
526
  /* Handle the microsecond precision */
527
  int64_t microsecond_diff= _useconds - rhs._useconds;
528
  if (microsecond_diff < 0)
529
  {
530
    microsecond_diff= (-1 * microsecond_diff);
531
    _seconds--;
532
  }
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
533
  _useconds= (uint32_t) microsecond_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
534
  /** 
535
   * @TODO Once exceptions are supported, we should raise an error here if
536
   *       the result Time is not valid?
537
   */
538
  return *this;
539
}
540
541
/**
542
 * We can add/subtract two Dates to/from each other.  The result
543
 * is always another Date instance.
544
 */
545
const Date Date::operator-(const Date &rhs)
546
{
547
  /* Figure out the difference in days between the two dates */
548
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
549
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
550
  int64_t day_diff= day_left - day_right;
551
552
  Date result;
553
  /* Now re-compose the Date's structure from the resulting Julian Day Number */
554
  gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
555
  return result;
556
}
557
const Date Date::operator+(const Date &rhs)
558
{
559
  /* 
560
   * Figure out the new Julian Day Number by adding the JDNs of both
561
   * dates together.
562
   */
563
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
564
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
565
  int64_t day_diff= day_left + day_right;
566
567
  /** @TODO Need an exception check here for bounds of JDN... */
568
569
  Date result;
570
  /* Now re-compose the Date's structure from the resulting Julian Day Number */
571
  gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
572
  return result;
573
}
574
/* Similar to the above, but we add/subtract the right side to this object itself */
575
Date& Date::operator-=(const Date &rhs)
576
{
577
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
578
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
579
  int64_t day_diff= day_left - day_right;
580
581
  /* Now re-compose the Date's structure from the resulting Julian Day Number */
582
  gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
583
  return *this;
584
}
585
Date& Date::operator+=(const Date &rhs)
586
{
587
  /* 
588
   * Figure out the new Julian Day Number by adding the JDNs of both
589
   * dates together.
590
   */
591
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
592
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
593
  int64_t day_diff= day_left + day_right;
594
595
  /** @TODO Need an exception check here for bounds of JDN... */
596
597
  /* Now re-compose the Date's structure from the resulting Julian Day Number */
598
  gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
599
  return *this;
600
}
601
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
602
Date& Date::operator=(const DateTime &rhs)
603
{
604
  /* Only copy the Date components of the assigned DateTime... */
605
  _years= rhs._years;
606
  _months= rhs._months;
607
  _days= rhs._days;
608
  /* Zero-out everything else.. */
609
  _hours= _minutes= _seconds= _useconds= _nseconds= 0;
610
  return *this;
611
}
612
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
613
/**
614
 * We can add/subtract two DateTimes to/from each other.  The result
615
 * is always another DateTime instance.
616
 */
892.2.9 by Monty Taylor
Raped Jay's code.
617
const Date Date::operator-(const DateTime &rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
618
{
619
  /* Figure out the difference in days between the two dates. */
620
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
621
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
622
  int64_t day_diff= day_left - day_right;
623
624
  DateTime result;
625
  /* Now re-compose the Date's structure from the resulting Julian Day Number */
626
  gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
627
628
  /* And now handle the time components */
629
  int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
630
631
  /* 
632
   * The resulting diff might be negative.  If it is, that means that 
633
   * we have subtracting a larger time piece from the datetime, like so:
634
   *
635
   * x = DateTime("2007-06-09 09:30:00");
636
   * x-= Time("16:30:00");
637
   *
638
   * In these cases, we need to subtract a day from the resulting
639
   * DateTime.
640
   */
641
  if (second_diff < 0)
642
    _days--;
643
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
644
  result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
645
  second_diff%= DRIZZLE_SECONDS_IN_HOUR;
646
  result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
647
  second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
648
  result._seconds= (uint32_t) second_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
649
650
  /* Handle the microsecond precision */
651
  int64_t microsecond_diff= _useconds - rhs._useconds;
652
  if (microsecond_diff < 0)
653
  {
654
    microsecond_diff= (-1 * microsecond_diff);
655
    result._seconds--;
656
  }
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
657
  result._useconds= (uint32_t) microsecond_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
658
659
  return result;
660
}
892.2.9 by Monty Taylor
Raped Jay's code.
661
const Date Date::operator+(const DateTime &rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
662
{
892.2.9 by Monty Taylor
Raped Jay's code.
663
  /*
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
664
   * Figure out the new Julian Day Number by adding the JDNs of both
665
   * dates together.
666
   */
667
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
668
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
669
  int64_t day_diff= day_left + day_right;
670
671
  /** @TODO Need an exception check here for bounds of JDN... */
672
673
  DateTime result;
674
  /* Now re-compose the Date's structure from the resulting Julian Day Number */
675
  gregorian_date_from_julian_day_number(day_diff, &result._years, &result._months, &result._days);
676
677
  /* And now handle the time components */
678
  int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
679
680
  /* 
681
   * The resulting seconds might be more than a day.  If do, 
682
   * adjust our resulting days up 1.
683
   */
684
  if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
685
  {
686
    result._days++;
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
687
    second_diff%= DRIZZLE_SECONDS_IN_DAY;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
688
  }
689
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
690
  result._hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
691
  second_diff%= DRIZZLE_SECONDS_IN_HOUR;
692
  result._minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
693
  second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
694
  result._seconds= (uint32_t) second_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
695
696
  /* Handle the microsecond precision */
697
  int64_t microsecond_diff= _useconds - rhs._useconds;
698
  if (microsecond_diff < 0)
699
  {
700
    microsecond_diff= (-1 * microsecond_diff);
701
    result._seconds--;
702
  }
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
703
  result._useconds= (uint32_t) microsecond_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
704
705
  return result;
706
}
707
/* Similar to the above, but we add/subtract the right side to this object itself */
892.2.9 by Monty Taylor
Raped Jay's code.
708
Date& Date::operator-=(const DateTime &rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
709
{
710
  /* Figure out the difference in days between the two dates.  */
711
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
712
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
713
  int64_t day_diff= day_left - day_right;
714
715
  /* Now re-compose the Date's structure from the ng Julian Day Number */
716
  gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
717
718
  /* And now handle the time components */
719
  int64_t second_diff= _cumulative_seconds_in_time() - rhs._cumulative_seconds_in_time();
720
721
  /* 
722
   * The resulting diff might be negative.  If it is, that means that 
723
   * we have subtracting a larger time piece from the datetime, like so:
724
   *
725
   * x = DateTime("2007-06-09 09:30:00");
726
   * x-= Time("16:30:00");
727
   *
728
   * In these cases, we need to subtract a day from the ng
729
   * DateTime.
730
   */
731
  if (second_diff < 0)
732
    _days--;
733
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
734
  _hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
735
  second_diff%= DRIZZLE_SECONDS_IN_HOUR;
736
  _minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
737
  second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
738
  _seconds= (uint32_t) second_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
739
740
  /* Handle the microsecond precision */
741
  int64_t microsecond_diff= _useconds - rhs._useconds;
742
  if (microsecond_diff < 0)
743
  {
744
    microsecond_diff= (-1 * microsecond_diff);
745
    _seconds--;
746
  }
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
747
  _useconds= (uint32_t) microsecond_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
748
749
  return *this;
750
}
892.2.9 by Monty Taylor
Raped Jay's code.
751
Date& Date::operator+=(const DateTime &rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
752
{
753
  /* 
754
   * Figure out the new Julian Day Number by adding the JDNs of both
755
   * dates together.
756
   */
757
  int64_t day_left= julian_day_number_from_gregorian_date(_years, _months, _days);
758
  int64_t day_right= julian_day_number_from_gregorian_date(rhs._years, rhs._months, rhs._days);
759
  int64_t day_diff= day_left + day_right;
760
761
  /** @TODO Need an exception check here for bounds of JDN... */
762
763
  /* Now re-compose the Date's structure from the ng Julian Day Number */
764
  gregorian_date_from_julian_day_number(day_diff, &_years, &_months, &_days);
765
766
  /* And now handle the time components */
767
  int64_t second_diff= _cumulative_seconds_in_time() + rhs._cumulative_seconds_in_time();
768
769
  /* 
770
   * The resulting seconds might be more than a day.  If do, 
771
   * adjust our ng days up 1.
772
   */
773
  if (second_diff >= DRIZZLE_SECONDS_IN_DAY)
774
  {
775
    _days++;
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
776
    second_diff%= DRIZZLE_SECONDS_IN_DAY;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
777
  }
778
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
779
  _hours= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_HOUR;
780
  second_diff%= DRIZZLE_SECONDS_IN_HOUR;
781
  _minutes= (uint32_t) second_diff / DRIZZLE_SECONDS_IN_MINUTE;
782
  second_diff%= DRIZZLE_SECONDS_IN_MINUTE;
783
  _seconds= (uint32_t) second_diff;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
784
785
  /* Handle the microsecond precision */
786
  int64_t microsecond_diff= _useconds - rhs._useconds;
787
  if (microsecond_diff < 0)
788
  {
789
    microsecond_diff= (-1 * microsecond_diff);
790
    _seconds--;
791
  }
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
792
  _useconds= (uint32_t) microsecond_diff;
793
794
  return *this;
795
}
1377.8.28 by Paweł Blokus
removed TemporalInterval speciaslisation classes
796
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
797
/*
910.2.10 by Monty Taylor
Merged in jay's patch again.
798
 * Comparison operators between a Date and a Timestamp
799
 */
800
bool Date::operator==(const Timestamp& rhs)
801
{
802
  return (_years == rhs._years && _months == rhs._months && _days == rhs._days);
803
}
804
bool Date::operator!=(const Timestamp& rhs)
805
{
806
  return ! (*this == rhs);
807
}
808
bool Date::operator<(const Timestamp& rhs)
809
{
810
  if (_years < rhs._years)
811
    return true;
812
  if (_years > rhs._years)
813
    return false;
814
  /* In same year */
815
  if (_months < rhs._months)
816
    return true;
817
  if (_months > rhs._months)
818
    return false;
819
  /* Same month */
820
  return _days < rhs._days;
821
}
822
bool Date::operator<=(const Timestamp& rhs)
823
{
824
  return (*this < rhs || *this == rhs);
825
}
826
bool Date::operator>(const Timestamp& rhs)
827
{
1377.8.25 by Paweł Blokus
this was the first working build, and these changes make almost all the tests pass
828
  return ! (*this <= rhs);
910.2.10 by Monty Taylor
Merged in jay's patch again.
829
}
830
bool Date::operator>=(const Timestamp& rhs)
831
{
1377.8.25 by Paweł Blokus
this was the first working build, and these changes make almost all the tests pass
832
  return ! (*this < rhs);
910.2.10 by Monty Taylor
Merged in jay's patch again.
833
}
834
/*
835
 * Comparison operators between a Timestamp and a Date
836
 */
837
bool Timestamp::operator==(const Date& rhs)
838
{
839
  return (_years == rhs._years && _months == rhs._months && _days == rhs._days);
840
}
841
bool Timestamp::operator!=(const Date& rhs)
842
{
843
  return ! (*this == rhs);
844
}
845
bool Timestamp::operator<(const Date& rhs)
846
{
847
  if (_years < rhs._years)
848
    return true;
849
  if (_years > rhs._years)
850
    return false;
851
  /* In same year */
852
  if (_months < rhs._months)
853
    return true;
854
  if (_months > rhs._months)
855
    return false;
856
  /* Same month */
857
  return _days < rhs._days;
858
}
859
bool Timestamp::operator<=(const Date& rhs)
860
{
861
  return (*this < rhs || *this == rhs);
862
}
863
bool Timestamp::operator>(const Date& rhs)
864
{
1377.8.25 by Paweł Blokus
this was the first working build, and these changes make almost all the tests pass
865
  return ! (*this <= rhs);
910.2.10 by Monty Taylor
Merged in jay's patch again.
866
}
867
bool Timestamp::operator>=(const Date& rhs)
868
{
1377.8.25 by Paweł Blokus
this was the first working build, and these changes make almost all the tests pass
869
  return ! (*this < rhs);
910.2.10 by Monty Taylor
Merged in jay's patch again.
870
}
871
/*
872
 * Comparison operators between a Timestamp and a DateTime
873
 */
874
bool Timestamp::operator==(const DateTime& rhs)
875
{
876
  return (_years == rhs._years && _months == rhs._months && _days == rhs._days
877
          && _hours == rhs._hours && _minutes == rhs._minutes && _seconds == rhs._seconds);
878
}
879
bool Timestamp::operator!=(const DateTime& rhs)
880
{
881
  return ! (*this == rhs);
882
}
883
bool Timestamp::operator<(const DateTime& rhs)
884
{
885
  if (_years < rhs._years)
886
    return true;
887
  if (_years > rhs._years)
888
    return false;
889
  /* In same year */
890
  if (_months < rhs._months)
891
    return true;
892
  if (_months > rhs._months)
893
    return false;
894
  /* Same month */
895
  if (_days < rhs._days)
896
    return true;
897
  if (_days > rhs._days)
898
     return false;
899
  /* Same day */
900
  if (_hours < rhs._hours)
901
    return true;
902
  if (_hours > rhs._hours)
903
    return false;
904
  /* Same hour */
905
  if (_minutes < rhs._minutes)
906
    return true;
907
  if (_minutes > rhs._minutes)
908
    return false;
909
  /* Same minute */
910
  return _seconds < rhs._seconds;
911
}
912
bool Timestamp::operator<=(const DateTime& rhs)
913
{
914
  return (*this < rhs || *this == rhs);
915
}
916
bool Timestamp::operator>(const DateTime& rhs)
917
{
1377.8.25 by Paweł Blokus
this was the first working build, and these changes make almost all the tests pass
918
  return ! (*this <= rhs);
910.2.10 by Monty Taylor
Merged in jay's patch again.
919
}
920
bool Timestamp::operator>=(const DateTime& rhs)
921
{
1377.8.25 by Paweł Blokus
this was the first working build, and these changes make almost all the tests pass
922
  return ! (*this < rhs);
910.2.10 by Monty Taylor
Merged in jay's patch again.
923
}
924
/*
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
925
 * Comparison operators between two Timestamps
926
 */
907.1.7 by Jay Pipes
Merged in remove-timezone work
927
bool Timestamp::operator==(const Timestamp& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
928
{
929
  return (_epoch_seconds == rhs._epoch_seconds);
930
}
907.1.7 by Jay Pipes
Merged in remove-timezone work
931
bool Timestamp::operator!=(const Timestamp& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
932
{
933
  return ! (*this == rhs);
934
}
907.1.7 by Jay Pipes
Merged in remove-timezone work
935
bool Timestamp::operator<(const Timestamp& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
936
{
937
  return (_epoch_seconds < rhs._epoch_seconds);
938
}
907.1.7 by Jay Pipes
Merged in remove-timezone work
939
bool Timestamp::operator<=(const Timestamp& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
940
{
941
  return (_epoch_seconds <= rhs._epoch_seconds);
942
}
907.1.7 by Jay Pipes
Merged in remove-timezone work
943
bool Timestamp::operator>(const Timestamp& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
944
{
1377.8.25 by Paweł Blokus
this was the first working build, and these changes make almost all the tests pass
945
  return ! (*this <= rhs);
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
946
}
907.1.7 by Jay Pipes
Merged in remove-timezone work
947
bool Timestamp::operator>=(const Timestamp& rhs)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
948
{
1377.8.25 by Paweł Blokus
this was the first working build, and these changes make almost all the tests pass
949
  return ! (*this < rhs);
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
950
}
951
907.1.7 by Jay Pipes
Merged in remove-timezone work
952
/**
953
 * Push the contents of the timestamp into the output stream
954
 * as a formatted Timestamp value.
955
 *
956
 * @TODO This unfortunately fails in a weird way...even with std::noskipws, 
957
 * the output stream only reads up to the space in the string... :(
958
 */
959
std::ostream& operator<<(std::ostream& os, const Timestamp& subject)
960
{
961
  return os << subject.years() << '-' 
962
            << std::setw(2) << std::setfill('0') << subject.months() << '-'
963
            << std::setw(2) << std::setfill('0') << subject.days() << ' '
964
            << std::setw(2) << std::setfill('0') << subject.hours() << ':'
965
            << std::setw(2) << std::setfill('0') << subject.minutes() << ':'
966
            << std::setw(2) << std::setfill('0') << subject.seconds();
967
}
968
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
969
bool Time::from_string(const char *from, size_t from_len)
970
{
892.2.9 by Monty Taylor
Raped Jay's code.
971
  /*
972
   * Loop through the known time formats and see if
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
973
   * there is a match.
974
   */
975
  bool matched= false;
976
  TemporalFormat *current_format;
977
  std::vector<TemporalFormat *>::iterator current= known_time_formats.begin();
978
979
  while (current != known_time_formats.end())
980
  {
981
    current_format= *current;
982
    if (current_format->matches(from, from_len, this))
983
    {
984
      matched= true;
985
      break;
986
    }
987
    current++;
988
  }
989
990
  if (! matched)
991
    return false;
992
  else
993
    return is_valid();
994
}
995
1079.3.1 by Stewart Smith
Change temporal to_string routines to use snprintf instead of sprintf.
996
int Time::to_string(char *to, size_t to_len) const
997
{
998
  return snprintf(to, to_len,
999
		  "%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32,
1000
		  _hours, _minutes, _seconds);
1001
}
1002
1003
int Date::to_string(char *to, size_t to_len) const
1004
{
1005
  return snprintf(to, to_len,
1006
		  "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32,
1007
		  _years, _months, _days);
1008
}
1009
1010
int DateTime::to_string(char *to, size_t to_len) const
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1011
{
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
1012
  /* If the temporal has a microsecond component, use a slightly different output */
1013
  if (_useconds == 0)
1014
  {
1079.3.1 by Stewart Smith
Change temporal to_string routines to use snprintf instead of sprintf.
1015
    return snprintf(to, to_len,
1016
		    "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
1017
		          " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32,
1018
		    _years, _months, _days,
1019
		    _hours, _minutes, _seconds);
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
1020
  }
1021
  else
1022
  {
1079.3.1 by Stewart Smith
Change temporal to_string routines to use snprintf instead of sprintf.
1023
    return snprintf(to, to_len,
1024
		    "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
1025
		       " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32,
1026
		    _years, _months, _days,
1027
		    _hours, _minutes, _seconds, _useconds);
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
1028
  }
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1029
}
1030
1079.3.1 by Stewart Smith
Change temporal to_string routines to use snprintf instead of sprintf.
1031
int MicroTimestamp::to_string(char *to, size_t to_len) const
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1032
{
1079.3.1 by Stewart Smith
Change temporal to_string routines to use snprintf instead of sprintf.
1033
  return snprintf(to, to_len,
1034
		  "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
1035
		      " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32,
1036
		  _years, _months, _days,
1037
		  _hours, _minutes, _seconds, _useconds);
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1038
}
1039
1040
void Time::to_decimal(my_decimal *to) const
1041
{
1042
  int64_t time_portion= (((_hours * 100L) + _minutes) * 100L) + _seconds;
1043
  (void) int2my_decimal(E_DEC_FATAL_ERROR, time_portion, false, to);
1044
  if (_useconds > 0)
1045
  {
1046
    to->buf[(to->intg-1) / 9 + 1]= _useconds * 1000;
1047
    to->frac= 6;
1048
  }
1049
}
1050
1051
void Date::to_decimal(my_decimal *to) const
1052
{
1053
  int64_t date_portion= (((_years * 100L) + _months) * 100L) + _days;
1054
  (void) int2my_decimal(E_DEC_FATAL_ERROR, date_portion, false, to);
1055
}
1056
1057
void DateTime::to_decimal(my_decimal *to) const
1058
{
1059
  int64_t date_portion= (((_years * 100L) + _months) * 100L) + _days;
1060
  int64_t time_portion= (((((date_portion * 100L) + _hours) * 100L) + _minutes) * 100L) + _seconds;
1061
  (void) int2my_decimal(E_DEC_FATAL_ERROR, time_portion, false, to);
1062
  if (_useconds > 0)
1063
  {
1064
    to->buf[(to->intg-1) / 9 + 1]= _useconds * 1000;
1065
    to->frac= 6;
1066
  }
1067
}
1068
1069
void Date::to_int64_t(int64_t *to) const
1070
{
1071
  *to= (_years * INT32_C(10000)) 
1072
     + (_months * INT32_C(100)) 
1073
     + _days;
1074
}
1075
1076
void Date::to_int32_t(int32_t *to) const
1077
{
1078
  *to= (_years * INT32_C(10000)) 
1079
     + (_months * INT32_C(100)) 
1080
     + _days;
1081
}
1082
1083
void Time::to_int32_t(int32_t *to) const
1084
{
1085
  *to= (_hours * INT32_C(10000)) 
1086
     + (_minutes * INT32_C(100)) 
1087
     + _seconds;
1088
}
1089
1090
void DateTime::to_int64_t(int64_t *to) const
1091
{
1092
  *to= ((
1093
       (_years * INT64_C(10000)) 
1094
     + (_months * INT64_C(100)) 
1095
     + _days
1096
       ) * INT64_C(1000000))
1097
     + (
1098
       (_hours * INT64_C(10000)) 
1099
     + (_minutes * INT64_C(100) )
1100
     + _seconds
1101
     );
1102
}
1103
1104
void Date::to_tm(struct tm *to) const
1105
{
1106
  to->tm_sec= 0;
1107
  to->tm_min= 0;
1108
  to->tm_hour= 0;
1109
  to->tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
1110
  to->tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
1111
  to->tm_year= _years - 1900;
1112
}
1113
1114
void DateTime::to_tm(struct tm *to) const
1115
{
1116
  to->tm_sec= _seconds;
1117
  to->tm_min= _minutes;
1118
  to->tm_hour= _hours;
1119
  to->tm_mday= _days; /* Drizzle format uses ordinal, standard tm does too! */
1120
  to->tm_mon= _months - 1; /* Drizzle format uses ordinal, standard tm does NOT! */
1121
  to->tm_year= _years - 1900;
1122
}
1123
1124
bool Date::from_julian_day_number(const int64_t from)
1125
{
1126
  gregorian_date_from_julian_day_number(from, &_years, &_months, &_days);
1127
  return is_valid();
1128
}
1129
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
1130
void Date::to_julian_day_number(int64_t *to) const
1131
{
1132
  *to= julian_day_number_from_gregorian_date(_years, _months, _days);
1133
}
1134
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1135
/**
1136
 * Ignore overflow and pass-through to DateTime::from_int64_t()
1137
 */
1138
bool Date::from_int32_t(const int32_t from)
1139
{
1140
  return ((DateTime *) this)->from_int64_t((int64_t) from);
1141
}
1142
1143
/**
1144
 * Attempt to interpret the supplied 4-byte integer as
1145
 * a TIME value in the format HHmmSS
1146
 */
1147
bool Time::from_int32_t(const int32_t from)
1148
{
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
1149
  uint32_t copy_from= (uint32_t) from;
1377.8.25 by Paweł Blokus
this was the first working build, and these changes make almost all the tests pass
1150
  _hours= copy_from / INT32_C(10000);
1151
  _minutes= (copy_from % INT32_C(10000)) / INT32_C(100);
1152
  _seconds= copy_from % INT32_C(100); /* Masks off all but last 2 digits */
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1153
  return is_valid();
1154
}
1155
1156
/**
1157
 * We try to intepret the incoming number as a datetime "string".
1158
 * This is pretty much a hack for usability, but keeps us compatible
1159
 * with MySQL.
1160
 */
1079.3.2 by Stewart Smith
Replace MAX_(DATE|TIME).*_WIDTH defines in definitions.h with real (and correct) static const members to Temporal types.
1161
bool DateTime::from_int64_t(const int64_t from, bool convert)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1162
{
1163
  int64_t copy_from= from;
1164
  int64_t part1;
1165
  int64_t part2;
1166
873.1.7 by Jay Pipes
Fixes Field_datetime::store(NUMBER) to throw an error when invalid
1167
  if (copy_from == 0LL)
1168
    return false;
1169
1079.3.2 by Stewart Smith
Replace MAX_(DATE|TIME).*_WIDTH defines in definitions.h with real (and correct) static const members to Temporal types.
1170
  if (convert && copy_from < 10000101000000LL)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1171
  {
1172
    if (copy_from < 101)
1173
      return false;
873.1.7 by Jay Pipes
Fixes Field_datetime::store(NUMBER) to throw an error when invalid
1174
    else if (copy_from <= (DRIZZLE_YY_PART_YEAR-1)*10000L+1231L)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1175
      copy_from= (copy_from+20000000L)*1000000L;                 /* YYMMDD, year: 2000-2069 */
873.1.7 by Jay Pipes
Fixes Field_datetime::store(NUMBER) to throw an error when invalid
1176
    else if (copy_from < (DRIZZLE_YY_PART_YEAR)*10000L+101L)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1177
      return false;
873.1.7 by Jay Pipes
Fixes Field_datetime::store(NUMBER) to throw an error when invalid
1178
    else if (copy_from <= 991231L)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1179
      copy_from= (copy_from+19000000L)*1000000L;                 /* YYMMDD, year: 1970-1999 */
873.1.7 by Jay Pipes
Fixes Field_datetime::store(NUMBER) to throw an error when invalid
1180
    else if (copy_from < 10000101L)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1181
      return false;
873.1.7 by Jay Pipes
Fixes Field_datetime::store(NUMBER) to throw an error when invalid
1182
    else if (copy_from <= 99991231L)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1183
      copy_from= copy_from*1000000L;
873.1.7 by Jay Pipes
Fixes Field_datetime::store(NUMBER) to throw an error when invalid
1184
    else if (copy_from < 101000000L)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1185
      return false;
873.1.7 by Jay Pipes
Fixes Field_datetime::store(NUMBER) to throw an error when invalid
1186
    else if (copy_from <= (DRIZZLE_YY_PART_YEAR-1) * 10000000000LL + 1231235959LL)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1187
      copy_from= copy_from + 20000000000000LL;                   /* YYMMDDHHMMSS, 2000-2069 */
873.1.7 by Jay Pipes
Fixes Field_datetime::store(NUMBER) to throw an error when invalid
1188
    else if (copy_from <  DRIZZLE_YY_PART_YEAR * 10000000000LL + 101000000LL)
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1189
      return false;
873.1.7 by Jay Pipes
Fixes Field_datetime::store(NUMBER) to throw an error when invalid
1190
    else if (copy_from <= 991231235959LL)
1377.8.26 by Paweł Blokus
created or modified all to_int**_t and from_int**_t function tests
1191
      copy_from= copy_from + 19000000000000LL;    /* YYMMDDHHMMSS, 1970-1999 */
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1192
  }
1193
1194
  part1= (int64_t) (copy_from / 1000000LL);
1195
  part2= (int64_t) (copy_from - (int64_t) part1 * 1000000LL);
1196
  _years=  (uint32_t) (part1/10000L);  
1197
  
1198
  part1%=10000L;
1199
  _months= (uint32_t) part1 / 100;
1200
  _days=   (uint32_t) part1 % 100;
1201
  _hours=  (uint32_t) (part2/10000L);  
1202
1203
  part2%=10000L;
1204
  _minutes= (uint32_t) part2 / 100;
1205
  _seconds= (uint32_t) part2 % 100;
1206
1207
  set_epoch_seconds();
1208
  return is_valid();
1209
}
1210
1211
bool Date::in_unix_epoch() const
1212
{
1213
  return in_unix_epoch_range(_years, _months, _days, 0, 0, 0);
1214
}
1215
1216
bool DateTime::in_unix_epoch() const
1217
{
1218
  return in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds);
1219
}
1220
1221
bool Date::from_tm(const struct tm *from)
1222
{
1223
  _years= 1900 + from->tm_year;
1224
  _months= 1 + from->tm_mon; /* Month is NOT ordinal for struct tm! */
1225
  _days= from->tm_mday; /* Day IS ordinal for struct tm */
1226
  _hours= from->tm_hour;
1227
  _minutes= from->tm_min;
1228
  _seconds= from->tm_sec;
1229
  /* Set hires precision to zero */
1230
  _useconds= 0;
1231
  _nseconds= 0;
1232
1233
  set_epoch_seconds();
1234
  return is_valid();
1235
}
1236
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
1237
/* 
1238
 * We convert as if it's a Datetime, then simply
1239
 * drop the date portions...
1240
 */
1241
bool Time::from_time_t(const time_t from)
1242
{
1243
  struct tm broken_time;
1244
  struct tm *result;
1245
1246
  result= gmtime_r(&from, &broken_time);
1247
  if (result != NULL)
1248
  {
1249
    _years= 0;
1250
    _months= 0;
1251
    _days= 0;
1252
    _hours= broken_time.tm_hour;
1253
    _minutes= broken_time.tm_min;
1254
    _seconds= broken_time.tm_sec;
1255
    _epoch_seconds= 0; /* Don't store the time_t, since we only use part of it */
1256
    /* Set hires precision to zero */
1257
    _useconds= 0;
1258
    _nseconds= 0;
1259
    return true; /* Always true... */
1260
  }
1261
  else 
1262
    return false;
1263
}
1264
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1265
bool Date::from_time_t(const time_t from)
1266
{
1267
  struct tm broken_time;
1268
  struct tm *result;
1269
1270
  result= gmtime_r(&from, &broken_time);
1271
  if (result != NULL)
1272
  {
1273
    _years= 1900 + broken_time.tm_year;
1274
    _months= 1 + broken_time.tm_mon; /* Month is NOT ordinal for struct tm! */
1275
    _days= broken_time.tm_mday; /* Day IS ordinal for struct tm */
1276
    _hours= 0;
1277
    _minutes= 0;
1278
    _seconds= 0;
873.1.4 by Jay Pipes
Solaris integer truncation fixes - Thanks to MontyT for the warning output.. :)
1279
    _epoch_seconds= 0; /* Don't store the time_t, since we only use part of it */
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1280
    /* Set hires precision to zero */
1281
    _useconds= 0;
1282
    _nseconds= 0;
1283
    return is_valid();
1284
  }
1285
  else 
1286
    return false;
1287
}
1288
1289
bool DateTime::from_time_t(const time_t from)
1290
{
1291
  struct tm broken_time;
1292
  struct tm *result;
1293
1294
  result= gmtime_r(&from, &broken_time);
1295
  if (result != NULL)
1296
  {
1297
    _years= 1900 + broken_time.tm_year;
1298
    _months= 1 + broken_time.tm_mon; /* Month is NOT ordinal for struct tm! */
1299
    _days= broken_time.tm_mday; /* Day IS ordinal for struct tm */
1300
    _hours= broken_time.tm_hour;
1301
    _minutes= broken_time.tm_min;
1302
    _seconds= broken_time.tm_sec;
1303
    _epoch_seconds= from;
1304
    /* Set hires precision to zero */
1305
    _useconds= 0;
1306
    _nseconds= 0;
1307
    return is_valid();
1308
  }
1309
  else 
1310
    return false;
1311
}
1312
1313
void Date::to_time_t(time_t *to) const
1314
{
1315
  if (in_unix_epoch())
997.6.1 by Devananda
added else in Date::to_time_t
1316
  {
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1317
    *to= _epoch_seconds;
997.6.1 by Devananda
added else in Date::to_time_t
1318
  }
1319
  else
1320
    *to= 0;
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1321
}
1322
1323
void Timestamp::to_time_t(time_t *to) const
1324
{
1325
  *to= _epoch_seconds;
1326
}
1327
1328
void MicroTimestamp::to_timeval(struct timeval *to) const
1329
{
1330
  to->tv_sec= _epoch_seconds;
1331
  to->tv_usec= _useconds;
1332
}
1333
1334
void NanoTimestamp::to_timespec(struct timespec *to) const
1335
{
1336
  to->tv_sec= _epoch_seconds;
1337
  to->tv_nsec= _nseconds;
1338
}
1339
1340
bool Date::is_valid() const
1341
{
1342
  return (_years >= DRIZZLE_MIN_YEARS_SQL && _years <= DRIZZLE_MAX_YEARS_SQL)
1343
      && (_months >= 1 && _months <= 12)
1344
      && (_days >= 1 && _days <= days_in_gregorian_year_month(_years, _months));
1345
}
1346
1347
bool Time::is_valid() const
1348
{
1349
  return (_years == 0)
1350
      && (_months == 0)
1351
      && (_days == 0)
1352
      && (_hours <= 23)
1353
      && (_minutes <= 59)
1354
      && (_seconds <= 59); /* No Leap second... TIME is for elapsed time... */
1355
}
1356
1357
bool DateTime::is_valid() const
1358
{
1359
  return (_years >= DRIZZLE_MIN_YEARS_SQL && _years <= DRIZZLE_MAX_YEARS_SQL)
1360
      && (_months >= 1 && _months <= 12)
1361
      && (_days >= 1 && _days <= days_in_gregorian_year_month(_years, _months))
1362
      && (_hours <= 23)
1363
      && (_minutes <= 59)
1364
      && (_seconds <= 61); /* Leap second... */
1365
}
1366
1367
bool Timestamp::is_valid() const
1368
{
907.1.7 by Jay Pipes
Merged in remove-timezone work
1369
  return DateTime::is_valid() 
1370
      && in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds);
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1371
}
1372
1373
bool MicroTimestamp::is_valid() const
1374
{
907.1.7 by Jay Pipes
Merged in remove-timezone work
1375
  return Timestamp::is_valid()
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1376
      && (_useconds <= UINT32_C(999999));
1377
}
1378
1379
bool NanoTimestamp::is_valid() const
1380
{
907.1.7 by Jay Pipes
Merged in remove-timezone work
1381
  return Timestamp::is_valid()
813.1.2 by Jay Pipes
First function cleanup for temporal handling: YEAR()
1382
      && (_useconds <= UINT32_C(999999))
1383
      && (_nseconds <= UINT32_C(999999999));
1384
}
1385
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1386
} /* namespace drizzled */