~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/temporal.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-03-21 01:02:23 UTC
  • mto: (960.2.5 mordred)
  • mto: This revision was merged to the branch mainline in revision 961.
  • Revision ID: osullivan.padraig@gmail.com-20090321010223-j8cph7eeyt1u3xol
Fixed function object to ensure it correctly returns a boolean type since
memcmp returns an integer. Added some more comments.

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
 * their single parameter.
35
35
 */
36
36
 
37
 
#include "config.h"
 
37
#include "drizzled/global.h"
38
38
 
39
 
#include "drizzled/charset_info.h"
40
 
#include "drizzled/decimal.h"
 
39
#include "mystrings/m_ctype.h"
 
40
#include "drizzled/my_decimal.h"
41
41
#include "drizzled/calendar.h"
42
42
#include "drizzled/temporal.h"
 
43
#ifdef NOTYETIMPLEMENTED
 
44
#include "drizzled/temporal_interval.h"
 
45
#endif
43
46
#include "drizzled/temporal_format.h"
44
 
#include "drizzled/time_functions.h"
45
 
#include "time.h"
46
 
 
47
 
#include <time.h>
48
 
 
49
 
#include <cstdio>
 
47
 
50
48
#include <ostream>
51
49
#include <iomanip>
52
50
#include <vector>
53
51
#include <string.h>
54
52
 
 
53
/* time.h may already have been included in global.h, but we
 
54
   need to pick up the extra defs as well, after the global time.h */
 
55
#ifndef HAVE_DECL_TIMEGM
 
56
# include <gnulib/time.h>
 
57
#endif
 
58
 
 
59
extern std::vector<drizzled::TemporalFormat *> known_datetime_formats;
 
60
extern std::vector<drizzled::TemporalFormat *> known_date_formats;
 
61
extern std::vector<drizzled::TemporalFormat *> known_time_formats;
 
62
 
55
63
namespace drizzled 
56
64
{
57
65
 
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
 
 
62
66
Temporal::Temporal()
63
67
:
64
68
  _calendar(GREGORIAN)
81
85
      + _seconds);
