gdate.c 70.9 KB
Newer Older
1
2
3
4
/* GLIB - Library of useful routines for C programming
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2.1 of the License, or (at your option) any later version.
8
9
10
11
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16
 */
17

18
/*
19
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
20
21
22
23
24
 * file for a list of people on the GLib Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GLib at ftp://ftp.gtk.org/pub/gtk/. 
 */

25
26
27
28
/* 
 * MT safe
 */

29
#include "config.h"
30
#include "glibconfig.h"
31

32
33
34
35
36
#define DEBUG_MSG(x)	/* */
#ifdef G_ENABLE_DEBUG
/* #define DEBUG_MSG(args)	g_message args ; */
#endif

37
#include <time.h>
38
39
40
41
#include <string.h>
#include <stdlib.h>
#include <locale.h>

42
43
44
45
#ifdef G_OS_WIN32
#include <windows.h>
#endif

Matthias Clasen's avatar
Matthias Clasen committed
46
47
48
49
50
51
52
53
#include "gdate.h"

#include "gconvert.h"
#include "gmem.h"
#include "gstrfuncs.h"
#include "gtestutils.h"
#include "gthread.h"
#include "gunicode.h"
54

55
56
57
58
#ifdef G_OS_WIN32
#include "garray.h"
#endif

Matthias Clasen's avatar
Matthias Clasen committed
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
 * SECTION:date
 * @title: Date and Time Functions
 * @short_description: calendrical calculations and miscellaneous time stuff
 *
 * The #GDate data structure represents a day between January 1, Year 1,
 * and sometime a few thousand years in the future (right now it will go
 * to the year 65535 or so, but g_date_set_parse() only parses up to the
 * year 8000 or so - just count on "a few thousand"). #GDate is meant to
 * represent everyday dates, not astronomical dates or historical dates
 * or ISO timestamps or the like. It extrapolates the current Gregorian
 * calendar forward and backward in time; there is no attempt to change
 * the calendar to match time periods or locations. #GDate does not store
72
 * time information; it represents a day.
Matthias Clasen's avatar
Matthias Clasen committed
73
74
75
76
77
78
79
80
81
82
83
84
85
 *
 * The #GDate implementation has several nice features; it is only a
 * 64-bit struct, so storing large numbers of dates is very efficient. It
 * can keep both a Julian and day-month-year representation of the date,
 * since some calculations are much easier with one representation or the
 * other. A Julian representation is simply a count of days since some
 * fixed day in the past; for #GDate the fixed day is January 1, 1 AD.
 * ("Julian" dates in the #GDate API aren't really Julian dates in the
 * technical sense; technically, Julian dates count from the start of the
 * Julian period, Jan 1, 4713 BC).
 *
 * #GDate is simple to use. First you need a "blank" date; you can get a
 * dynamically allocated date from g_date_new(), or you can declare an
86
87
 * automatic variable or array and initialize it by
 * calling g_date_clear(). A cleared date is safe; it's safe to call
Matthias Clasen's avatar
Matthias Clasen committed
88
89
 * g_date_set_dmy() and the other mutator functions to initialize the
 * value of a cleared date. However, a cleared date is initially
90
91
92
 * invalid, meaning that it doesn't represent a day that exists.
 * It is undefined to call any of the date calculation routines on an
 * invalid date. If you obtain a date from a user or other
Matthias Clasen's avatar
Matthias Clasen committed
93
94
95
96
97
 * unpredictable source, you should check its validity with the
 * g_date_valid() predicate. g_date_valid() is also used to check for
 * errors with g_date_set_parse() and other functions that can
 * fail. Dates can be invalidated by calling g_date_clear() again.
 *
98
99
 * It is very important to use the API to access the #GDate
 * struct. Often only the day-month-year or only the Julian
Matthias Clasen's avatar
Matthias Clasen committed
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
 * representation is valid. Sometimes neither is valid. Use the API.
 *
 * GLib also features #GDateTime which represents a precise time.
 */

/**
 * G_USEC_PER_SEC:
 *
 * Number of microseconds in one second (1 million).
 * This macro is provided for code readability.
 */

/**
 * GTimeVal:
 * @tv_sec: seconds
 * @tv_usec: microseconds
 *
 * Represents a precise time, with seconds and microseconds.
118
119
 * Similar to the struct timeval returned by the gettimeofday()
 * UNIX system call.
Matthias Clasen's avatar
Matthias Clasen committed
120
 *
121
 * GLib is attempting to unify around the use of 64-bit integers to
Matthias Clasen's avatar
Matthias Clasen committed
122
 * represent microsecond-precision time. As such, this type will be
123
124
125
 * removed from a future version of GLib. A consequence of using `glong` for
 * `tv_sec` is that on 32-bit systems `GTimeVal` is subject to the year 2038
 * problem.
126
127
 *
 * Deprecated: 2.62: Use #GDateTime or #guint64 instead.
Matthias Clasen's avatar
Matthias Clasen committed
128
129
130
131
132
133
134
135
136
137
138
139
140
141
 */

