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