00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <drizzled/function/time/timestamp_diff.h>
00023 #include <drizzled/time_functions.h>
00024
00025 namespace drizzled
00026 {
00027
00028 int64_t Item_func_timestamp_diff::val_int()
00029 {
00030 type::Time ltime1, ltime2;
00031 int64_t seconds;
00032 long microseconds;
00033 long months= 0;
00034 int neg= 1;
00035
00036 null_value= 0;
00037 if (args[0]->get_date(ltime1, TIME_NO_ZERO_DATE) ||
00038 args[1]->get_date(ltime2, TIME_NO_ZERO_DATE))
00039 goto null_date;
00040
00041 if (calc_time_diff(<ime2,<ime1, 1,
00042 &seconds, µseconds))
00043 neg= -1;
00044
00045 if (int_type == INTERVAL_YEAR ||
00046 int_type == INTERVAL_QUARTER ||
00047 int_type == INTERVAL_MONTH)
00048 {
00049 uint32_t year_beg, year_end, month_beg, month_end, day_beg, day_end;
00050 uint32_t years= 0;
00051 uint32_t second_beg, second_end, microsecond_beg, microsecond_end;
00052
00053 if (neg == -1)
00054 {
00055 year_beg= ltime2.year;
00056 year_end= ltime1.year;
00057 month_beg= ltime2.month;
00058 month_end= ltime1.month;
00059 day_beg= ltime2.day;
00060 day_end= ltime1.day;
00061 second_beg= ltime2.hour * 3600 + ltime2.minute * 60 + ltime2.second;
00062 second_end= ltime1.hour * 3600 + ltime1.minute * 60 + ltime1.second;
00063 microsecond_beg= ltime2.second_part;
00064 microsecond_end= ltime1.second_part;
00065 }
00066 else
00067 {
00068 year_beg= ltime1.year;
00069 year_end= ltime2.year;
00070 month_beg= ltime1.month;
00071 month_end= ltime2.month;
00072 day_beg= ltime1.day;
00073 day_end= ltime2.day;
00074 second_beg= ltime1.hour * 3600 + ltime1.minute * 60 + ltime1.second;
00075 second_end= ltime2.hour * 3600 + ltime2.minute * 60 + ltime2.second;
00076 microsecond_beg= ltime1.second_part;
00077 microsecond_end= ltime2.second_part;
00078 }
00079
00080
00081 years= year_end - year_beg;
00082 if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
00083 years-= 1;
00084
00085
00086 months= 12*years;
00087 if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
00088 months+= 12 - (month_beg - month_end);
00089 else
00090 months+= (month_end - month_beg);
00091
00092 if (day_end < day_beg)
00093 months-= 1;
00094 else if ((day_end == day_beg) &&
00095 ((second_end < second_beg) ||
00096 (second_end == second_beg && microsecond_end < microsecond_beg)))
00097 months-= 1;
00098 }
00099
00100 switch (int_type) {
00101 case INTERVAL_YEAR:
00102 return months/12*neg;
00103 case INTERVAL_QUARTER:
00104 return months/3*neg;
00105 case INTERVAL_MONTH:
00106 return months*neg;
00107 case INTERVAL_WEEK:
00108 return seconds/86400L/7L*neg;
00109 case INTERVAL_DAY:
00110 return seconds/86400L*neg;
00111 case INTERVAL_HOUR:
00112 return seconds/3600L*neg;
00113 case INTERVAL_MINUTE:
00114 return seconds/60L*neg;
00115 case INTERVAL_SECOND:
00116 return seconds*neg;
00117 case INTERVAL_MICROSECOND:
00118
00119
00120
00121
00122 return (seconds*1000000L+microseconds)*neg;
00123 default:
00124 break;
00125 }
00126
00127 null_date:
00128 null_value=1;
00129 return 0;
00130 }
00131
00132
00133 void Item_func_timestamp_diff::print(String *str)
00134 {
00135 str->append(func_name());
00136 str->append('(');
00137
00138 switch (int_type) {
00139 case INTERVAL_YEAR:
00140 str->append(STRING_WITH_LEN("YEAR"));
00141 break;
00142 case INTERVAL_QUARTER:
00143 str->append(STRING_WITH_LEN("QUARTER"));
00144 break;
00145 case INTERVAL_MONTH:
00146 str->append(STRING_WITH_LEN("MONTH"));
00147 break;
00148 case INTERVAL_WEEK:
00149 str->append(STRING_WITH_LEN("WEEK"));
00150 break;
00151 case INTERVAL_DAY:
00152 str->append(STRING_WITH_LEN("DAY"));
00153 break;
00154 case INTERVAL_HOUR:
00155 str->append(STRING_WITH_LEN("HOUR"));
00156 break;
00157 case INTERVAL_MINUTE:
00158 str->append(STRING_WITH_LEN("MINUTE"));
00159 break;
00160 case INTERVAL_SECOND:
00161 str->append(STRING_WITH_LEN("SECOND"));
00162 break;
00163 case INTERVAL_MICROSECOND:
00164 str->append(STRING_WITH_LEN("SECOND_FRAC"));
00165 break;
00166 default:
00167 break;
00168 }
00169
00170 for (uint32_t i=0 ; i < 2 ; i++)
00171 {
00172 str->append(',');
00173 args[i]->print(str);
00174 }
00175 str->append(')');
00176 }
00177
00178 }