/**
 * GDate:
 * @julian_days: the Julian representation of the date
 * @julian: this bit is set if @julian_days is valid
 * @dmy: this is set if @day, @month and @year are valid
 * @day: the day of the day-month-year representation of the date,
 *     as a number between 1 and 31
 * @month: the day of the day-month-year representation of the date,
 *     as a number between 1 and 12
 * @year: the day of the day-month-year representation of the date
 *
 * Represents a day between January 1, Year 1 and a few thousand years in
142
143
144
145
146
147
148
 * the future. None of its members should be accessed directly.
 *
 * If the #GDate-struct is obtained from g_date_new(), it will be safe
 * to mutate but invalid and thus not safe for calendrical computations.
 *
 * If it's declared on the stack, it will contain garbage so must be
 * initialized with g_date_clear(). g_date_clear() makes the date invalid
149
 * but safe. An invalid date doesn't represent a day, it's "empty." A date
150
151
 * becomes valid after you set it to a Julian day or you set a day, month,
 * and year.
Matthias Clasen's avatar
Matthias Clasen committed
152
153
154
155
 */

/**
 * GTime:
Allison Karlitskaya's avatar
Allison Karlitskaya committed
156
 *
157
158
159
 * Simply a replacement for `time_t`. It has been deprecated
 * since it is not equivalent to `time_t` on 64-bit platforms
 * with a 64-bit `time_t`. Unrelated to #GTimer.
160
 *
161
 * Note that #GTime is defined to always be a 32-bit integer,
162
 * unlike `time_t` which may be 64-bit on some systems. Therefore,
163
164
165
 * #GTime will overflow in the year 2038, and you cannot use the
 * address of a #GTime variable as argument to the UNIX time()
 * function.
Matthias Clasen's avatar
Matthias Clasen committed
166
 *
167
 * Instead, do the following:
168
 * |[<!-- language="C" -->
Matthias Clasen's avatar
Matthias Clasen committed
169
170
171
 * time_t ttime;
 * GTime gtime;
 *
Matthias Clasen's avatar
Matthias Clasen committed
172
 * time (&ttime);
Matthias Clasen's avatar
Matthias Clasen committed
173
174
 * gtime = (GTime)ttime;
 * ]|
175
176
177
 *
 * Deprecated: 2.62: This is not [Y2038-safe](https://en.wikipedia.org/wiki/Year_2038_problem).
 *    Use #GDateTime or #time_t instead.
Matthias Clasen's avatar
Matthias Clasen committed
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
 */

/**
 * GDateDMY:
 * @G_DATE_DAY: a day
 * @G_DATE_MONTH: a month
 * @G_DATE_YEAR: a year
 *
 * This enumeration isn't used in the API, but may be useful if you need
 * to mark a number as a day, month, or year.
 */

/**
 * GDateDay:
 *
193
194
 * Integer representing a day of the month; between 1 and 31.
 * #G_DATE_BAD_DAY represents an invalid day of the month.
Matthias Clasen's avatar
Matthias Clasen committed
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
 */

/**
 * GDateMonth:
 * @G_DATE_BAD_MONTH: invalid value
 * @G_DATE_JANUARY: January
 * @G_DATE_FEBRUARY: February
 * @G_DATE_MARCH: March
 * @G_DATE_APRIL: April
 * @G_DATE_MAY: May
 * @G_DATE_JUNE: June
 * @G_DATE_JULY: July
 * @G_DATE_AUGUST: August
 * @G_DATE_SEPTEMBER: September
 * @G_DATE_OCTOBER: October
 * @G_DATE_NOVEMBER: November
 * @G_DATE_DECEMBER: December
 *
 * Enumeration representing a month; values are #G_DATE_JANUARY,
 * #G_DATE_FEBRUARY, etc. #G_DATE_BAD_MONTH is the invalid value.
 */

/**
 * GDateYear:
 *
 * Integer representing a year; #G_DATE_BAD_YEAR is the invalid
 * value. The year must be 1 or higher; negative (BC) years are not
 * allowed. The year is represented with four digits.
 */

/**
 * GDateWeekday:
 * @G_DATE_BAD_WEEKDAY: invalid value
 * @G_DATE_MONDAY: Monday
 * @G_DATE_TUESDAY: Tuesday
 * @G_DATE_WEDNESDAY: Wednesday
 * @G_DATE_THURSDAY: Thursday
 * @G_DATE_FRIDAY: Friday
 * @G_DATE_SATURDAY: Saturday
 * @G_DATE_SUNDAY: Sunday
 *
 * Enumeration representing a day of the week; #G_DATE_MONDAY,
 * #G_DATE_TUESDAY, etc. #G_DATE_BAD_WEEKDAY is an invalid weekday.
 */

/**
 * G_DATE_BAD_DAY:
 *
 * Represents an invalid #GDateDay.
 */

/**
 * G_DATE_BAD_JULIAN:
 *
 * Represents an invalid Julian day number.
 */

/**
 * G_DATE_BAD_YEAR:
 *
 * Represents an invalid year.
 */

/**
 * g_date_new:
 *
 * Allocates a #GDate and initializes
262
 * it to a safe state. The new date will
Matthias Clasen's avatar
Matthias Clasen committed
263
264
265
266
267
 * be cleared (as if you'd called g_date_clear()) but invalid (it won't
 * represent an existing day). Free the return value with g_date_free().
 *
 * Returns: a newly-allocated #GDate
 */
268
GDate*
269
g_date_new (void)
270
271
272
273
274
275
{
  GDate *d = g_new0 (GDate, 1); /* happily, 0 is the invalid flag for everything. */
  
  return d;
}

Matthias Clasen's avatar
Matthias Clasen committed
276
277
278
279
280
281
282
283
284
285
286
287
/**
 * g_date_new_dmy:
 * @day: day of the month
 * @month: month of the year
 * @year: year
 *
 * Like g_date_new(), but also sets the value of the date. Assuming the
 * day-month-year triplet you pass in represents an existing day, the
 * returned date will be valid.
 *
 * Returns: a newly-allocated #GDate initialized with @day, @month, and @year
 */
