My Project
|
00001 /* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; version 2 of the License. 00006 00007 This program is distributed in the hope that it will be useful, 00008 but WITHOUT ANY WARRANTY; without even the implied warranty of 00009 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00010 GNU General Public License for more details. 00011 00012 You should have received a copy of the GNU General Public License 00013 along with this program; if not, write to the Free Software 00014 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00015 00016 #ifndef SQL_TIME_INCLUDED 00017 #define SQL_TIME_INCLUDED 00018 00019 #include "my_global.h" /* ulong */ 00020 #include "my_time.h" 00021 #include "mysql_time.h" /* timestamp_type */ 00022 #include "sql_error.h" /* Sql_condition */ 00023 #include "structs.h" /* INTERVAL */ 00024 00025 typedef enum enum_mysql_timestamp_type timestamp_type; 00026 typedef struct st_date_time_format DATE_TIME_FORMAT; 00027 typedef struct st_known_date_time_format KNOWN_DATE_TIME_FORMAT; 00028 00029 /* Flags for calc_week() function. */ 00030 #define WEEK_MONDAY_FIRST 1 00031 #define WEEK_YEAR 2 00032 #define WEEK_FIRST_WEEKDAY 4 00033 00034 ulong convert_period_to_month(ulong period); 00035 ulong convert_month_to_period(ulong month); 00036 void mix_date_and_time(MYSQL_TIME *ldate, const MYSQL_TIME *ltime); 00037 void get_date_from_daynr(long daynr,uint *year, uint *month, uint *day); 00038 my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, my_bool *not_exist); 00039 bool datetime_with_no_zero_in_date_to_timeval(THD *thd, const MYSQL_TIME *t, 00040 struct timeval *tm, 00041 int *warnings); 00042 bool datetime_to_timeval(THD *thd, const MYSQL_TIME *t, 00043 struct timeval *tm, int *warnings); 00044 bool str_to_datetime_with_warn(String *str, MYSQL_TIME *l_time, uint flags); 00045 bool my_decimal_to_datetime_with_warn(const my_decimal *decimal, 00046 MYSQL_TIME *ltime, uint flags); 00047 bool my_double_to_datetime_with_warn(double nr, MYSQL_TIME *ltime, uint flags); 00048 bool my_longlong_to_datetime_with_warn(longlong nr, 00049 MYSQL_TIME *ltime, uint flags); 00050 bool my_decimal_to_time_with_warn(const my_decimal *decimal, 00051 MYSQL_TIME *ltime); 00052 bool my_double_to_time_with_warn(double nr, MYSQL_TIME *ltime); 00053 bool my_longlong_to_time_with_warn(longlong nr, MYSQL_TIME *ltime); 00054 bool str_to_time_with_warn(String *str, MYSQL_TIME *l_time); 00055 void time_to_datetime(THD *thd, const MYSQL_TIME *tm, MYSQL_TIME *dt); 00056 inline void datetime_to_time(MYSQL_TIME *ltime) 00057 { 00058 ltime->year= ltime->month= ltime->day= 0; 00059 ltime->time_type= MYSQL_TIMESTAMP_TIME; 00060 } 00061 inline void datetime_to_date(MYSQL_TIME *ltime) 00062 { 00063 ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0; 00064 ltime->time_type= MYSQL_TIMESTAMP_DATE; 00065 } 00066 inline void date_to_datetime(MYSQL_TIME *ltime) 00067 { 00068 ltime->time_type= MYSQL_TIMESTAMP_DATETIME; 00069 } 00070 void make_truncated_value_warning(THD *thd, 00071 Sql_condition::enum_warning_level level, 00072 ErrConvString val, 00073 timestamp_type time_type, 00074 const char *field_name); 00075 inline void make_truncated_value_warning(ErrConvString val, 00076 timestamp_type time_type) 00077 { 00078 make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 00079 val, time_type, NullS); 00080 } 00081 extern DATE_TIME_FORMAT *date_time_format_make(timestamp_type format_type, 00082 const char *format_str, 00083 uint format_length); 00084 extern DATE_TIME_FORMAT *date_time_format_copy(THD *thd, 00085 DATE_TIME_FORMAT *format); 00086 const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format, 00087 timestamp_type type); 00088 void make_date(const DATE_TIME_FORMAT *format, const MYSQL_TIME *l_time, 00089 String *str); 00090 void make_time(const DATE_TIME_FORMAT *format, const MYSQL_TIME *l_time, 00091 String *str, uint dec); 00092 void make_datetime(const DATE_TIME_FORMAT *format, const MYSQL_TIME *l_time, 00093 String *str, uint dec); 00094 bool my_TIME_to_str(const MYSQL_TIME *ltime, String *str, uint dec); 00095 00096 /* MYSQL_TIME operations */ 00097 bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type, 00098 INTERVAL interval); 00099 bool calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2, 00100 int l_sign, longlong *seconds_out, long *microseconds_out); 00101 int my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b); 00102 void localtime_to_TIME(MYSQL_TIME *to, struct tm *from); 00103 void calc_time_from_sec(MYSQL_TIME *to, longlong seconds, long microseconds); 00104 uint calc_week(MYSQL_TIME *l_time, uint week_behaviour, uint *year); 00105 00106 int calc_weekday(long daynr,bool sunday_first_day_of_week); 00107 bool parse_date_time_format(timestamp_type format_type, 00108 const char *format, uint format_length, 00109 DATE_TIME_FORMAT *date_time_format); 00110 /* Character set-aware version of str_to_time() */ 00111 bool str_to_time(const CHARSET_INFO *cs, const char *str, uint length, 00112 MYSQL_TIME *l_time, uint flags, MYSQL_TIME_STATUS *status); 00113 static inline bool 00114 str_to_time(const String *str, MYSQL_TIME *ltime, uint flags, 00115 MYSQL_TIME_STATUS *status) 00116 { 00117 return str_to_time(str->charset(), str->ptr(), str->length(), 00118 ltime, flags, status); 00119 } 00120 00121 bool time_add_nanoseconds_with_round(MYSQL_TIME *ltime, uint nanoseconds, 00122 int *warnings); 00123 /* Character set-aware version of str_to_datetime() */ 00124 bool str_to_datetime(const CHARSET_INFO *cs, 00125 const char *str, uint length, 00126 MYSQL_TIME *l_time, uint flags, 00127 MYSQL_TIME_STATUS *status); 00128 static inline bool 00129 str_to_datetime(const String *str, MYSQL_TIME *ltime, uint flags, 00130 MYSQL_TIME_STATUS *status) 00131 { 00132 return str_to_datetime(str->charset(), str->ptr(), str->length(), 00133 ltime, flags, status); 00134 } 00135 00136 bool datetime_add_nanoseconds_with_round(MYSQL_TIME *ltime, 00137 uint nanoseconds, int *warnings); 00138 00139 /* convenience wrapper */ 00140 inline bool parse_date_time_format(timestamp_type format_type, 00141 DATE_TIME_FORMAT *date_time_format) 00142 { 00143 return parse_date_time_format(format_type, 00144 date_time_format->format.str, 00145 date_time_format->format.length, 00146 date_time_format); 00147 } 00148 00149 00150 extern DATE_TIME_FORMAT global_date_format; 00151 extern DATE_TIME_FORMAT global_datetime_format; 00152 extern DATE_TIME_FORMAT global_time_format; 00153 extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[]; 00154 extern LEX_STRING interval_type_to_name[]; 00155 00156 /* Date/time rounding and truncation functions */ 00157 inline long my_time_fraction_remainder(long nr, uint decimals) 00158 { 00159 DBUG_ASSERT(decimals <= DATETIME_MAX_DECIMALS); 00160 return nr % (long) log_10_int[DATETIME_MAX_DECIMALS - decimals]; 00161 } 00162 inline void my_time_trunc(MYSQL_TIME *ltime, uint decimals) 00163 { 00164 ltime->second_part-= my_time_fraction_remainder(ltime->second_part, decimals); 00165 } 00166 inline void my_datetime_trunc(MYSQL_TIME *ltime, uint decimals) 00167 { 00168 return my_time_trunc(ltime, decimals); 00169 } 00170 inline void my_timeval_trunc(struct timeval *tv, uint decimals) 00171 { 00172 tv->tv_usec-= my_time_fraction_remainder(tv->tv_usec, decimals); 00173 } 00174 bool my_time_round(MYSQL_TIME *ltime, uint decimals); 00175 bool my_datetime_round(MYSQL_TIME *ltime, uint decimals, int *warnings); 00176 bool my_timeval_round(struct timeval *tv, uint decimals); 00177 00178 00179 inline ulonglong TIME_to_ulonglong_datetime_round(const MYSQL_TIME *ltime) 00180 { 00181 // Catch simple cases 00182 if (ltime->second_part < 500000) 00183 return TIME_to_ulonglong_datetime(ltime); 00184 if (ltime->second < 59) 00185 return TIME_to_ulonglong_datetime(ltime) + 1; 00186 // Corner case e.g. 'YYYY-MM-DD hh:mm:59.5'. Proceed with slower method. 00187 int warnings= 0; 00188 MYSQL_TIME tmp= *ltime; 00189 my_datetime_round(&tmp, 0, &warnings); 00190 return TIME_to_ulonglong_datetime(&tmp);// + TIME_microseconds_round(ltime); 00191 } 00192 00193 00194 inline ulonglong TIME_to_ulonglong_time_round(const MYSQL_TIME *ltime) 00195 { 00196 if (ltime->second_part < 500000) 00197 return TIME_to_ulonglong_time(ltime); 00198 if (ltime->second < 59) 00199 return TIME_to_ulonglong_time(ltime) + 1; 00200 // Corner case e.g. 'hh:mm:59.5'. Proceed with slower method. 00201 MYSQL_TIME tmp= *ltime; 00202 my_time_round(&tmp, 0); 00203 return TIME_to_ulonglong_time(&tmp); 00204 } 00205 00206 00207 inline ulonglong TIME_to_ulonglong_round(const MYSQL_TIME *ltime) 00208 { 00209 switch (ltime->time_type) 00210 { 00211 case MYSQL_TIMESTAMP_TIME: 00212 return TIME_to_ulonglong_time_round(ltime); 00213 case MYSQL_TIMESTAMP_DATETIME: 00214 return TIME_to_ulonglong_datetime_round(ltime); 00215 case MYSQL_TIMESTAMP_DATE: 00216 return TIME_to_ulonglong_date(ltime); 00217 default: 00218 DBUG_ASSERT(0); 00219 return 0; 00220 } 00221 } 00222 00223 00224 inline double TIME_microseconds(const MYSQL_TIME *ltime) 00225 { 00226 return (double) ltime->second_part / 1000000; 00227 } 00228 00229 inline double TIME_to_double_datetime(const MYSQL_TIME *ltime) 00230 { 00231 return (double) TIME_to_ulonglong_datetime(ltime) + TIME_microseconds(ltime); 00232 } 00233 00234 00235 inline double TIME_to_double_time(const MYSQL_TIME *ltime) 00236 { 00237 return (double) TIME_to_ulonglong_time(ltime) + TIME_microseconds(ltime); 00238 } 00239 00240 00241 inline double TIME_to_double(const MYSQL_TIME *ltime) 00242 { 00243 return (double) TIME_to_ulonglong(ltime) + TIME_microseconds(ltime); 00244 } 00245 00246 00247 static inline bool 00248 check_fuzzy_date(const MYSQL_TIME *ltime, uint fuzzydate) 00249 { 00250 return !(fuzzydate & TIME_FUZZY_DATE) && (!ltime->month || !ltime->day); 00251 } 00252 00253 static inline bool 00254 non_zero_date(const MYSQL_TIME *ltime) 00255 { 00256 return ltime->year || ltime->month || ltime->day; 00257 } 00258 00259 static inline bool 00260 non_zero_time(const MYSQL_TIME *ltime) 00261 { 00262 return ltime->hour || ltime->minute || ltime->second || ltime->second_part; 00263 } 00264 00265 longlong TIME_to_longlong_packed(const MYSQL_TIME *tm, 00266 enum enum_field_types type); 00267 void TIME_from_longlong_packed(MYSQL_TIME *ltime, 00268 enum enum_field_types type, 00269 longlong packed_value); 00270 my_decimal *my_decimal_from_datetime_packed(my_decimal *dec, 00271 enum enum_field_types type, 00272 longlong packed_value); 00273 00274 longlong longlong_from_datetime_packed(enum enum_field_types type, 00275 longlong packed_value); 00276 00277 double double_from_datetime_packed(enum enum_field_types type, 00278 longlong packed_value); 00279 00280 static inline 00281 timestamp_type field_type_to_timestamp_type(enum enum_field_types type) 00282 { 00283 switch (type) 00284 { 00285 case MYSQL_TYPE_TIME: return MYSQL_TIMESTAMP_TIME; 00286 case MYSQL_TYPE_DATE: return MYSQL_TIMESTAMP_DATE; 00287 case MYSQL_TYPE_TIMESTAMP: 00288 case MYSQL_TYPE_DATETIME: return MYSQL_TIMESTAMP_DATETIME; 00289 default: return MYSQL_TIMESTAMP_NONE; 00290 } 00291 } 00292 #endif /* SQL_TIME_INCLUDED */