1 /*
2 * Osmo - a handy personal organizer
3 *
4 * Copyright (C) 2007-2009 Tomasz Maka <pasp@users.sourceforge.net>
5 * 2007-2009 Piotr Maka <silloz@users.sourceforge.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 #include "i18n.h"
23 #include "utils.h"
24 #include "utils_date.h"
25
26 /*============================================================================*/
27
28 GDate *
utl_date_new_current(void)29 utl_date_new_current (void)
30 {
31 GDate *d = g_date_new ();
32 g_date_set_time_t (d, time (NULL));
33
34 return d;
35 }
36
37 /*============================================================================*/
38
39 guint
utl_date_get_current_day(void)40 utl_date_get_current_day (void)
41 {
42 GDate *d = utl_date_new_current ();
43 guint day = g_date_get_day (d);
44 g_date_free (d);
45
46 return day;
47 }
48
49 /*============================================================================*/
50
51 guint
utl_date_get_current_month(void)52 utl_date_get_current_month (void)
53 {
54 GDate *d = utl_date_new_current ();
55 guint month = g_date_get_month (d);
56 g_date_free (d);
57
58 return month;
59 }
60
61 /*============================================================================*/
62
63 guint
utl_date_get_current_year(void)64 utl_date_get_current_year (void)
65 {
66 GDate *d = utl_date_new_current ();
67 guint year = g_date_get_year (d);
68 g_date_free (d);
69
70 return year;
71 }
72
73 /*============================================================================*/
74
75 guint32
utl_date_get_current_julian(void)76 utl_date_get_current_julian (void)
77 {
78 GDate *d = utl_date_new_current ();
79 guint32 julian = g_date_get_julian (d);
80 g_date_free (d);
81
82 return julian;
83 }
84
85 /*============================================================================*/
86
87 void
utl_date_get_current_dmy(gint * day,gint * month,gint * year)88 utl_date_get_current_dmy (gint *day, gint *month, gint *year)
89 {
90 GDate *d = utl_date_new_current ();
91
92 if (day != NULL) *day = g_date_get_day (d);
93 if (month != NULL) *month = g_date_get_month (d);
94 if (year != NULL) *year = g_date_get_year (d);
95
96 g_date_free (d);
97 }
98
99 /*============================================================================*/
100
101 guint
utl_date_get_days_in_month(const GDate * date)102 utl_date_get_days_in_month (const GDate *date)
103 {
104 g_return_val_if_fail (g_date_valid (date), 0);
105
106 return g_date_get_days_in_month (g_date_get_month (date), g_date_get_year (date));
107 }
108
109 /*============================================================================*/
110
111 gboolean
utl_date_set_valid_day(GDate * date,gint day)112 utl_date_set_valid_day (GDate *date, gint day)
113 {
114 gint days = utl_date_get_days_in_month (date);
115
116 if (day > days) {
117 g_date_set_day (date, days);
118 return TRUE;
119 }
120
121 g_date_set_day (date, day);
122 return FALSE;
123 }
124
125 /*============================================================================*/
126
127 gboolean
utl_date_set_valid_dmy(gint * day,gint month,gint year)128 utl_date_set_valid_dmy (gint *day, gint month, gint year)
129 {
130 gint days = g_date_get_days_in_month (month, year);
131
132 if (*day > days) {
133 *day = days;
134 return TRUE;
135 }
136
137 return FALSE;
138 }
139
140 /*============================================================================*/
141
142 void
utl_date_diff(const GDate * date1,const GDate * date2,gint * day,gint * month,gint * year)143 utl_date_diff (const GDate *date1, const GDate *date2, gint *day, gint *month, gint *year)
144 {
145 g_return_if_fail (g_date_valid (date1));
146 g_return_if_fail (g_date_valid (date2));
147 g_return_if_fail (g_date_compare (date1, date2) <= 0);
148
149 *day = g_date_get_day (date2) - g_date_get_day (date1);
150 *month = g_date_get_month (date2) - g_date_get_month (date1);
151 *year = g_date_get_year (date2) - g_date_get_year (date1);
152
153 if (*day < 0) {
154 *day += utl_date_get_days_in_month (date1);
155 *month -= 1;
156 }
157
158 if (*month < 0) {
159 *month += 12;
160 *year -= 1;
161 }
162 }
163
164 /*============================================================================*/
165
166 gboolean
utl_date_order(GDate * date1,GDate * date2)167 utl_date_order (GDate *date1, GDate *date2)
168 {
169 g_return_val_if_fail (g_date_valid (date1), FALSE);
170 g_return_val_if_fail (g_date_valid (date2), FALSE);
171
172 if (g_date_compare (date1, date2) > 0)
173 {
174 GDate tmp = *date1;
175 *date1 = *date2;
176 *date2 = tmp;
177 return TRUE;
178 } else
179 return FALSE;
180 }
181
182 /*============================================================================*/
183
184 void
utl_date_set_nearest_weekday(GDate * date,gint weekdays,gboolean month_mode)185 utl_date_set_nearest_weekday (GDate *date, gint weekdays, gboolean month_mode)
186 {
187 gint day, start_day, days_in_month;
188 gint i, j;
189
190 if (weekdays == D_WEEK) return;
191 g_return_if_fail (weekdays > D_BAD_DAY && weekdays <= D_WEEK);
192 g_return_if_fail (g_date_valid (date));
193
194 day = g_date_get_weekday (date) - 1;
195
196 if (month_mode == TRUE) {
197
198 days_in_month = utl_date_get_days_in_month (date);
199 start_day = g_date_get_day (date);
200
201 for (i = 0; i < 7; i++) {
202 if (weekdays & (1 << ((day + i) % 7))) break;
203 }
204
205 for (j = 0; j < 7; j++) {
206 if (weekdays & (1 << ((day + 7 - j) % 7))) break;
207 }
208
209 if (start_day + i > days_in_month) i = 7;
210 if (start_day - j < 1) j = 7;
211
212 if (i <= j) {
213 if (i > 0) g_date_add_days (date, i);
214 } else {
215 if (j > 0) g_date_subtract_days (date, j);
216 }
217
218 } else {
219
220 for (i = 0; i < 7; i++) {
221 if (weekdays & (1 << ((day + i) % 7))) break;
222 }
223 if (i > 0) g_date_add_days (date, i);
224
225 }
226
227 }
228
229 /*============================================================================*/
230
231 gchar *
utl_date_print(const GDate * d,gint date_format,gint override_locale)232 utl_date_print (const GDate *d, gint date_format, gint override_locale)
233 {
234 gchar date_str[BUFFER_SIZE], *format;
235
236 g_return_val_if_fail (g_date_valid (d), NULL);
237
238 format = utl_date_get_format_str (date_format, override_locale);
239 g_date_strftime (date_str, BUFFER_SIZE, format, d);
240
241 return g_strdup (date_str);
242 }
243
244 /*============================================================================*/
245
246 gchar *
utl_date_print_j(guint32 julian,gint date_format,gint override_locale)247 utl_date_print_j (guint32 julian, gint date_format, gint override_locale)
248 {
249 gchar *date_str;
250
251 if (g_date_valid_julian (julian)) {
252 GDate *d = g_date_new_julian (julian);
253 date_str = utl_date_print (d, date_format, override_locale);
254 g_date_free (d);
255 } else
256 date_str = g_strdup (_("No date"));
257
258 return date_str;
259 }
260
261 /*============================================================================*/
262
263 gchar *
utl_date_get_format_str(gint date_format,gint override_locale)264 utl_date_get_format_str (gint date_format, gint override_locale)
265 {
266 gchar *date_format_str[] = {
267 "%d-%m-%Y", "%m-%d-%Y", "%Y-%m-%d", "%Y-%d-%m", "%e %B", "%A", "%e %B %Y", "%x"
268 };
269
270 if (!override_locale)
271 return date_format_str[DATE_LOCALE];
272
273 g_return_val_if_fail (date_format >= DATE_DD_MM_YYYY &&
274 date_format <= DATE_FULL, NULL);
275
276 return date_format_str[date_format];
277 }
278
279 /*============================================================================*/
280
281 void
utl_date_get_dmy(const GDate * date,gint * day,gint * month,gint * year)282 utl_date_get_dmy (const GDate *date, gint *day, gint *month, gint *year)
283 {
284 g_return_if_fail (g_date_valid (date));
285
286 if (day != NULL) *day = g_date_get_day (date);
287 if (month != NULL) *month = g_date_get_month (date);
288 if (year != NULL) *year = g_date_get_year (date);
289 }
290
291 /*============================================================================*/
292
293 void
utl_date_julian_to_dmy(guint32 julian,gint * day,gint * month,gint * year)294 utl_date_julian_to_dmy (guint32 julian, gint *day, gint *month, gint *year)
295 {
296 g_return_if_fail (g_date_valid_julian (julian));
297
298 GDate *d = g_date_new_julian (julian);
299 if (day != NULL) *day = g_date_get_day (d);
300 if (month != NULL) *month = g_date_get_month (d);
301 if (year != NULL) *year = g_date_get_year (d);
302
303 g_date_free (d);
304 }
305
306 /*============================================================================*/
307
308 guint32
utl_date_dmy_to_julian(guint day,guint month,guint year)309 utl_date_dmy_to_julian (guint day, guint month, guint year)
310 {
311 g_return_val_if_fail (g_date_valid_dmy (day, month, year), 0);
312
313 GDate *d = g_date_new_dmy (day, month, year);
314 guint32 julian = g_date_get_julian (d);
315 g_date_free (d);
316
317 return julian;
318 }
319
320 /*============================================================================*/
321 /*
322 * lib_date routines
323 * Copyright (c) 1995, 1996, 1997, 1998 by Steffen Beyer
324 *
325 */
326
327 guint
utl_get_month_length(guint leap_year,guint month)328 utl_get_month_length (guint leap_year, guint month) {
329
330 const guint month_length[2][13] = {
331 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
332 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
333 };
334
335 return month_length[leap_year][month];
336 }
337
338 guint
utl_get_days_in_months(guint leap_year,guint month)339 utl_get_days_in_months (guint leap_year, guint month) {
340
341 const guint days_in_months[2][14] = {
342 { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
343 { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
344 };
345
346 return days_in_months[leap_year][month];
347 }
348
349 glong
utl_year_to_days(guint year)350 utl_year_to_days (guint year) {
351 return( year * 365L + (year / 4) - (year / 100) + (year / 400) );
352 }
353
354 glong
utl_calc_days(guint year,guint mm,guint dd)355 utl_calc_days (guint year, guint mm, guint dd) {
356
357 gboolean lp;
358
359 if (year < 1) return(0L);
360 if ((mm < 1) || (mm > 12)) return(0L);
361 if ((dd < 1) || (dd > utl_get_month_length((lp = g_date_is_leap_year(year)), mm))) return(0L);
362
363 return( utl_year_to_days(--year) + utl_get_days_in_months(lp, mm) + dd );
364 }
365
366 glong
utl_dates_difference(guint year1,guint mm1,guint dd1,guint year2,guint mm2,guint dd2)367 utl_dates_difference (guint year1, guint mm1, guint dd1,
368 guint year2, guint mm2, guint dd2) {
369
370 return (utl_calc_days(year2, mm2, dd2) - utl_calc_days(year1, mm1, dd1));
371 }
372
373 guint
utl_day_of_week(guint year,guint mm,guint dd)374 utl_day_of_week (guint year, guint mm, guint dd) {
375
376 glong days;
377
378 days = utl_calc_days(year, mm, dd);
379 if (days > 0L) {
380 days--;
381 days %= 7L;
382 days++;
383 }
384 return( (guint) days );
385 }
386
387 guint
utl_weeks_in_year(guint year)388 utl_weeks_in_year (guint year) {
389 return(52 + ((utl_day_of_week(year, 1, 1) == 4) || (utl_day_of_week(year, 12, 31) == 4)));
390 }
391
392 guint
utl_get_week_number(guint year,guint mm,guint dd)393 utl_get_week_number (guint year, guint mm, guint dd) {
394
395 guint first;
396
397 first = utl_day_of_week(year,1,1) - 1;
398 return( (guint) ( (utl_dates_difference(year,1,1, year,mm,dd) + first) / 7L ) +
399 (first < 4) );
400 }
401
402 gboolean
utl_week_of_year(guint * week,guint * year,guint mm,guint dd)403 utl_week_of_year (guint *week, guint *year, guint mm, guint dd) {
404
405 if (g_date_valid_dmy (dd, mm, *year)) {
406 *week = utl_get_week_number(*year, mm, dd);
407 if (*week == 0)
408 *week = utl_weeks_in_year(--(*year));
409 else if (*week > utl_weeks_in_year(*year)) {
410 *week = 1;
411 (*year)++;
412 }
413 return TRUE;
414 }
415 return FALSE;
416 }
417
418 /*------------------------------------------------------------------------------*/
419
420