288
GDate*
289
290
291
g_date_new_dmy (GDateDay   day, 
                GDateMonth m, 
                GDateYear  y)
292
293
{
  GDate *d;
294
  g_return_val_if_fail (g_date_valid_dmy (day, m, y), NULL);
295
296
  
  d = g_new (GDate, 1);
297
  
298
  d->julian = FALSE;
299
  d->dmy    = TRUE;
300
  
301
302
303
304
305
  d->month = m;
  d->day   = day;
  d->year  = y;
  
  g_assert (g_date_valid (d));
306
  
307
308
309
  return d;
}

Matthias Clasen's avatar
Matthias Clasen committed
310
311
/**
 * g_date_new_julian:
Allison Karlitskaya's avatar
Allison Karlitskaya committed
312
 * @julian_day: days since January 1, Year 1
Matthias Clasen's avatar
Matthias Clasen committed
313
314
315
316
317
318
319
 *
 * Like g_date_new(), but also sets the value of the date. Assuming the
 * Julian day number you pass in is valid (greater than 0, less than an
 * unreasonably large number), the returned date will be valid.
 *
 * Returns: a newly-allocated #GDate initialized with @julian_day
 */
320
GDate*
Allison Karlitskaya's avatar
Allison Karlitskaya committed
321
g_date_new_julian (guint32 julian_day)
322
323
{
  GDate *d;
Allison Karlitskaya's avatar
Allison Karlitskaya committed
324
  g_return_val_if_fail (g_date_valid_julian (julian_day), NULL);
325
326
  
  d = g_new (GDate, 1);
327
  
328
  d->julian = TRUE;
329
  d->dmy    = FALSE;
330
  
Allison Karlitskaya's avatar
Allison Karlitskaya committed
331
  d->julian_days = julian_day;
332
333
  
  g_assert (g_date_valid (d));
334
  
335
336
337
  return d;
}

Matthias Clasen's avatar
Matthias Clasen committed
338
339
/**
 * g_date_free:
Allison Karlitskaya's avatar
Allison Karlitskaya committed
340
 * @date: a #GDate to free
Matthias Clasen's avatar
Matthias Clasen committed
341
342
343
 *
 * Frees a #GDate returned from g_date_new().
 */
344
void
Allison Karlitskaya's avatar
Allison Karlitskaya committed
345
g_date_free (GDate *date)
346
{
Allison Karlitskaya's avatar
Allison Karlitskaya committed
347
  g_return_if_fail (date != NULL);
348
  
Allison Karlitskaya's avatar
Allison Karlitskaya committed
349
  g_free (date);
350
351
}

talisein's avatar
talisein committed
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
/**
 * g_date_copy:
 * @date: a #GDate to copy
 *
 * Copies a GDate to a newly-allocated GDate. If the input was invalid
 * (as determined by g_date_valid()), the invalid state will be copied
 * as is into the new object.
 *
 * Returns: (transfer full): a newly-allocated #GDate initialized from @date
 *
 * Since: 2.56
 */
GDate *
g_date_copy (const GDate *date)
{
  GDate *res;
  g_return_val_if_fail (date != NULL, NULL);

  if (g_date_valid (date))
    res = g_date_new_julian (g_date_get_julian (date));
  else
    {
      res = g_date_new ();
      *res = *date;
    }

  return res;
}

Matthias Clasen's avatar
Matthias Clasen committed
381
382
383
384
385
386
387
388
389
390
/**
 * g_date_valid:
 * @date: a #GDate to check
 *
 * Returns %TRUE if the #GDate represents an existing day. The date must not
 * contain garbage; it should have been initialized with g_date_clear()
 * if it wasn't allocated by one of the g_date_new() variants.
 *
 * Returns: Whether the date is valid
 */
391
gboolean     
392
g_date_valid (const GDate *d)
393
394
{
  g_return_val_if_fail (d != NULL, FALSE);
395
  
396
  return (d->julian || d->dmy);
397
398
399
400
401
402
403
404
405
406
407
408
409
410
}

