1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /*
4 * GThumb
5 *
6 * Copyright (C) 2009 The Free Software Foundation, Inc.
7 *
8 * This program 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 of the License, or
11 * (at your option) any later version.
12 *
13 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <config.h>
23 #include <stdlib.h>
24 #include "glib-utils.h"
25 #include "gth-time.h"
26
27
28 #define INVALID_HOUR (24)
29 #define INVALID_MIN (60)
30 #define INVALID_SEC (60)
31 #define INVALID_USEC (1000000)
32
33
34 static GthDateTime *
gth_datetime_copy_for_boxed(GthDateTime * source)35 gth_datetime_copy_for_boxed (GthDateTime *source)
36 {
37 GthDateTime *dest;
38
39 dest = gth_datetime_new ();
40 gth_datetime_copy (source, dest);
41
42 return dest;
43 }
44
45
G_DEFINE_BOXED_TYPE(GthDateTime,gth_datetime,gth_datetime_copy_for_boxed,gth_datetime_free)46 G_DEFINE_BOXED_TYPE (GthDateTime, gth_datetime, gth_datetime_copy_for_boxed, gth_datetime_free)
47
48
49 GthTime *
50 gth_time_new (void)
51 {
52 GthTime *time;
53
54 time = g_new (GthTime, 1);
55 gth_time_clear (time);
56
57 return time;
58 }
59
60
61 void
gth_time_free(GthTime * time)62 gth_time_free (GthTime *time)
63 {
64 g_free (time);
65 }
66
67
68 void
gth_time_clear(GthTime * time)69 gth_time_clear (GthTime *time)
70 {
71 time->hour = INVALID_HOUR;
72 time->min = INVALID_MIN;
73 time->sec = INVALID_SEC;
74 time->usec = INVALID_USEC;
75 }
76
77
78 gboolean
gth_time_valid(GthTime * time)79 gth_time_valid (GthTime *time)
80 {
81 return (time->hour < INVALID_HOUR) && (time->min < INVALID_MIN) && (time->sec < INVALID_SEC) && (time->usec < INVALID_USEC);
82 }
83
84
85 void
gth_time_set_hms(GthTime * time,guint8 hour,guint8 min,guint8 sec,guint usec)86 gth_time_set_hms (GthTime *time,
87 guint8 hour,
88 guint8 min,
89 guint8 sec,
90 guint usec)
91 {
92 time->hour = hour;
93 time->min = min;
94 time->sec = sec;
95 time->usec = usec;
96 }
97
98
99 GthDateTime *
gth_datetime_new(void)100 gth_datetime_new (void)
101 {
102 GthDateTime *dt;
103
104 dt = g_new0 (GthDateTime, 1);
105 dt->date = g_date_new ();
106 dt->time = gth_time_new ();
107
108 return dt;
109 }
110
111
112 void
gth_datetime_free(GthDateTime * dt)113 gth_datetime_free (GthDateTime *dt)
114 {
115 if (dt == NULL)
116 return;
117 g_date_free (dt->date);
118 gth_time_free (dt->time);
119 g_free (dt);
120 }
121
122
123 void
gth_datetime_copy(GthDateTime * src,GthDateTime * dest)124 gth_datetime_copy (GthDateTime *src,
125 GthDateTime *dest)
126 {
127 if (g_date_valid (src->date)) {
128 *dest->date = *src->date;
129 if (gth_time_valid (src->time))
130 *dest->time = *src->time;
131 else
132 gth_time_clear (dest->time);
133 }
134 else
135 gth_datetime_clear (dest);
136 }
137
138
139 void
gth_datetime_clear(GthDateTime * dt)140 gth_datetime_clear (GthDateTime *dt)
141 {
142 gth_time_clear (dt->time);
143 g_date_clear (dt->date, 1);
144 }
145
146
147 gboolean
gth_datetime_valid(GthDateTime * dt)148 gth_datetime_valid (GthDateTime *dt)
149 {
150 return gth_time_valid (dt->time) && g_date_valid (dt->date);
151 }
152
153
154 gboolean
gth_datetime_valid_date(GthDateTime * dt)155 gth_datetime_valid_date (GthDateTime *dt)
156 {
157 return g_date_valid (dt->date);
158 }
159
160
161 void
gth_datetime_from_timeval(GthDateTime * dt,GTimeVal * tv)162 gth_datetime_from_timeval (GthDateTime *dt,
163 GTimeVal *tv)
164 {
165 char *exif_date;
166
167 exif_date = _g_time_val_to_exif_date (tv);
168 gth_datetime_from_exif_date (dt, exif_date);
169
170 g_free (exif_date);
171 }
172
173
174 gboolean
gth_datetime_from_exif_date(GthDateTime * dt,const char * exif_date)175 gth_datetime_from_exif_date (GthDateTime *dt,
176 const char *exif_date)
177 {
178 GDateYear year;
179 GDateMonth month;
180 GDateDay day;
181 long val;
182
183 if (exif_date == NULL)
184 return FALSE;
185
186 g_return_val_if_fail (dt != NULL, FALSE);
187
188 while (g_ascii_isspace (*exif_date))
189 exif_date++;
190
191 if (*exif_date == '\0')
192 return FALSE;
193
194 if (! g_ascii_isdigit (*exif_date))
195 return FALSE;
196
197 /* YYYY */
198
199 val = g_ascii_strtoull (exif_date, (char **)&exif_date, 10);
200 year = val;
201
202 if (*exif_date != ':')
203 return FALSE;
204
205 /* MM */
206
207 exif_date++;
208 month = g_ascii_strtoull (exif_date, (char **)&exif_date, 10);
209
210 if (*exif_date != ':')
211 return FALSE;
212
213 /* DD */
214
215 exif_date++;
216 day = g_ascii_strtoull (exif_date, (char **)&exif_date, 10);
217
218 if (*exif_date != ' ')
219 return FALSE;
220
221 g_date_set_dmy (dt->date, day, month, year);
222
223 /* hh */
224
225 val = g_ascii_strtoull (exif_date, (char **)&exif_date, 10);
226 dt->time->hour = val;
227
228 if (*exif_date != ':')
229 return FALSE;
230
231 /* mm */
232
233 exif_date++;
234 dt->time->min = g_ascii_strtoull (exif_date, (char **)&exif_date, 10);
235
236 if (*exif_date != ':')
237 return FALSE;
238
239 /* ss */
240
241 exif_date++;
242 dt->time->sec = strtoul (exif_date, (char **)&exif_date, 10);
243
244 /* usec */
245
246 dt->time->usec = 0;
247 if ((*exif_date == ',') || (*exif_date == '.')) {
248 glong mul = 100000;
249
250 while (g_ascii_isdigit (*++exif_date)) {
251 dt->time->usec += (*exif_date - '0') * mul;
252 mul /= 10;
253 }
254 }
255
256 while (g_ascii_isspace (*exif_date))
257 exif_date++;
258
259 return *exif_date == '\0';
260 }
261
262
263 void
gth_datetime_from_struct_tm(GthDateTime * dt,struct tm * tm)264 gth_datetime_from_struct_tm (GthDateTime *dt,
265 struct tm *tm)
266 {
267 if (tm->tm_hour < 0)
268 gth_time_clear (dt->time);
269 else
270 gth_time_set_hms (dt->time, tm->tm_hour, tm->tm_min, tm->tm_sec, 0);
271
272 if ((tm->tm_year < 0) || (tm->tm_mday < 1) || (tm->tm_mday > 31) || (tm->tm_mon < 0) || (tm->tm_mon > 11))
273 g_date_clear (dt->date, 1);
274 else
275 g_date_set_dmy (dt->date, tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year);
276 }
277
278
279 void
gth_datetime_from_gdate(GthDateTime * dt,GDate * date)280 gth_datetime_from_gdate (GthDateTime *dt,
281 GDate *date)
282 {
283 if (date != NULL)
284 *dt->date = *date;
285 else
286 g_date_clear (dt->date, 1);
287 gth_time_clear (dt->time);
288 }
289
290
291 char *
gth_datetime_to_exif_date(GthDateTime * dt)292 gth_datetime_to_exif_date (GthDateTime *dt)
293 {
294 if (gth_datetime_valid (dt))
295 return g_strdup_printf ("%4d:%02d:%02d %02d:%02d:%02d",
296 g_date_get_year (dt->date),
297 g_date_get_month (dt->date),
298 g_date_get_day (dt->date),
299 dt->time->hour,
300 dt->time->min,
301 dt->time->sec);
302 else if (g_date_valid (dt->date))
303 return g_strdup_printf ("%4d:%02d:%02d 00:00:00",
304 g_date_get_year (dt->date),
305 g_date_get_month (dt->date),
306 g_date_get_day (dt->date));
307 else
308 return g_strdup ("");
309 }
310
311
312 gboolean
gth_datetime_to_struct_tm(GthDateTime * dt,struct tm * tm)313 gth_datetime_to_struct_tm (GthDateTime *dt,
314 struct tm *tm)
315 {
316 if (! gth_datetime_valid (dt))
317 return FALSE;
318
319 g_date_to_struct_tm (dt->date, tm);
320 tm->tm_hour = dt->time->hour;
321 tm->tm_min = dt->time->min;
322 tm->tm_sec = dt->time->sec;
323
324 return TRUE;
325 }
326
327
328 gboolean
gth_datetime_to_timeval(GthDateTime * dt,GTimeVal * tv)329 gth_datetime_to_timeval (GthDateTime *dt,
330 GTimeVal *tv)
331 {
332 char *exif_date;
333 gboolean result;
334
335 exif_date = gth_datetime_to_exif_date (dt);
336 result = _g_time_val_from_exif_date (exif_date, tv);
337
338 g_free (exif_date);
339
340 return result;
341 }
342
343
344 char *
gth_datetime_strftime(GthDateTime * dt,const char * format)345 gth_datetime_strftime (GthDateTime *dt,
346 const char *format)
347 {
348 struct tm tm;
349
350 if (gth_datetime_to_struct_tm (dt, &tm))
351 return _g_struct_tm_strftime (&tm, format);
352 else
353 return g_strdup ("");
354 }
355