1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008-2009 Sun Microsystems
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
/* Functions to handle date and time */
24
#include "drizzled/error.h"
25
#include "drizzled/util/test.h"
26
#include "drizzled/tztime.h"
27
#include "drizzled/session.h"
28
#include "drizzled/time_functions.h"
33
/* Some functions to calculate dates */
36
int calc_weekday(long daynr,bool sunday_first_day_of_week)
38
return ((int) ((daynr + 5L + (sunday_first_day_of_week ? 1L : 0L)) % 7));
42
uint32_t calc_week(DRIZZLE_TIME *l_time, uint32_t week_behaviour, uint32_t *year)
45
uint32_t daynr= calc_daynr(l_time->year,l_time->month,l_time->day);
46
uint32_t first_daynr= calc_daynr(l_time->year,1,1);
47
bool monday_first= test(week_behaviour & WEEK_MONDAY_FIRST);
48
bool week_year= test(week_behaviour & WEEK_YEAR);
49
bool first_weekday= test(week_behaviour & WEEK_FIRST_WEEKDAY);
51
uint32_t weekday= calc_weekday(first_daynr, !monday_first);
54
if (l_time->month == 1 && l_time->day <= 7-weekday)
56
if ((!week_year) && ((first_weekday && weekday != 0) || (!first_weekday && weekday >= 4)))
60
first_daynr-= (days=calc_days_in_year(*year));
61
weekday= (weekday + 53*7- days) % 7;
64
if ((first_weekday && weekday != 0) ||
65
(!first_weekday && weekday >= 4))
66
days= daynr - (first_daynr+ (7-weekday));
68
days= daynr - (first_daynr - weekday);
70
if (week_year && days >= 52*7)
72
weekday= (weekday + calc_days_in_year(*year)) % 7;
73
if ((!first_weekday && weekday < 4) || (first_weekday && weekday == 0))
83
void get_date_from_daynr(long daynr,
88
uint32_t year,temp,leap_day,day_of_year,days_in_year;
89
unsigned char *month_pos;
91
if (daynr <= 365L || daynr >= 3652500)
92
{ /* Fix if wrong daynr */
93
*ret_year= *ret_month = *ret_day =0;
97
year= (uint32_t) (daynr*100 / 36525L);
98
temp=(((year-1)/100+1)*3)/4;
99
day_of_year=(uint32_t) (daynr - (long) year * 365L) - (year-1)/4 +temp;
100
while (day_of_year > (days_in_year= calc_days_in_year(year)))
102
day_of_year-=days_in_year;
106
if (days_in_year == 366)
108
if (day_of_year > 31+28)
111
if (day_of_year == 31+28)
112
leap_day=1; /* Handle leapyears leapday */
116
for (month_pos= days_in_month ;
117
day_of_year > (uint32_t) *month_pos ;
118
day_of_year-= *(month_pos++), (*ret_month)++)
121
*ret_day=day_of_year+leap_day;
127
enum enum_drizzle_timestamp_type
128
str_to_datetime_with_warn(const char *str,
130
DRIZZLE_TIME *l_time,
134
Session *session= current_session;
135
enum enum_drizzle_timestamp_type ts_type;
137
ts_type= str_to_datetime(str, length, l_time,
138
(flags | (session->variables.sql_mode &
139
(MODE_INVALID_DATES |
140
MODE_NO_ZERO_DATE))),
142
if (was_cut || ts_type <= DRIZZLE_TIMESTAMP_ERROR)
143
make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
144
str, length, ts_type, NULL);
150
str_to_time_with_warn(const char *str, uint32_t length, DRIZZLE_TIME *l_time)
153
bool ret_val= str_to_time(str, length, l_time, &warning);
154
if (ret_val || warning)
155
make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
156
str, length, DRIZZLE_TIMESTAMP_TIME, NULL);
161
void localtime_to_TIME(DRIZZLE_TIME *to, struct tm *from)
165
to->year= (int) ((from->tm_year+1900) % 10000);
166
to->month= (int) from->tm_mon+1;
167
to->day= (int) from->tm_mday;
168
to->hour= (int) from->tm_hour;
169
to->minute= (int) from->tm_min;
170
to->second= (int) from->tm_sec;
173
void make_date(const DRIZZLE_TIME *l_time, String *str)
175
str->alloc(MAX_DATE_STRING_REP_LENGTH);
176
uint32_t length= (uint32_t) my_date_to_str(l_time, str->c_ptr());
178
str->set_charset(&my_charset_bin);
182
void make_datetime(const DRIZZLE_TIME *l_time, String *str)
184
str->alloc(MAX_DATE_STRING_REP_LENGTH);
185
uint32_t length= (uint32_t) my_datetime_to_str(l_time, str->c_ptr());
187
str->set_charset(&my_charset_bin);
191
void make_truncated_value_warning(Session *session,
192
DRIZZLE_ERROR::enum_warning_level level,
195
enum enum_drizzle_timestamp_type time_type,
196
const char *field_name)
198
char warn_buff[DRIZZLE_ERRMSG_SIZE];
199
const char *type_str;
200
CHARSET_INFO *cs= &my_charset_utf8_general_ci;
202
String str(buff,(uint32_t) sizeof(buff), system_charset_info);
203
str.copy(str_val, str_length, system_charset_info);
204
str[str_length]= 0; // Ensure we have end 0 for snprintf
207
case DRIZZLE_TIMESTAMP_DATE:
210
case DRIZZLE_TIMESTAMP_TIME:
213
case DRIZZLE_TIMESTAMP_DATETIME: // FALLTHROUGH
215
type_str= "datetime";
219
cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff),
220
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
221
type_str, str.c_ptr(), field_name,
222
(uint32_t) session->row_count);
225
if (time_type > DRIZZLE_TIMESTAMP_ERROR)
226
cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff),
227
ER(ER_TRUNCATED_WRONG_VALUE),
228
type_str, str.c_ptr());
230
cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff),
231
ER(ER_WRONG_VALUE), type_str, str.c_ptr());
233
push_warning(session, level,
234
ER_TRUNCATED_WRONG_VALUE, warn_buff);
239
calc_time_diff(DRIZZLE_TIME *l_time1, DRIZZLE_TIME *l_time2, int l_sign, int64_t *seconds_out,
240
long *microseconds_out)
244
int64_t microseconds;
247
We suppose that if first argument is DRIZZLE_TIMESTAMP_TIME
248
the second argument should be TIMESTAMP_TIME also.
249
We should check it before calc_time_diff call.
251
if (l_time1->time_type == DRIZZLE_TIMESTAMP_TIME) // Time value
252
days= (long)l_time1->day - l_sign * (long)l_time2->day;
255
days= calc_daynr((uint32_t) l_time1->year,
256
(uint32_t) l_time1->month,
257
(uint32_t) l_time1->day);
258
if (l_time2->time_type == DRIZZLE_TIMESTAMP_TIME)
259
days-= l_sign * (long)l_time2->day;
261
days-= l_sign*calc_daynr((uint32_t) l_time2->year,
262
(uint32_t) l_time2->month,
263
(uint32_t) l_time2->day);
266
microseconds= ((int64_t)days*86400L +
267
(int64_t)(l_time1->hour*3600L +
268
l_time1->minute*60L +
270
l_sign*(int64_t)(l_time2->hour*3600L +
271
l_time2->minute*60L +
272
l_time2->second)) * 1000000L +
273
(int64_t)l_time1->second_part -
274
l_sign*(int64_t)l_time2->second_part;
277
if (microseconds < 0)
279
microseconds= -microseconds;
282
*seconds_out= microseconds/1000000L;
283
*microseconds_out= (long) (microseconds%1000000L);
287
} /* namespace drizzled */