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