1 /*
2 * $Id: date.c,v 1.7 2001/02/13 23:38:05 danny Exp $
3 *
4 * Copyright � 1990, 1992, 1993, 2001 Free Software Foundation, Inc.
5 *
6 * This file is part of Oleo, the GNU Spreadsheet.
7 *
8 * Oleo is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * Oleo is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with Oleo; see the file COPYING. If not, write to
20 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #ifdef WITH_DMALLOC
28 #include <dmalloc.h>
29 #endif
30
31 #include "funcdef.h"
32 #include "sysdef.h"
33
34 #include "global.h"
35 #include "cell.h"
36 #include "eval.h"
37 #include "errors.h"
38
39 struct value
40 {
41 int type;
42 union vals x;
43 };
44
45 #define Float x.c_d
46 #define String x.c_s
47 #define Int x.c_l
48 #define Value x.c_i
49 #define Rng x.c_r
50
51
52
53 struct timeb;
54 extern time_t get_date (char *, struct timeb *);
55 extern time_t posixtime (char *);
56
57
58
59 /* These functions simply provide convenient syntax for expressing intervals
60 * of time.
61 */
62
63 static long
dt_hms_to_time(long h,long m,long s)64 dt_hms_to_time (long h, long m, long s)
65 {
66 return ((h * 60) + m) * 60 + s;
67 }
68
69 static long
dt_dhms_to_time(long d,long h,long m,long s)70 dt_dhms_to_time (long d, long h, long m, long s)
71 {
72 return ((((d * 24) + h) * 60) + m) * 60 + s;
73 }
74
75 static long
dt_time_to_d(long t)76 dt_time_to_d (long t)
77 {
78 return t / (60 * 60 * 24);
79 }
80
81 static long
dt_time_to_h(long t)82 dt_time_to_h (long t)
83 {
84 return (t / (60 * 60)) % 24;
85 }
86
87 static long
dt_time_to_m(long t)88 dt_time_to_m (long t)
89 {
90 return (t / 60) % 60;
91 }
92
93 static long
dt_time_to_s(long t)94 dt_time_to_s (long t)
95 {
96 return t % 60;
97 }
98
99
100
101 /* These relate time values to calendar dates using localtime, gmtime,
102 * strftime, mktime, etc.
103 */
104
105 /* mktime: */
106
107
108 static long
dt_ymd_dst(long y,long mo,long d,long dst)109 dt_ymd_dst (long y, long mo, long d, long dst)
110 {
111 struct tm tm;
112 tm.tm_year = y - 1900;
113 tm.tm_mon = mo;
114 tm.tm_mday = d;
115 tm.tm_hour = 0;
116 tm.tm_min = 0;
117 tm.tm_sec = 0;
118 tm.tm_isdst = dst;
119 return mktime (&tm);
120 }
121
122 static long
dt_ymd(long y,long mo,long d)123 dt_ymd (long y, long mo, long d)
124 {
125 return dt_ymd_dst (y, mo, d, -1);
126 }
127
128
129
130
131 #define TM_ACCESS(FN,FIELD,TMFN) \
132 static long \
133 FN (clk) \
134 long clk; \
135 { \
136 time_t t = (time_t)clk; \
137 struct tm * tm = TMFN(&t); \
138 return (long)tm->FIELD; \
139 }
140
141 #define TM_ACCESS_LOCAL(FN,FIELD) TM_ACCESS(FN, FIELD, localtime)
142
143 TM_ACCESS_LOCAL (dt_local_year, tm_year + 1900)
TM_ACCESS_LOCAL(dt_local_month,tm_mon)144 TM_ACCESS_LOCAL (dt_local_month, tm_mon)
145 TM_ACCESS_LOCAL (dt_local_date, tm_mday)
146 TM_ACCESS_LOCAL (dt_local_hour, tm_hour)
147 TM_ACCESS_LOCAL (dt_local_min, tm_min)
148 TM_ACCESS_LOCAL (dt_local_sec, tm_sec)
149 TM_ACCESS_LOCAL (dt_local_isdst, tm_isdst)
150 TM_ACCESS_LOCAL (dt_local_yday, tm_yday)
151 TM_ACCESS_LOCAL (dt_local_wday, tm_wday)
152
153
154 #define TM_ACCESS_GMT(FN,FIELD) TM_ACCESS(FN, FIELD, gmtime)
155
156 TM_ACCESS_GMT (dt_gmt_year, tm_year + 1900)
157 TM_ACCESS_GMT (dt_gmt_month, tm_mon)
158 TM_ACCESS_GMT (dt_gmt_date, tm_mday)
159 TM_ACCESS_GMT (dt_gmt_hour, tm_hour)
160 TM_ACCESS_GMT (dt_gmt_min, tm_min)
161 TM_ACCESS_GMT (dt_gmt_sec, tm_sec)
162 TM_ACCESS_GMT (dt_gmt_isdst, tm_isdst)
163 TM_ACCESS_GMT (dt_gmt_yday, tm_yday)
164 TM_ACCESS_GMT (dt_gmt_wday, tm_wday)
165
166
167
168 static char *
169 dt_strftime (char * format, long clk)
170 {
171 int len_used = 0;
172 int len = 32;
173 char * buf = (char *)ck_malloc (len);
174 time_t ck = (time_t)clk;
175 struct tm * tm = localtime (&ck);
176 while (!len_used)
177 {
178 len *= 2;
179 buf = (char *)ck_remalloc (buf, len);
180 len_used = strftime (buf, len - 1, format, tm);
181 }
182 if (len - 1 > len_used)
183 buf = (char *)ck_remalloc (buf, len_used + 1);
184 buf [len_used] = 0;
185 return buf;
186 }
187
188
189
190 static long
dt_get_date(char * date)191 dt_get_date (char * date)
192 {
193 return get_date (date, NULL);
194 }
195
196 static long
dt_posix_date(char * date)197 dt_posix_date (char * date)
198 {
199 return posixtime (date);
200 }
201
202
203
204 static void
205 l_l (fn, p)
206 long (*fn)();
207 struct value * p;
208 {
209 p[0].Int = fn (p->Int);
210 }
211
212 static void
213 l_lll (fn, p)
214 long (*fn)();
215 struct value * p;
216 {
217 p[0].Int = fn (p[0].Int, p[1].Int, p[2].Int);
218 }
219
220 static void
221 l_llll (fn, p)
222 long (*fn)();
223 struct value * p;
224 {
225 p[0].Int = fn (p[0].Int, p[1].Int, p[2].Int, p[3].Int);
226 }
227
228 static void
229 l_s (fn, p)
230 long (*fn)();
231 struct value * p;
232 {
233 p[0].Int = fn (p[0].String);
234 p[0].type = TYP_INT;
235 }
236
237
238
239 #define CALLER(FN,CALL,VIA) static void FN (p) struct value * p; { VIA(CALL,p); }
240
241 CALLER(do_hms_to_time, dt_hms_to_time, l_lll)
242 CALLER(do_dhms_to_time, dt_dhms_to_time, l_llll)
243 CALLER(do_time_to_d, dt_time_to_d, l_l)
244 CALLER(do_time_to_h, dt_time_to_h, l_l)
245 CALLER(do_time_to_m, dt_time_to_m, l_l)
246 CALLER(do_time_to_s, dt_time_to_s, l_l)
247 CALLER(do_ymd_dst, dt_ymd_dst, l_llll)
248 CALLER(do_ymd, dt_ymd, l_lll)
249 CALLER(do_local_year, dt_local_year, l_l)
250 CALLER(do_local_month, dt_local_month, l_l)
251 CALLER(do_local_date, dt_local_date, l_l)
252 CALLER(do_local_hour, dt_local_hour, l_l)
253 CALLER(do_local_min, dt_local_min, l_l)
254 CALLER(do_local_sec, dt_local_sec, l_l)
255 CALLER(do_local_isdst, dt_local_isdst, l_l)
256 CALLER(do_local_yday, dt_local_yday, l_l)
257 CALLER(do_local_wday, dt_local_wday, l_l)
258 CALLER(do_gmt_year, dt_gmt_year, l_l)
259 CALLER(do_gmt_month, dt_gmt_month, l_l)
260 CALLER(do_gmt_date, dt_gmt_date, l_l)
261 CALLER(do_gmt_hour, dt_gmt_hour, l_l)
262 CALLER(do_gmt_min, dt_gmt_min, l_l)
263 CALLER(do_gmt_sec, dt_gmt_sec, l_l)
264 CALLER(do_gmt_isdst, dt_gmt_isdst, l_l)
265 CALLER(do_gmt_yday, dt_gmt_yday, l_l)
266 CALLER(do_gmt_wday, dt_gmt_wday, l_l)
267 CALLER(do_get_date, dt_get_date, l_s)
268 CALLER(do_posix_date, dt_posix_date, l_s)
269
270
271
272 void
273 do_strftime (p)
274 struct value * p;
275 {
276 p[0].String = dt_strftime (p[0].String, p[1].Int);
277 }
278
279
280
281
282 struct function date_funs[] =
283 {
284 {C_FN3, X_A3, "III", do_hms_to_time, "hms_to_time"}, /* 1 */
285 {C_FN4, X_A4, "IIII", do_dhms_to_time, "dhms_to_time"}, /* 2 */
286 {C_FN1, X_A1, "I", do_time_to_d, "time_to_d"}, /* 3 */
287 {C_FN1, X_A1, "I", do_time_to_h, "time_to_h"}, /* 4 */
288 {C_FN1, X_A1, "I", do_time_to_m, "time_to_m"}, /* 5 */
289 {C_FN1, X_A1, "I", do_time_to_s, "time_to_s"}, /* 6 */
290 {C_FN3, X_A3, "III", do_ymd, "ymd"}, /* 7 */
291 {C_FN4, X_A4, "IIII", do_ymd_dst, "ymd_dst"}, /* 8 */
292 {C_FN1, X_A1, "I", do_local_year, "local_year"}, /* 9 */
293 {C_FN1, X_A1, "I", do_local_month, "local_month"}, /* 10 */
294 {C_FN1, X_A1, "I", do_local_date, "local_date"}, /* 11 */
295 {C_FN1, X_A1, "I", do_local_hour, "local_hour"}, /* 12 */
296 {C_FN1, X_A1, "I", do_local_min, "local_min"}, /* 13 */
297 {C_FN1, X_A1, "I", do_local_sec, "local_sec"}, /* 14 */
298 {C_FN1, X_A1, "I", do_local_isdst, "local_isdst"}, /* 15 */
299 {C_FN1, X_A1, "I", do_local_yday, "local_yday"}, /* 16 */
300 {C_FN1, X_A1, "I", do_local_wday, "local_wday"}, /* 17 */
301 {C_FN1, X_A1, "I", do_gmt_year, "gmt_year"}, /* 18 */
302 {C_FN1, X_A1, "I", do_gmt_month, "gmt_month"}, /* 19 */
303 {C_FN1, X_A1, "I", do_gmt_date, "gmt_date"}, /* 20 */
304 {C_FN1, X_A1, "I", do_gmt_hour, "gmt_hour"}, /* 21 */
305 {C_FN1, X_A1, "I", do_gmt_min, "gmt_min"}, /* 22 */
306 {C_FN1, X_A1, "I", do_gmt_sec, "gmt_sec"}, /* 23 */
307 {C_FN1, X_A1, "I", do_gmt_isdst, "gmt_isdst"}, /* 24 */
308 {C_FN1, X_A1, "I", do_gmt_yday, "gmt_yday"}, /* 25 */
309 {C_FN1, X_A1, "I", do_gmt_wday, "gmt_wday"}, /* 26 */
310 {C_FN1, X_A1, "S", do_get_date, "get_date"}, /* 27 */
311 {C_FN1, X_A1, "S", do_posix_date, "posix_date"}, /* 28 */
312 {C_FN2, X_A2, "SI", do_strftime, "strftime"}, /* 29 */
313 {0, 0, "", 0, 0}
314 };
315
init_date_function_count(void)316 int init_date_function_count(void)
317 {
318 return sizeof(date_funs) / sizeof(struct function) - 1;
319 }
320