82
86
}
83
87
 
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
 
 
122
88
void Temporal::set_epoch_seconds()
123
89
{
124
90
  /* 
242
208
 * This operator is called in the following situation:
243
209
 *
244
210
 * @code
245
 
 * Time lhs;
 
211
 * drizzled::Time lhs;
246
212
 * lhs.from_string("20:00:00");
247
 
 * Time rhs;
 
213
 * drizzled::Time rhs;
248
214
 * rhs.from_string("19:00:00");
249
215
 *
250
 
 * Time result= lhs - rhs;
 
216
 * drizzled::Time result= lhs - rhs;
251
217
 * @endcode
252
218
 *
253
219
 * @note
831
797
 
832
798
  return *this;
833
799
}
834
 
 
 
800
#ifdef NOTYETIMPLEMENTED
 
801
Date& Date::operator+=(const TemporalIntervalYear &rhs)
 
802
{
 
803
  /* Simple one...add the years and adjust for any leaps */
 
804
  int64_t new_years= _years;
 
805
  new_years+= rhs._years;
 
806
  if (new_years > DRIZZLE_MAX_YEARS_SQL)
 
807
  {
 
808
    /* 
 
809
     * Set everything to zero. We got an overflow.
 
810
     * @TODO Exceptions would be great here...
 
811
     */
 
812
    _reset();
 
813
    _overflow= true;
 
814
    return *this;
 
815
  }
 
816
  _years= (uint32_t) new_years;
 
817
  if (_months == 2 && _days == 29 && days_in_gregorian_year_month(_years, _months) != 366)
 
818
    _days= 28;
 
819
  return *this;
 
820
 
821
 
 
822
Date& Date::operator-=(const TemporalIntervalYear &rhs)
 
823
{
 
824
  /* Simple one...subtract the years and adjust for any leaps */
 
825
  int64_t new_years= _years;
 
826
  new_years-= rhs._years;
 
827
  if (new_years < 0)
 
828
  {
 
829
    /* 
 
830
     * Set everything to zero. We got an overflow.
 
831
     * @TODO Exceptions would be great here...
 
832
     */
 
833
    _reset();
 
834
    _overflow= true;
 
835
    return *this;
 
836
  }
 
837
  _years= (uint32_t) new_years;
 
838
  if (_months == 2 && _days == 29 && days_in_gregorian_year_month(_years, _months) != 366)
 
839
    _days= 28;
 
840
  return *this;
 
841
 
842
 
 
843
Date& Date::operator+=(const TemporalIntervalDayOrWeek &rhs)
 
844
{
 
845
  /* Simple one...add the days */
 
846
  int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, _days) + rhs._days;
 
847
  gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
 
848
  return *this;
 
849
 
850
 
 
851
Date& Date::operator-=(const TemporalIntervalDayOrWeek &rhs)
 
852
{
 
853
  /* Simple one...subtract the days */
 
854
  int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, _days) - rhs._days;
 
855
  gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
 
856
  return *this;
 
857
 
858
 
 
859
Date& Date::operator+=(const TemporalIntervalYearMonth &rhs)
 
860
{
 
861
  /* Simple one...add the months in the period adjust */
 
862
  int64_t period= (_years * 12) + (rhs._years * 12) + (_months - 1) + rhs._months;
 
863
  int64_t new_years= (period / 12);
 
864
  if (new_years > DRIZZLE_MAX_YEARS_SQL)
 
865
  {
 
866
    /* 
 
867
     * Set everything to zero. We got an overflow.
 
868
     * @TODO Exceptions would be great here...
 
869
     */
 
870
    _reset();
 
871
    _overflow= true;
 
872
    return *this;
 
873
  }
 
874
  _years= (uint32_t) new_years;
 
875
  _months= (uint32_t) (period % 12) + 1;
 
876
  
 
877
  /* Adjust day if the new month doesn't have enough days */
 
878
  uint32_t days_in_new_month= days_in_gregorian_year_month(_years, _months);
 
879
  if (_days > days_in_new_month)
 
880
    _days= days_in_new_month;
 
881
  return *this;
 
882
 
883
 
 
884
Date& Date::operator-=(const TemporalIntervalYearMonth &rhs)
 
885
{
 
886
  /* Simple one...subtract the months in the period and adjust */
 
887
  int64_t period= (_years * 12) - (rhs._years * 12) + (_months - 1) - rhs._months;
 
888
  int64_t new_years= (period / 12);
 
889
  if (new_years < 0)
 
890
  {
 
891
    /* 
 
892
     * Set everything to zero. We got an overflow.
 
893
     * @TODO Exceptions would be great here...
 
894
     */
 
895
    _reset();
 
896
    _overflow= true;
 
897
    return *this;
 
898
  }
 
899
  _years= (uint32_t) (period / 12);
 
900
  _months= (uint32_t) (period % 12) + 1;
 
901
  
 
902
  /* Adjust day if the new month doesn't have enough days */
 
903
  uint32_t days_in_new_month= days_in_gregorian_year_month(_years, _months);
 
904
  if (_days > days_in_new_month)
 
905
    _days= days_in_new_month;
 
906
  return *this;
 
907
 
908
 
 
909
Date& Date::operator+=(const TemporalIntervalDayOrLess &rhs)
 
910
{
 
911
  /* 
 
912
   * Convert the temporal and the interval into a number of 
 
913
   * microseconds, then add them together and convert the
 
914
   * resulting microseconds back into a broken-down temporal
 
915
   * component.
 
916
   */
 
917
  int64_t new_seconds;
 
918
  int64_t new_microseconds;
 
919
  int64_t extra_sec;
 
920
  int64_t new_days;
 
921
  new_microseconds= _useconds + rhs._useconds;
 
922
  extra_sec= new_microseconds / INT64_C(1000000);
 
923
  new_microseconds= new_microseconds % INT64_C(1000000);
 
924
 
 
925
  new_seconds= ((_days - 1) * 3600 * 24) + (_hours * 3600) + (_minutes * 60) + _seconds;
 
926
  new_seconds+= (rhs._days * 3600 * 24) + (rhs._hours * 3600) + (rhs._minutes * 60) + rhs._seconds;
 
927
  new_seconds+= extra_sec;
 
928
 
 
929
  if (new_microseconds < 0)
 
930
  {
 
931
    new_microseconds+= INT64_C(1000000);
 
932
    new_seconds--;
 
933
  }
 
934
  
 
935
  new_days= new_seconds / (3600 * 24L);
 
936
  new_seconds-= new_days * 3600 * 24L;
 
937
  if (new_seconds < 0)
 
938
  {
 
939
    new_days--;
 
940
    new_seconds+= 3600 * 24L;
 
941
  }
 
942
  _useconds= (uint32_t) new_microseconds;
 
943
  _seconds= (uint32_t) (new_seconds % 60);
 
944
  _minutes= (uint32_t) ((new_seconds / 60) % 60);
 
945
  _hours= (uint32_t) (new_seconds / 3600);
 
946
  int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, 1) + new_days;
 
947
  gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
 
948
  return *this;
 
949
}
 
950
 
 
951
Date& Date::operator-=(const TemporalIntervalDayOrLess &rhs)
 
952
{
 
953
  /* 
 
954
   * Convert the temporal and the interval into a number of 
 
955
   * microseconds, then subtract them from each other and convert 
 
956
   * the resulting microseconds back into a broken-down temporal
 
957
   * component.
 
958
   */
 
959
  int64_t new_seconds;
 
960
  int64_t new_microseconds;
 
961
  int64_t extra_sec;
 
962
  int64_t new_days;
 
963
  new_microseconds= _useconds - rhs._useconds;
 
964
  extra_sec= new_microseconds / INT64_C(1000000);
 
965
  new_microseconds= new_microseconds % INT64_C(1000000);
 
966
 
 
967
  new_seconds= ((_days - 1) * 3600 * 24) + (_hours * 3600) + (_minutes * 60) + _seconds;
 
968
  new_seconds-= (rhs._days * 3600 * 24) + (rhs._hours * 3600) + (rhs._minutes * 60) + rhs._seconds;
 
969
  new_seconds+= extra_sec;
 
970
 
 
971
  if (new_microseconds < 0)
 
972
  {
 
973
    new_microseconds+= INT64_C(1000000);
 
974
    new_seconds--;
 
975
  }
 
976
  
 
977
  new_days= new_seconds / (3600 * 24L);
 
978
  new_seconds-= new_days * 3600 * 24L;
 
979
  if (new_seconds < 0)
 
980
  {
 
981
    new_days--;
 
982
    new_seconds+= 3600 * 24L;
 
983
  }
 
984
  _useconds= (uint32_t) new_microseconds;
 
985
  _seconds= (uint32_t) (new_seconds % 60);
 
986
  _minutes= (uint32_t) ((new_seconds / 60) % 60);
 
987
  _hours= (uint32_t) (new_seconds / 3600);
 
988
  int64_t julian_day= julian_day_number_from_gregorian_date(_years, _months, 1) + new_days;
 
989
  gregorian_date_from_julian_day_number(julian_day, &_years, &_months, &_days);
 
990
  return *this;
 
991
}
 
992
#endif /* NOTYETIMPLEMENTED */
835
993
/*
836
994
 * Comparison operators between a Date and a Timestamp
837
995
 */
863
1021
}
864
1022
bool Date::operator>(const Timestamp& rhs)
865
1023
{
866
 
  return ! (*this <= rhs);
 
1024
  return ! (*this < rhs);
867
1025
}
868
1026
bool Date::operator>=(const Timestamp& rhs)
869
1027
{
870
 
  return ! (*this < rhs);
 
1028
  return ! (*this <= rhs);
871
1029
}
872
1030
/*
873
1031
 * Comparison operators between a Timestamp and a Date
900
1058
}
901
1059
bool Timestamp::operator>(const Date& rhs)
902
1060
{
903
 
  return ! (*this <= rhs);
 
1061
  return ! (*this < rhs);
904
1062
}
905
1063
bool Timestamp::operator>=(const Date& rhs)
906
1064
{
907
 
  return ! (*this < rhs);
 
1065
  return ! (*this <= rhs);
908
1066
}
909
1067
/*
910
1068
 * Comparison operators between a Timestamp and a DateTime
953
1111
}
954
1112
bool Timestamp::operator>(const DateTime& rhs)
955
1113
{
956
 
  return ! (*this <= rhs);
 
1114
  return ! (*this < rhs);
957
1115
}
958
1116
bool Timestamp::operator>=(const DateTime& rhs)
959
1117
{
960
 
  return ! (*this < rhs);
 
1118
  return ! (*this <= rhs);
961
1119
}
962
1120
/*
963
1121
 * Comparison operators between two Timestamps
980
1138
}
981
1139
bool Timestamp::operator>(const Timestamp& rhs)
982
1140
{
983
 
  return ! (*this <= rhs);
 
1141
  return ! (*this < rhs);
984
1142
}
985
1143
bool Timestamp::operator>=(const Timestamp& rhs)
986
1144
{
987
 
  return ! (*this < rhs);
 
1145
  return ! (*this <= rhs);
988
1146
}
989
1147
 
990
1148
/**
1031
1189
    return is_valid();
1032
1190
}
1033
1191
 
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
 
1192
void Time::to_string(char *to, size_t *to_len) const
 
1193
{
 
1194
  *to_len= sprintf(to
 
1195
                 , "%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32
 
1196
                 , _hours
 
1197
                 , _minutes
 
1198
                 , _seconds);
 
1199
}
 
1200
 
 
1201
void Date::to_string(char *to, size_t *to_len) const
 
1202
{
 
1203
  *to_len= sprintf(to
 
1204
                 , "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
 
1205
                 , _years
 
1206
                 , _months
 
1207
                 , _days);
 
1208
}
 
1209
 
 
1210
void DateTime::to_string(char *to, size_t *to_len) const
1049
1211
{
1050
1212
  /* If the temporal has a microsecond component, use a slightly different output */
1051
1213
  if (_useconds == 0)
1052
1214
  {
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);
 
1215
    *to_len= sprintf(to
 
1216
                  , "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32 " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32
 
1217
                  , _years
 
1218
                  , _months
 
1219
                  , _days
 
1220
                  , _hours
 
1221
                  , _minutes
 
1222
                  , _seconds);
1058
1223
  }
1059
1224
  else
1060
1225
  {
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);
 
1226
    *to_len= sprintf(to
 
1227
                  , "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32 " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32
 
1228
                  , _years
 
1229
                  , _months
 
1230
                  , _days
 
1231
                  , _hours
 
1232
                  , _minutes
 
1233
                  , _seconds
 
1234
                  , _useconds);
1066
1235
  }
