xref: /PHP-5.5/ext/date/lib/timelib.c (revision 912e42fc)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2015 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Derick Rethans <derick@derickrethans.nl>                    |
16    +----------------------------------------------------------------------+
17  */
18 
19 /* $Id$ */
20 
21 #include "timelib.h"
22 #include <ctype.h>
23 #include <math.h>
24 
25 #define TIMELIB_TIME_FREE(m) 	\
26 	if (m) {		\
27 		free(m);	\
28 		m = NULL;	\
29 	}			\
30 
31 #define TIMELIB_LLABS(y) (y < 0 ? (y * -1) : y)
32 
33 #define HOUR(a) (int)(a * 60)
34 
timelib_time_ctor(void)35 timelib_time* timelib_time_ctor(void)
36 {
37 	timelib_time *t;
38 	t = calloc(1, sizeof(timelib_time));
39 
40 	return t;
41 }
42 
timelib_rel_time_ctor(void)43 timelib_rel_time* timelib_rel_time_ctor(void)
44 {
45 	timelib_rel_time *t;
46 	t = calloc(1, sizeof(timelib_rel_time));
47 
48 	return t;
49 }
50 
timelib_time_clone(timelib_time * orig)51 timelib_time* timelib_time_clone(timelib_time *orig)
52 {
53 	timelib_time *tmp = timelib_time_ctor();
54 	memcpy(tmp, orig, sizeof(timelib_time));
55 	if (orig->tz_abbr) {
56 		tmp->tz_abbr = strdup(orig->tz_abbr);
57 	}
58 	if (orig->tz_info) {
59 		tmp->tz_info = orig->tz_info;
60 	}
61 	return tmp;
62 }
63 
timelib_rel_time_clone(timelib_rel_time * rel)64 timelib_rel_time* timelib_rel_time_clone(timelib_rel_time *rel)
65 {
66 	timelib_rel_time *tmp = timelib_rel_time_ctor();
67 	memcpy(tmp, rel, sizeof(timelib_rel_time));
68 	return tmp;
69 }
70 
timelib_time_tz_abbr_update(timelib_time * tm,char * tz_abbr)71 void timelib_time_tz_abbr_update(timelib_time* tm, char* tz_abbr)
72 {
73 	unsigned int i;
74 
75 	TIMELIB_TIME_FREE(tm->tz_abbr);
76 	tm->tz_abbr = strdup(tz_abbr);
77 	for (i = 0; i < strlen(tz_abbr); i++) {
78 		tm->tz_abbr[i] = toupper(tz_abbr[i]);
79 	}
80 }
81 
timelib_time_dtor(timelib_time * t)82 void timelib_time_dtor(timelib_time* t)
83 {
84 	TIMELIB_TIME_FREE(t->tz_abbr);
85 	TIMELIB_TIME_FREE(t);
86 }
87 
timelib_rel_time_dtor(timelib_rel_time * t)88 void timelib_rel_time_dtor(timelib_rel_time* t)
89 {
90 	TIMELIB_TIME_FREE(t);
91 }
92 
timelib_time_offset_ctor(void)93 timelib_time_offset* timelib_time_offset_ctor(void)
94 {
95 	timelib_time_offset *t;
96 	t = calloc(1, sizeof(timelib_time_offset));
97 
98 	return t;
99 }
100 
timelib_time_offset_dtor(timelib_time_offset * t)101 void timelib_time_offset_dtor(timelib_time_offset* t)
102 {
103 	TIMELIB_TIME_FREE(t->abbr);
104 	TIMELIB_TIME_FREE(t);
105 }
106 
timelib_tzinfo_ctor(char * name)107 timelib_tzinfo* timelib_tzinfo_ctor(char *name)
108 {
109 	timelib_tzinfo *t;
110 	t = calloc(1, sizeof(timelib_tzinfo));
111 	t->name = strdup(name);
112 
113 	return t;
114 }
115 
timelib_tzinfo_clone(timelib_tzinfo * tz)116 timelib_tzinfo *timelib_tzinfo_clone(timelib_tzinfo *tz)
117 {
118 	timelib_tzinfo *tmp = timelib_tzinfo_ctor(tz->name);
119 	tmp->bit32.ttisgmtcnt = tz->bit32.ttisgmtcnt;
120 	tmp->bit32.ttisstdcnt = tz->bit32.ttisstdcnt;
121 	tmp->bit32.leapcnt = tz->bit32.leapcnt;
122 	tmp->bit32.timecnt = tz->bit32.timecnt;
123 	tmp->bit32.typecnt = tz->bit32.typecnt;
124 	tmp->bit32.charcnt = tz->bit32.charcnt;
125 
126 	tmp->trans = (int32_t *) malloc(tz->bit32.timecnt * sizeof(int32_t));
127 	tmp->trans_idx = (unsigned char*) malloc(tz->bit32.timecnt * sizeof(unsigned char));
128 	memcpy(tmp->trans, tz->trans, tz->bit32.timecnt * sizeof(int32_t));
129 	memcpy(tmp->trans_idx, tz->trans_idx, tz->bit32.timecnt * sizeof(unsigned char));
130 
131 	tmp->type = (ttinfo*) malloc(tz->bit32.typecnt * sizeof(struct ttinfo));
132 	memcpy(tmp->type, tz->type, tz->bit32.typecnt * sizeof(struct ttinfo));
133 
134 	tmp->timezone_abbr = (char*) malloc(tz->bit32.charcnt);
135 	memcpy(tmp->timezone_abbr, tz->timezone_abbr, tz->bit32.charcnt);
136 
137 	tmp->leap_times = (tlinfo*) malloc(tz->bit32.leapcnt * sizeof(tlinfo));
138 	memcpy(tmp->leap_times, tz->leap_times, tz->bit32.leapcnt * sizeof(tlinfo));
139 
140 	return tmp;
141 }
142 
timelib_tzinfo_dtor(timelib_tzinfo * tz)143 void timelib_tzinfo_dtor(timelib_tzinfo *tz)
144 {
145 	TIMELIB_TIME_FREE(tz->name);
146 	TIMELIB_TIME_FREE(tz->trans);
147 	TIMELIB_TIME_FREE(tz->trans_idx);
148 	TIMELIB_TIME_FREE(tz->type);
149 	TIMELIB_TIME_FREE(tz->timezone_abbr);
150 	TIMELIB_TIME_FREE(tz->leap_times);
151 	TIMELIB_TIME_FREE(tz->location.comments);
152 	TIMELIB_TIME_FREE(tz);
153 	tz = NULL;
154 }
155 
timelib_get_tz_abbr_ptr(timelib_time * t)156 char *timelib_get_tz_abbr_ptr(timelib_time *t)
157 {
158 	if (!t->sse_uptodate) {
159 		timelib_update_ts(t, NULL);
160 	};
161 	return t->tz_abbr;
162 }
163 
timelib_error_container_dtor(timelib_error_container * errors)164 void timelib_error_container_dtor(timelib_error_container *errors)
165 {
166 	int i;
167 
168 	for (i = 0; i < errors->warning_count; i++) {
169 		free(errors->warning_messages[i].message);
170 	}
171 	free(errors->warning_messages);
172 	for (i = 0; i < errors->error_count; i++) {
173 		free(errors->error_messages[i].message);
174 	}
175 	free(errors->error_messages);
176 	free(errors);
177 }
178 
timelib_date_to_int(timelib_time * d,int * error)179 signed long timelib_date_to_int(timelib_time *d, int *error)
180 {
181 	timelib_sll ts;
182 
183 	ts = d->sse;
184 
185 	if (ts < LONG_MIN || ts > LONG_MAX) {
186 		if (error) {
187 			*error = 1;
188 		}
189 		return 0;
190 	}
191 	if (error) {
192 		*error = 0;
193 	}
194 	return (signed long) d->sse;
195 }
196 
timelib_decimal_hour_to_hms(double h,int * hour,int * min,int * sec)197 void timelib_decimal_hour_to_hms(double h, int *hour, int *min, int *sec)
198 {
199 	*hour = floor(h);
200 	*min =  floor((h - *hour) * 60);
201 	*sec =  (h - *hour - ((float) *min / 60)) * 3600;
202 }
203 
timelib_dump_date(timelib_time * d,int options)204 void timelib_dump_date(timelib_time *d, int options)
205 {
206 	if ((options & 2) == 2) {
207 		printf("TYPE: %d ", d->zone_type);
208 	}
209 	printf("TS: %lld | %s%04lld-%02lld-%02lld %02lld:%02lld:%02lld",
210 		d->sse, d->y < 0 ? "-" : "", TIMELIB_LLABS(d->y), d->m, d->d, d->h, d->i, d->s);
211 	if (d->f > +0.0) {
212 		printf(" %.5f", d->f);
213 	}
214 
215 	if (d->is_localtime) {
216 		switch (d->zone_type) {
217 			case TIMELIB_ZONETYPE_OFFSET: /* Only offset */
218 				printf(" GMT %05d%s", d->z, d->dst == 1 ? " (DST)" : "");
219 				break;
220 			case TIMELIB_ZONETYPE_ID: /* Timezone struct */
221 				/* Show abbreviation if wanted */
222 				if (d->tz_abbr) {
223 					printf(" %s", d->tz_abbr);
224 				}
225 				/* Do we have a TimeZone struct? */
226 				if (d->tz_info) {
227 					printf(" %s", d->tz_info->name);
228 				}
229 				break;
230 			case TIMELIB_ZONETYPE_ABBR:
231 				printf(" %s", d->tz_abbr);
232 				printf(" %05d%s", d->z, d->dst == 1 ? " (DST)" : "");
233 				break;
234 		}
235 	}
236 
237 	if ((options & 1) == 1) {
238 		if (d->have_relative) {
239 			printf("%3lldY %3lldM %3lldD / %3lldH %3lldM %3lldS",
240 				d->relative.y, d->relative.m, d->relative.d, d->relative.h, d->relative.i, d->relative.s);
241 			if (d->relative.first_last_day_of != 0) {
242 				switch (d->relative.first_last_day_of) {
243 					case 1:
244 						printf(" / first day of");
245 						break;
246 					case 2:
247 						printf(" / last day of");
248 						break;
249 				}
250 			}
251 			if (d->relative.have_weekday_relative) {
252 				printf(" / %d.%d", d->relative.weekday, d->relative.weekday_behavior);
253 			}
254 			if (d->relative.have_special_relative) {
255 				switch (d->relative.special.type) {
256 					case TIMELIB_SPECIAL_WEEKDAY:
257 						printf(" / %lld weekday", d->relative.special.amount);
258 						break;
259 					case TIMELIB_SPECIAL_DAY_OF_WEEK_IN_MONTH:
260 						printf(" / x y of z month");
261 						break;
262 					case TIMELIB_SPECIAL_LAST_DAY_OF_WEEK_IN_MONTH:
263 						printf(" / last y of z month");
264 						break;
265 				}
266 			}
267 		}
268 	}
269 	printf("\n");
270 }
271 
timelib_dump_rel_time(timelib_rel_time * d)272 void timelib_dump_rel_time(timelib_rel_time *d)
273 {
274 	printf("%3lldY %3lldM %3lldD / %3lldH %3lldM %3lldS (days: %lld)%s",
275 		d->y, d->m, d->d, d->h, d->i, d->s, d->days, d->invert ? " inverted" : "");
276 	if (d->first_last_day_of != 0) {
277 		switch (d->first_last_day_of) {
278 			case 1:
279 				printf(" / first day of");
280 				break;
281 			case 2:
282 				printf(" / last day of");
283 				break;
284 		}
285 	}
286 	printf("\n");
287 }
288 
timelib_parse_tz_cor(char ** ptr)289 long timelib_parse_tz_cor(char **ptr)
290 {
291         char *begin = *ptr, *end;
292         long  tmp;
293 
294         while (isdigit(**ptr) || **ptr == ':') {
295                 ++*ptr;
296         }
297         end = *ptr;
298         switch (end - begin) {
299                 case 1:
300                 case 2:
301                         return HOUR(strtol(begin, NULL, 10));
302                         break;
303                 case 3:
304                 case 4:
305                         if (begin[1] == ':') {
306                                 tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 2, NULL, 10);
307                                 return tmp;
308                         } else if (begin[2] == ':') {
309                                 tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
310                                 return tmp;
311                         } else {
312                                 tmp = strtol(begin, NULL, 10);
313                                 return HOUR(tmp / 100) + tmp % 100;
314                         }
315                 case 5:
316                         tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
317                         return tmp;
318         }
319         return 0;
320 }
321