static const guint8 days_in_months[2][13] = 
{  /* error, jan feb mar apr may jun jul aug sep oct nov dec */
  {  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 
  {  0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } /* leap year */
};

static const guint16 days_in_year[2][14] = 
{  /* 0, jan feb mar apr may  jun  jul  aug  sep  oct  nov  dec */
  {  0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, 
  {  0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};

Matthias Clasen's avatar
Matthias Clasen committed
411
412
413
414
415
416
417
418
419
/**
 * g_date_valid_month:
 * @month: month
 *
 * Returns %TRUE if the month value is valid. The 12 #GDateMonth
 * enumeration values are the only valid months.
 *
 * Returns: %TRUE if the month is valid
 */
420
gboolean     
421
g_date_valid_month (GDateMonth m)
422
{ 
423
  return (((gint) m > G_DATE_BAD_MONTH) && ((gint) m < 13));
424
425
}

Matthias Clasen's avatar
Matthias Clasen committed
426
427
428
429
430
431
432
433
434
/**
 * g_date_valid_year:
 * @year: year
 *
 * Returns %TRUE if the year is valid. Any year greater than 0 is valid,
 * though there is a 16-bit limit to what #GDate will understand.
 *
 * Returns: %TRUE if the year is valid
 */
435
gboolean     
436
g_date_valid_year (GDateYear y)
437
438
439
440
{
  return ( y > G_DATE_BAD_YEAR );
}

Matthias Clasen's avatar
Matthias Clasen committed
441
442
443
444
445
446
447
448
449
450
/**
 * g_date_valid_day:
 * @day: day to check
 *
 * Returns %TRUE if the day of the month is valid (a day is valid if it's
 * between 1 and 31 inclusive).
 *
 * Returns: %TRUE if the day is valid
 */

451
gboolean     
452
g_date_valid_day (GDateDay d)
453
454
455
456
{
  return ( (d > G_DATE_BAD_DAY) && (d < 32) );
}

Matthias Clasen's avatar
Matthias Clasen committed
457
458
459
460
461
462
463
464
465
/**
 * g_date_valid_weekday:
 * @weekday: weekday
 *
 * Returns %TRUE if the weekday is valid. The seven #GDateWeekday enumeration
 * values are the only valid weekdays.
 *
 * Returns: %TRUE if the weekday is valid
 */
466
467
468
gboolean     
g_date_valid_weekday (GDateWeekday w)
{
469
  return (((gint) w > G_DATE_BAD_WEEKDAY) && ((gint) w < 8));
470
471
}

Matthias Clasen's avatar
Matthias Clasen committed
472
473
474
475
476
477
478
479
480
/**
 * g_date_valid_julian:
 * @julian_date: Julian day to check
 *
 * Returns %TRUE if the Julian day is valid. Anything greater than zero
 * is basically a valid Julian, though there is a 32-bit limit.
 *
 * Returns: %TRUE if the Julian day is valid
 */
481
gboolean     
482
g_date_valid_julian (guint32 j)
483
484
485
486
{
  return (j > G_DATE_BAD_JULIAN);
}

Matthias Clasen's avatar
Matthias Clasen committed
487
488
489
490
491
492
493
494
495
496
497
498
/**
 * g_date_valid_dmy:
 * @day: day
 * @month: month
 * @year: year
 *
 * Returns %TRUE if the day-month-year triplet forms a valid, existing day
 * in the range of days #GDate understands (Year 1 or later, no more than
 * a few thousand years in the future).
 *
 * Returns: %TRUE if the date is a valid one
 */
499
gboolean     
500
501
502
g_date_valid_dmy (GDateDay   d, 
                  GDateMonth m, 
		  GDateYear  y)
503
{
504
505
  /* No need to check the upper bound of @y, because #GDateYear is 16 bits wide,
   * just like #GDate.year. */
506
507
508
509
510
  return ( (m > G_DATE_BAD_MONTH) &&
           (m < 13)               && 
           (d > G_DATE_BAD_DAY)   && 
           (y > G_DATE_BAD_YEAR)  &&   /* must check before using g_date_is_leap_year */
           (d <=  (g_date_is_leap_year (y) ? 
511
		   days_in_months[1][m] : days_in_months[0][m])) );
512
513
514
515
516
517
518
}


/* "Julian days" just means an absolute number of days, where Day 1 ==
 *   Jan 1, Year 1
 */
static void
519
g_date_update_julian (const GDate *const_d)
520
{
521
  GDate *d = (GDate *) const_d;
522
  GDateYear year;
Matthias Clasen's avatar
Matthias Clasen committed
523
  gint idx;
524
  
525
  g_return_if_fail (d != NULL);
526
  g_return_if_fail (d->dmy != 0);
527
  g_return_if_fail (!d->julian);
528
  g_return_if_fail (g_date_valid_dmy (d->day, d->month, d->year));
529
  
530
  /* What we actually do is: multiply years * 365 days in the year,
Matthias Clasen's avatar
Matthias Clasen committed
531
532
533
534
   * add the number of years divided by 4, subtract the number of
   * years divided by 100 and add the number of years divided by 400,
   * which accounts for leap year stuff. Code from Steffen Beyer's
   * DateCalc. 
535
   */
536
  
537
  year = d->year - 1; /* we know d->year > 0 since it's valid */
538
  
539
540
541
542
  d->julian_days = year * 365U;
  d->julian_days += (year >>= 2); /* divide by 4 and add */
  d->julian_days -= (year /= 25); /* divides original # years by 100 */
  d->julian_days += year >> 2;    /* divides by 4, which divides original by 400 */
543
  
Matthias Clasen's avatar
Matthias Clasen committed
544
  idx = g_date_is_leap_year (d->year) ? 1 : 0;
545
  
Matthias Clasen's avatar
Matthias Clasen committed
546
  d->julian_days += days_in_year[idx][d->month] + d->day;
547
  
548
  g_return_if_fail (g_date_valid_julian (d->julian_days));
549
  
550
551
552
553
  d->julian = TRUE;
}

static void 
554
g_date_update_dmy (const GDate *const_d)
555
{
556
  GDate *d = (GDate *) const_d;
557
558
559
  GDateYear y;
  GDateMonth m;
  GDateDay day;
560
  
561
  guint32 A, B, C, D, E, M;
562
  
563
564
  g_return_if_fail (d != NULL);
  g_return_if_fail (d->julian);
565
  g_return_if_fail (!d->dmy);
566
  g_return_if_fail (g_date_valid_julian (d->julian_days));
567
  
568
569
570
571
572
573
574
  /* Formula taken from the Calendar FAQ; the formula was for the
   *  Julian Period which starts on 1 January 4713 BC, so we add
   *  1,721,425 to the number of days before doing the formula.
   *
   * I'm sure this can be simplified for our 1 January 1 AD period
   * start, but I can't figure out how to unpack the formula.  
   */
575
  
576
577
578
579
580
581
582
583
584
585
  A = d->julian_days + 1721425 + 32045;
  B = ( 4 *(A + 36524) )/ 146097 - 1;
  C = A - (146097 * B)/4;
  D = ( 4 * (C + 365) ) / 1461 - 1;
  E = C - ((1461*D) / 4);
  M = (5 * (E - 1) + 2)/153;
  
  m = M + 3 - (12*(M/10));
  day = E - (153*M + 2)/5;
  y = 100 * B + D - 4800 + (M/10);
586
  
587
#ifdef G_ENABLE_DEBUG
588
  if (!g_date_valid_dmy (day, m, y)) 
589
    g_warning ("OOPS julian: %u  computed dmy: %u %u %u",
590
	       d->julian_days, day, m, y);
591
#endif
592
  
593
594
595
  d->month = m;
  d->day   = day;
  d->year  = y;
596
  
597
  d->dmy = TRUE;
598
599
}

Matthias Clasen's avatar
Matthias Clasen committed
600
601
602
603
604
605
606
607
/**
 * g_date_get_weekday:
 * @date: a #GDate
 *
 * Returns the day of the week for a #GDate. The date must be valid.
 *
 * Returns: day of the week as a #GDateWeekday.
 */
608
GDateWeekday 
609
g_date_get_weekday (const GDate *d)
610
611
{
  g_return_val_if_fail (g_date_valid (d), G_DATE_BAD_WEEKDAY);
612
  
613
  if (!d->julian) 
614
615
    g_date_update_julian (d);

616
  g_return_val_if_fail (d->julian, G_DATE_BAD_WEEKDAY);
617
  
618
619
620
  return ((d->julian_days - 1) % 7) + 1;
}

Matthias Clasen's avatar
Matthias Clasen committed
621
622
623
624
625
626
627
628
/**
 * g_date_get_month:
 * @date: a #GDate to get the month from
 *
 * Returns the month of the year. The date must be valid.
 *
 * Returns: month of the year as a #GDateMonth
 */
629
GDateMonth   
630
g_date_get_month (const GDate *d)
631
632
{
  g_return_val_if_fail (g_date_valid (d), G_DATE_BAD_MONTH);
633
  
634
  if (!d->dmy) 
635
636
    g_date_update_dmy (d);

637
  g_return_val_if_fail (d->dmy, G_DATE_BAD_MONTH);
638
639
640
641
  
  return d->month;
}

Matthias Clasen's avatar
Matthias Clasen committed
642
643
644
645
646
647
648
649
/**
 * g_date_get_year:
 * @date: a #GDate
 *
 * Returns the year of a #GDate. The date must be valid.
 *
 * Returns: year in which the date falls
 */
650
GDateYear    
651
g_date_get_year (const GDate *d)
652
653
{
  g_return_val_if_fail (g_date_valid (d), G_DATE_BAD_YEAR);
654
  
655
  if (!d->dmy) 
656
657
    g_date_update_dmy (d);

658
  g_return_val_if_fail (d->dmy, G_DATE_BAD_YEAR);  
659
  
660
661
662
  return d->year;
}

Matthias Clasen's avatar
Matthias Clasen committed
663
664
665
666
667
668
669
670
/**
 * g_date_get_day:
 * @date: a #GDate to extract the day of the month from
 *
 * Returns the day of the month. The date must be valid.
 *
 * Returns: day of the month
 */
671
GDateDay     
672
g_date_get_day (const GDate *d)
673
674
{
  g_return_val_if_fail (g_date_valid (d), G_DATE_BAD_DAY);
675
  
676
  if (!d->dmy) 
677
678
    g_date_update_dmy (d);

679
  g_return_val_if_fail (d->dmy, G_DATE_BAD_DAY);  
680
681
682
683
  
  return d->day;
}

Matthias Clasen's avatar
Matthias Clasen committed
684
685
686
687
688
689
690
691
692
693
694
/**
 * g_date_get_julian:
 * @date: a #GDate to extract the Julian day from
 *
 * Returns the Julian day or "serial number" of the #GDate. The
 * Julian day is simply the number of days since January 1, Year 1; i.e.,
 * January 1, Year 1 is Julian day 1; January 2, Year 1 is Julian day 2,
 * etc. The date must be valid.
 *
 * Returns: Julian day
 */
695
guint32      
696
g_date_get_julian (const GDate *d)
697
698
{
  g_return_val_if_fail (g_date_valid (d), G_DATE_BAD_JULIAN);
699
  
700
  if (!d->julian) 
701
702
    g_date_update_julian (d);

703
704
705
706
707
  g_return_val_if_fail (d->julian, G_DATE_BAD_JULIAN);  
  
  return d->julian_days;
}

Matthias Clasen's avatar
Matthias Clasen committed
708
709
710
711
712
713
714
715
716
/**
 * g_date_get_day_of_year:
 * @date: a #GDate to extract day of year from
 *
 * Returns the day of the year, where Jan 1 is the first day of the
 * year. The date must be valid.
 *
 * Returns: day of the year
 */
717
guint        
718
g_date_get_day_of_year (const GDate *d)
719
{
Matthias Clasen's avatar
Matthias Clasen committed
720
  gint idx;
721
  
722
  g_return_val_if_fail (g_date_valid (d), 0);
723
  
724
  if (!d->dmy) 
725
726
    g_date_update_dmy (d);

727
  g_return_val_if_fail (d->dmy, 0);  
728
  
Matthias Clasen's avatar
Matthias Clasen committed
729
  idx = g_date_is_leap_year (d->year) ? 1 : 0;
730
  
Matthias Clasen's avatar
Matthias Clasen committed
731
  return (days_in_year[idx][d->month] + d->day);
732
733
}

Matthias Clasen's avatar
Matthias Clasen committed
734
735
736
737
738
/**
 * g_date_get_monday_week_of_year:
 * @date: a #GDate
 *
 * Returns the week of the year, where weeks are understood to start on
Matthias Clasen's avatar
Matthias Clasen committed
739
740
 * Monday. If the date is before the first Monday of the year, return 0.
 * The date must be valid.
Matthias Clasen's avatar
Matthias Clasen committed
741
742
743
 *
 * Returns: week of the year
 */
744
guint        
745
g_date_get_monday_week_of_year (const GDate *d)
746
747
748
749
{
  GDateWeekday wd;
  guint day;
  GDate first;
750
  
751
  g_return_val_if_fail (g_date_valid (d), 0);
752
  
753
  if (!d->dmy) 
754
755
    g_date_update_dmy (d);

756
  g_return_val_if_fail (d->dmy, 0);  
757
  
758
  g_date_clear (&first, 1);
759
  
760
  g_date_set_dmy (&first, 1, 1, d->year);
761
  
762
763
  wd = g_date_get_weekday (&first) - 1; /* make Monday day 0 */
  day = g_date_get_day_of_year (d) - 1;
764
  
765
766
767
  return ((day + wd)/7U + (wd == 0 ? 1 : 0));
}

Matthias Clasen's avatar
Matthias Clasen committed
768
769
770
771
/**
 * g_date_get_sunday_week_of_year:
 * @date: a #GDate
 *
Matthias Clasen's avatar
Matthias Clasen committed
772
 * Returns the week of the year during which this date falls, if
Michael Catanzaro's avatar
Michael Catanzaro committed
773
 * weeks are understood to begin on Sunday. The date must be valid.
Matthias Clasen's avatar
Matthias Clasen committed
774
 * Can return 0 if the day is before the first Sunday of the year.
Matthias Clasen's avatar
Matthias Clasen committed
775
776
777
 *
 * Returns: week number
 */
778
guint        
779
g_date_get_sunday_week_of_year (const GDate *d)
780
781
782
783
{
  GDateWeekday wd;
  guint day;
  GDate first;
784
  
785
  g_return_val_if_fail (g_date_valid (d), 0);
786
  
787
  if (!d->dmy) 
788
789
    g_date_update_dmy (d);

790
  g_return_val_if_fail (d->dmy, 0);  
791
  
792
  g_date_clear (&first, 1);
793
  
794
  g_date_set_dmy (&first, 1, 1, d->year);
795
  
796
  wd = g_date_get_weekday (&first);
797
  if (wd == 7) wd = 0; /* make Sunday day 0 */
798
  day = g_date_get_day_of_year (d) - 1;
799
  
800
801
802
  return ((day + wd)/7U + (wd == 0 ? 1 : 0));
}

803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
/**
 * g_date_get_iso8601_week_of_year:
 * @date: a valid #GDate
 *
 * Returns the week of the year, where weeks are interpreted according
 * to ISO 8601. 
 * 
 * Returns: ISO 8601 week number of the year.
 *
 * Since: 2.6
 **/
guint
g_date_get_iso8601_week_of_year (const GDate *d)
{
  guint j, d4, L, d1, w;

  g_return_val_if_fail (g_date_valid (d), 0);
  
  if (!d->julian)
    g_date_update_julian (d);
823

824
825
826
827
828
829
  g_return_val_if_fail (d->julian, 0);

  /* Formula taken from the Calendar FAQ; the formula was for the
   * Julian Period which starts on 1 January 4713 BC, so we add
   * 1,721,425 to the number of days before doing the formula. 
   */
830
  j  = d->julian_days + 1721425;
831
832
833
834
835
836
837
838
  d4 = (j + 31741 - (j % 7)) % 146097 % 36524 % 1461;
  L  = d4 / 1460;
  d1 = ((d4 - L) % 365) + L;
  w  = d1 / 7 + 1;

  return w;
}

Matthias Clasen's avatar
Matthias Clasen committed
839
840
841
842
843
844
845
846
847
848
849
/**
 * g_date_days_between:
 * @date1: the first date
 * @date2: the second date
 *
 * Computes the number of days between two dates.
 * If @date2 is prior to @date1, the returned value is negative.
 * Both dates must be valid.
 *
 * Returns: the number of days between @date1 and @date2
 */
850
851
852
853
854
855
856
857
858
859
gint
g_date_days_between (const GDate *d1,
		     const GDate *d2)
{
  g_return_val_if_fail (g_date_valid (d1), 0);
  g_return_val_if_fail (g_date_valid (d2), 0);

  return (gint)g_date_get_julian (d2) - (gint)g_date_get_julian (d1);
}

Matthias Clasen's avatar
Matthias Clasen committed
860
861
862
863
864
/**
 * g_date_clear:
 * @date: pointer to one or more dates to clear
 * @n_dates: number of dates to clear
 *
865
 * Initializes one or more #GDate structs to a safe but invalid
Matthias Clasen's avatar
Matthias Clasen committed
866
867
868
869
 * state. The cleared dates will not represent an existing date, but will
 * not contain garbage. Useful to init a date declared on the stack.
 * Validity can be tested with g_date_valid().
 */
870
void         
871
g_date_clear (GDate *d, guint ndates)
872
873
874
{
  g_return_if_fail (d != NULL);
  g_return_if_fail (ndates != 0);
875
  
876
877
878
  memset (d, 0x0, ndates*sizeof (GDate)); 
}

879
G_LOCK_DEFINE_STATIC (g_date_global);
880

881
882
883
884
885
886
887
/* These are for the parser, output to the user should use *
 * g_date_strftime () - this creates more never-freed memory to annoy
 * all those memory debugger users. :-) 
 */

static gchar *long_month_names[13] = 
{ 
888
  NULL,
889
890
};

891
892
893
894
895
static gchar *long_month_names_alternative[13] =
{
  NULL,
};

896
897
static gchar *short_month_names[13] = 
{
898
  NULL, 
899
900
};

901
902
903
904
905
static gchar *short_month_names_alternative[13] =
{
  NULL,
};

906
907
908
909
/* This tells us if we need to update the parse info */
static gchar *current_locale = NULL;

/* order of these in the current locale */
910
static GDateDMY dmy_order[3] = 
911
{
912
   G_DATE_DAY, G_DATE_MONTH, G_DATE_YEAR
913
914
915
916
917
918
919
};

/* Where to chop two-digit years: i.e., for the 1930 default, numbers
 * 29 and below are counted as in the year 2000, numbers 30 and above
 * are counted as in the year 1900.  
 */

920
static const GDateYear twodigit_start_year = 1930;
921
922
923
924
925
926

/* It is impossible to enter a year between 1 AD and 99 AD with this
 * in effect.  
 */
static gboolean using_twodigit_years = FALSE;

927
928
929
930
/* Adjustment of locale era to AD, non-zero means using locale era
 */
static gint locale_era_adjust = 0;

931
932
933
934
935
936
937
938
struct _GDateParseTokens {
  gint num_ints;
  gint n[3];
  guint month;
};

typedef struct _GDateParseTokens GDateParseTokens;

939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
static inline gboolean
update_month_match (gsize *longest,
                    const gchar *haystack,
                    const gchar *needle)
{
  gsize length;

  if (needle == NULL)
    return FALSE;

  length = strlen (needle);
  if (*longest >= length)
    return FALSE;

  if (strstr (haystack, needle) == NULL)
    return FALSE;

  *longest = length;
  return TRUE;
}

960
961
#define NUM_LEN 10

962
/* HOLDS: g_date_global_lock */
963
964
965
966
967
static void
g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
{
  gchar num[4][NUM_LEN+1];
  gint i;
968
  const guchar *s;
969
  
970
971
972
973
974
  /* We count 4, but store 3; so we can give an error
   * if there are 4.
   */
  num[0][0] = num[1][0] = num[2][0] = num[3][0] = '\0';
  
Martin Baulig's avatar
Martin Baulig committed
975
  s = (const guchar *) str;
976
977
978
  pt->num_ints = 0;
  while (*s && pt->num_ints < 4) 
    {
979
      
980
      i = 0;
981
      while (*s && g_ascii_isdigit (*s) && i < NUM_LEN)
982
983
984
985
986
        {
          num[pt->num_ints][i] = *s;
          ++s; 
          ++i;
        }
987
      
988
989
990
991
992
      if (i > 0) 
        {
          num[pt->num_ints][i] = '\0';
          ++(pt->num_ints);
        }
993
      
994
      if (*s == '\0') break;
995
      
996
997
998
999
1000
1001
      ++s;
    }
  
  pt->n[0] = pt->num_ints > 0 ? atoi (num[0]) : 0;
  pt->n[1] = pt->num_ints > 1 ? atoi (num[1]) : 0;
  pt->n[2] = pt->num_ints > 2 ? atoi (num[2]) : 0;
1002
  
1003
  pt->month = G_DATE_BAD_MONTH;
1004
  
1005
1006
  if (pt->num_ints < 3)
    {
1007
      gsize longest = 0;
1008
1009
      gchar *casefold;
      gchar *normalized;
1010
      
1011
1012
      casefold = g_utf8_casefold (str, -1);
      normalized = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
1013
1014
      g_free (casefold);

1015
      for (i = 1; i < 13; ++i)
1016
        {
1017
1018
          /* Here month names may be in a genitive case if the language
           * grammatical rules require it.
1019
1020
1021
           * Examples of how January may look in some languages:
           * Catalan: "de gener", Croatian: "siječnja", Polish: "stycznia",
           * Upper Sorbian: "januara".
1022
1023
1024
           * Note that most of the languages can't or don't use the the
           * genitive case here so they use nominative everywhere.
           * For example, English always uses "January".
1025
           */
1026
1027
          if (update_month_match (&longest, normalized, long_month_names[i]))
            pt->month = i;
1028
1029
1030
1031
1032
1033

          /* Here month names will be in a nominative case.
           * Examples of how January may look in some languages:
           * Catalan: "gener", Croatian: "Siječanj", Polish: "styczeń",
           * Upper Sorbian: "Januar".
           */
1034
1035
          if (update_month_match (&longest, normalized, long_month_names_alternative[i]))
            pt->month = i;
1036
1037
1038
1039
1040

          /* Differences between abbreviated nominative and abbreviated
           * genitive month names are visible in very few languages but
           * let's handle them.
           */
1041
1042
          if (update_month_match (&longest, normalized, short_month_names[i]))
            pt->month = i;
1043

1044
1045
          if (update_month_match (&longest, normalized, short_month_names_alternative[i]))
            pt->month = i;
1046
1047
1048
        }

      g_free (normalized);
1049
1050
1051
    }
}

1052
/* HOLDS: g_date_global_lock */
1053
static void
1054
1055
g_date_prepare_to_parse (const gchar      *str, 
                         GDateParseTokens *pt)
1056
1057
1058
1059
{
  const gchar *locale = setlocale (LC_TIME, NULL);
  gboolean recompute_localeinfo = FALSE;
  GDate d;
1060
  
1061
  g_return_if_fail (locale != NULL); /* should not happen */
1062
  
1063
  g_date_clear (&d, 1);              /* clear for scratch use */
1064
  
1065
  if ( (current_locale == NULL) || (strcmp (locale, current_locale) != 0) ) 
1066
    recompute_localeinfo = TRUE;  /* Uh, there used to be a reason for the temporary */
1067
1068
1069
1070
1071
1072
  
  if (recompute_localeinfo)
    {
      int i = 1;
      GDateParseTokens testpt;
      gchar buf[128];
1073
      
1074
      g_free (current_locale); /* still works if current_locale == NULL */
1075
      
1076
      current_locale = g_strdup (locale);
1077
      
1078
1079
1080
      short_month_names[0] = "Error";
      long_month_names[0] = "Error";

1081
1082
      while (i < 13) 
        {
1083
1084
	  gchar *casefold;
	  
1085
          g_date_set_dmy (&d, 1, i, 1976);
1086
	  
1087
          g_return_if_fail (g_date_valid (&d));
1088
	  
1089
          g_date_strftime (buf, 127, "%b", &d);
1090

1091
	  casefold = g_utf8_casefold (buf, -1);
1092
          g_free (short_month_names[i]);
1093
          short_month_names[i] = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
1094
	  g_free (casefold);
1095
	  
1096
          g_date_strftime (buf, 127, "%B", &d);
1097
	  casefold = g_utf8_casefold (buf, -1);
1098
          g_free (long_month_names[i]);
1099
          long_month_names[i] = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
1100
	  g_free (casefold);
1101
          
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
          g_date_strftime (buf, 127, "%Ob", &d);
          casefold = g_utf8_casefold (buf, -1);
          g_free (short_month_names_alternative[i]);
          short_month_names_alternative[i] = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
          g_free (casefold);

          g_date_strftime (buf, 127, "%OB", &d);
          casefold = g_utf8_casefold (buf, -1);
          g_free (long_month_names_alternative[i]);
          long_month_names_alternative[i] = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
          g_free (casefold);

1114
1115
          ++i;
        }
1116
      
1117
      /* Determine DMY order */
1118
      
1119
1120
1121
      /* had to pick a random day - don't change this, some strftimes
       * are broken on some days, and this one is good so far. */
      g_date_set_dmy (&d, 4, 7, 1976);
1122
1123
1124
1125
      
      g_date_strftime (buf, 127, "%x", &d);
      
      g_date_fill_parse_tokens (buf, &testpt);
1126
1127
1128
1129
1130
1131

      using_twodigit_years = FALSE;
      locale_era_adjust = 0;
      dmy_order[0] = G_DATE_DAY;
      dmy_order[1] = G_DATE_MONTH;
      dmy_order[2] = G_DATE_YEAR;
1132
1133
1134
1135
1136
1137
1138
      
      i = 0;
      while (i < testpt.num_ints)
        {
          switch (testpt.n[i])
            {
            case 7:
1139
              dmy_order[i] = G_DATE_MONTH;
1140
1141
              break;
            case 4:
1142
              dmy_order[i] = G_DATE_DAY;
1143
1144
              break;
            case 76:
1145
1146
              using_twodigit_years = TRUE;
              G_GNUC_FALLTHROUGH;
1147
            case 1976:
1148
              dmy_order[i] = G_DATE_YEAR;
1149
1150
              break;
            default:
1151
1152
1153
              /* assume locale era */
              locale_era_adjust = 1976 - testpt.n[i];
              dmy_order[i] = G_DATE_YEAR;
1154
1155
1156
1157
              break;
            }
          ++i;
        }
1158
      
Dan Winship's avatar
Dan Winship committed
1159
#if defined(G_ENABLE_DEBUG) && 0
1160
      DEBUG_MSG (("**GDate prepared a new set of locale-specific parse rules."));
1161
1162
1163
      i = 1;
      while (i < 13) 
        {
1164
          DEBUG_MSG (("  %s   %s", long_month_names[i], short_month_names[i]));
1165
1166
          ++i;
        }
1167
1168
1169
1170
1171
1172
1173
      DEBUG_MSG (("Alternative month names:"));
      i = 1;
      while (i < 13)
        {
          DEBUG_MSG (("  %s   %s", long_month_names_alternative[i], short_month_names_alternative[i]));
          ++i;
        }
1174
      if (using_twodigit_years)
Matthias Clasen's avatar
Matthias Clasen committed
1175
1176
1177
        {
	  DEBUG_MSG (("**Using twodigit years with cutoff year: %u", twodigit_start_year));
        }
1178
1179
1180
1181
1182
      { 
        gchar *strings[3];
        i = 0;
        while (i < 3)
          {
1183
            switch (dmy_order[i])