1067
1236
}
1068
1237
 
1069
 
int MicroTimestamp::to_string(char *to, size_t to_len) const
 
1238
void MicroTimestamp::to_string(char *to, size_t *to_len) const
1070
1239
{
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);
 
1240
  *to_len= sprintf(to
 
1241
                 , "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32 " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32
 
1242
                 , _years
 
1243
                 , _months
 
1244
                 , _days
 
1245
                 , _hours
 
1246
                 , _minutes
 
1247
                 , _seconds
 
1248
                 , _useconds);
1076
1249
}
1077
1250
 
1078
1251
void Time::to_decimal(my_decimal *to) const
1185
1358
bool Time::from_int32_t(const int32_t from)
1186
1359
{
1187
1360
  uint32_t copy_from= (uint32_t) from;
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 */
 
1361
  _hours= copy_from % INT32_C(10000);
 
1362
  _minutes= copy_from % INT32_C(100);
 
1363
  _seconds= copy_from & 3; /* Masks off all but last 2 digits */
1191
1364
  return is_valid();
1192
1365
}
1193
1366
 
1196
1369
 * This is pretty much a hack for usability, but keeps us compatible
1197
1370
 * with MySQL.
1198
1371
 */
1199
 
bool DateTime::from_int64_t(const int64_t from, bool convert)
 
1372
bool DateTime::from_int64_t(const int64_t from)
1200
1373
{
1201
1374
  int64_t copy_from= from;
1202
1375
  int64_t part1;
1205
1378
  if (copy_from == 0LL)
1206
1379
    return false;
1207
1380
 
1208
 
  if (convert && copy_from < 10000101000000LL)
 
1381
  if (copy_from < 10000101000000LL)
1209
1382
  {
1210
1383
    if (copy_from < 101)
1211
1384
      return false;
1226
1399
    else if (copy_from <  DRIZZLE_YY_PART_YEAR * 10000000000LL + 101000000LL)
1227
1400
      return false;
1228
1401
    else if (copy_from <= 991231235959LL)
1229
 
      copy_from= copy_from + 19000000000000LL;    /* YYMMDDHHMMSS, 1970-1999 */
 
1402
      copy_from= copy_from + 19000000000000LL;          /* YYMMDDHHMMSS, 1970-1999 */
1230
1403
  }
1231
1404
 
1232
1405
  part1= (int64_t) (copy_from / 1000000LL);
1351
1524
void Date::to_time_t(time_t *to) const
1352
1525
{
1353
1526
  if (in_unix_epoch())
1354
 
  {
1355
1527
    *to= _epoch_seconds;
1356
 
  }
1357
 
  else
1358
 
    *to= 0;
 
1528
  *to= 0;
1359
1529
}
1360
1530
 
1361
1531
void Timestamp::to_time_t(time_t *to) const
1405
1575
bool Timestamp::is_valid() const
1406
1576
{
1407
1577
  return DateTime::is_valid() 
1408
 
      && in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds)
1409
 
      && (_seconds <= 59);
 
1578
      && in_unix_epoch_range(_years, _months, _days, _hours, _minutes, _seconds);
1410
1579
}
1411
1580
 
1412
1581
bool MicroTimestamp::is_valid() const
1422
1591
      && (_nseconds <= UINT32_C(999999999));
1423
1592
}
1424
1593
 
1425
 
} /* namespace drizzled */
 
1594
} /* end namespace drizzled */