93
93
return ((double) s_val.tv_sec + 0.000001 * s_val.tv_usec);
94
94
} /* End ink_time_wall_seconds */
96
/*===========================================================================*
98
High-Level Date Processing
100
*===========================================================================*/
102
/*---------------------------------------------------------------------------*
104
int ink_time_gmt_string_to_tm(char *string, struct tm *broken_down_time)
106
This routine takes an ASCII string representation of a date <string> in one
107
of several formats, converts the string to a calendar time, and stores the
108
calendar time through the pointer <broken_down_time>.
110
This routine currently attempts to support RFC 1123 format, RFC 850
111
format, and asctime() format. The times are expected to be in GMT time.
113
If the string is successfully parsed and converted to a date, the number
114
of characters processed from the string is returned (useful for scanning
115
over a string), otherwise 0 is returned.
117
*---------------------------------------------------------------------------*/
119
ink_time_gmt_string_to_tm(char *string, struct tm *bdt)
123
/* This declaration isn't being found in time.h for some reason */
127
/* Try RFC 1123 Format */
130
result = strptime(string, (char *) "%a, %d %b %Y %T GMT", bdt);
132
result = strptime(string, (char *) "%a, %d %b %Y %T UTC", bdt);
134
/* Try RFC 850 Format */
137
result = strptime(string, (char *) "%A, %d-%b-%y %T GMT", bdt);
139
result = strptime(string, (char *) "%A, %d-%b-%y %T UTC", bdt);
141
/* Try asctime() Format */
144
result = strptime(string, (char *) "%a %b %d %T %Y", bdt);
148
/* If No Success, You Lose, Pal */
153
return (result - string);
154
} /* End ink_time_gmt_string_to_tm */
157
/*---------------------------------------------------------------------------*
159
int ink_time_gmt_tm_to_rfc1123_string(struct tm *t, char *string, int maxsize)
161
This routine takes a calendar time <tm> in universal time, and converts
162
the time to an RFC 1123 formatted string as in "Sun, 06 Nov 1994 08:49:37 GMT",
163
which is placed in the string <string> up to <maxsize> bytes. 1 is
164
returned on success, else 0.
166
*---------------------------------------------------------------------------*/
168
ink_time_gmt_tm_to_rfc1123_string(struct tm *t, char *string, int maxsize)
172
size = strftime(string, maxsize, "%a, %d %b %Y %T GMT", t);
179
} /* End ink_time_gmt_tm_to_rfc1123_string */
182
/*---------------------------------------------------------------------------*
184
InkTimeDayID ink_time_tm_to_dayid(struct tm *t)
186
This routine takes a broken-down time <t>, and converts it to an
187
InkTimeDayID <dayid>, representing an integer number of days since a base.
189
*---------------------------------------------------------------------------*/
191
ink_time_tm_to_dayid(struct tm * t)
196
ink_time_tm_to_mdy(t, &m, &dom, &y);
197
dayid = ink_time_mdy_to_dayid(m, dom, y);
199
} /* End ink_time_tm_to_dayid */
202
/*---------------------------------------------------------------------------*
204
void ink_time_dump_dayid(FILE *fp, InkTimeDayID dayid)
206
This routine prints an ASCII representation of <dayid> onto the file
209
*---------------------------------------------------------------------------*/
211
ink_time_dump_dayid(FILE * fp, InkTimeDayID dayid)
215
ink_time_dayid_to_mdy(dayid, &m, &d, &y);
216
fprintf(fp, "dayid %d (%d/%d/%d)\n", dayid, m, d, y);
217
} /* End ink_time_dump_dayid */
220
/*---------------------------------------------------------------------------*
222
void ink_time_dayid_to_tm(InkTimeDayID dayid, struct tm *t)
224
This routine takes an InkTimeDayID <dayid>, representing an integer number
225
of days since a base, and computes a broken-down time <t>.
227
*---------------------------------------------------------------------------*/
229
ink_time_dayid_to_tm(InkTimeDayID dayid, struct tm *t)
233
ink_time_dayid_to_mdy(dayid, &m, &dom, &y);
234
ink_time_mdy_to_tm(m, dom, y, t);
235
} /* End ink_time_dayid_to_tm */
238
/*---------------------------------------------------------------------------*
240
InkTimeDayRange ink_time_dayid_to_dayrange(InkTimeDayID dayid, unsigned int width)
242
This routine takes a <dayid> representing a particular day, and returns
243
an InkTimeDayRange object of width <width> that spans the day in question.
245
*---------------------------------------------------------------------------*/
247
ink_time_dayid_to_dayrange(InkTimeDayID dayid, unsigned int width)
249
InkTimeDayRange range;
251
range.base = dayid - (dayid % width);
254
} /* End ink_time_dayid_to_dayrange */
257
/*---------------------------------------------------------------------------*
259
InkTimeDayRange ink_time_chomp_off_mouthful_of_dayrange
260
(InkTimeDayRange *dayrange_ptr, unsigned int biggest_width)
262
This routine takes a dayrange pointer <dayrange_ptr>, and bites off the
263
biggest possible chunk of the dayrange pointed to by <dayrange_ptr>
264
which is less than or equal to <biggest_width> and whose chunk is
265
"chomp aligned", meaning that the start of the dayrange chunk starts on
266
a multiple of the width.
268
The value <biggest_width> must be a positive power of two.
270
On exit, the chunk chomped off will be returned, and the original
271
dayrange pointed to by <dayrange_ptr> will be modified to consist of
272
the data after the chunk that was chopped off.
274
If the dayrange pointed to by <dayrange_ptr> has no size, a dayrange
275
of size 0 is returned, and the original data is unmodified.
277
The purpose of this routine is to decompose a range of consecutive days
278
into a collection of variable-sized, disjoint day ranges which cover the
279
original space of days.
281
*---------------------------------------------------------------------------*/
283
ink_time_chomp_off_mouthful_of_dayrange(InkTimeDayRange * dayrange_ptr, unsigned int biggest_width)
286
InkTimeDayRange chomped_chunk;
288
chomped_chunk.base = dayrange_ptr->base;
290
for (width = biggest_width; width >= 1; width = width / 2) {
291
if ((width <= dayrange_ptr->width) && ((dayrange_ptr->base % width) == 0)) {
292
chomped_chunk.width = width;
294
dayrange_ptr->base += width;
295
dayrange_ptr->width -= width;
297
return (chomped_chunk);
301
chomped_chunk.width = 0;
303
return (chomped_chunk);
304
} /* End ink_time_chomp_off_mouthful_of_dayrange */
307
/*---------------------------------------------------------------------------*
309
char *ink_time_dayrange_to_string(InkTimeDayRange *dayrange_ptr, char *buf)
311
This routine take a day range pointer <dayrange_ptr>, and places a string
312
representation of the day range in the buffer <buf>. The buffer must be
313
big enough to hold the representation of the dayrange.
315
Of course, you shouldn't have any idea what the representation is, so I
316
guess you're hosed. Something like 64 characters is probably reasonable.
318
The pointer <buf> is returned.
320
*---------------------------------------------------------------------------*/
322
ink_time_dayrange_to_string(InkTimeDayRange * dayrange_ptr, char *buf, const size_t bufSize)
328
snprintf(buf, bufSize, "range_start_%d_width_%u", dayrange_ptr->base, dayrange_ptr->width);
330
} /* End ink_time_dayrange_to_string */
333
/*===========================================================================*
335
Date Conversion Routines
337
Note that both the day of month and the month number start at 1 not zero,
338
so January 1 is <m=1,d=1> not <m=0,d=0>.
340
*===========================================================================*/
342
static int _base_day = 4; /* 1/1/1970 is Thursday */
343
static int _base_year = 1970;
345
static int _base_daysinmonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
347
static const char *_day_names[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
348
static const char *_month_names[12] = {
349
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
350
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
354
/*---------------------------------------------------------------------------*
356
void ink_time_current_mdy(int *m, int *dom, int *y)
358
Gets the current local date in GMT, and returns the month, day of month,
361
*---------------------------------------------------------------------------*/
363
ink_time_current_mdy(int *m, int *dom, int *y)
368
ink_gmtime_r(&c, &t);
369
ink_time_tm_to_mdy(&t, m, dom, y);
370
} /* End ink_time_current_mdy */
373
/*---------------------------------------------------------------------------*
375
void ink_time_tm_to_mdy(struct tm *t, int *m, int *dom, int *y)
377
Takes a broken down time pointer <t>, and returns the month, day of month,
380
*---------------------------------------------------------------------------*/
382
ink_time_tm_to_mdy(struct tm *t, int *m, int *dom, int *y)
386
*y = t->tm_year + 1900;
387
} /* End ink_time_tm_to_mdy */
390
/*---------------------------------------------------------------------------*
392
void ink_time_mdy_to_tm(int m, int dom, int y, struct tm *t)
394
Takes a month <m>, day of month <dom>, and year <y>, and places a
395
broken-down time in the structure pointed to by <t>.
397
*---------------------------------------------------------------------------*/
399
ink_time_mdy_to_tm(int m, int dom, int y, struct tm *t)
401
bzero((char *) t, sizeof(*t));
404
t->tm_year = y - 1900;
405
t->tm_wday = ink_time_mdy_to_dow(m, dom, y);
406
t->tm_yday = ink_time_mdy_to_doy(m, dom, y);
407
} /* End ink_time_mdy_to_tm */
410
/*---------------------------------------------------------------------------*
412
InkTimeDayID ink_time_mdy_to_dayid(int m, int dom, int y)
414
Return a single integer representing encoding of the day <m> <dom>, <y>.
415
The encoding is performed with respect to the base day.
417
*---------------------------------------------------------------------------*/
419
ink_time_mdy_to_dayid(int m, int dom, int y)
425
for (year = _base_year; year < y; year++)
426
dayid = dayid + ink_time_days_in_year(year);
427
for (month = 1; month < m; month++)
428
dayid = dayid + ink_time_days_in_month(month, year);
429
dayid = dayid + dom - 1;
431
} /* End ink_time_mdy_to_dayid */
434
/*---------------------------------------------------------------------------*
436
InkTimeDayID ink_time_current_dayid()
438
Return a single integer representing encoding of the today's date.
439
The encoding is performed with respect to the base day.
441
*---------------------------------------------------------------------------*/
443
ink_time_current_dayid()
446
int today_m, today_d, today_y;
448
ink_time_current_mdy(&today_m, &today_d, &today_y);
449
today = ink_time_mdy_to_dayid(today_m, today_d, today_y);
452
} /* End ink_time_current_dayid */
455
/*---------------------------------------------------------------------------*
457
void ink_time_dayid_to_mdy(InkTimeDayID dayid, int *mp, int *dp, int *yp)
459
Takes a single integer representation of the date, and convert to the
460
month <m>, day of month <dom>, and year <y>.
462
*---------------------------------------------------------------------------*/
464
ink_time_dayid_to_mdy(InkTimeDayID dayid, int *mp, int *dp, int *yp)
467
for (*yp = _base_year; ink_time_days_in_year(*yp) < dayid; (*yp)++)
468
dayid = dayid - ink_time_days_in_year(*yp);
469
for (*mp = 1; ink_time_days_in_month(*mp, *yp) < dayid; (*mp)++)
470
dayid = dayid - ink_time_days_in_month(*mp, *yp);
472
} /* End ink_time_dayid_to_mdy */
475
/*---------------------------------------------------------------------------*
477
int ink_time_mdy_to_doy(int m, int dom, int y)
479
Takes a date <m> <dom> <y>, and returns the number of days into year <y>.
481
*---------------------------------------------------------------------------*/
483
ink_time_mdy_to_doy(int m, int dom, int y)
485
InkTimeDayID first, current;
487
first = ink_time_mdy_to_dayid(1, 1, y);
488
current = ink_time_mdy_to_dayid(m, dom, y);
489
return (current - first);
490
} /* End ink_time_mdy_to_doy */
493
/*---------------------------------------------------------------------------*
495
void ink_time_doy_to_mdy(int doy, int year, int *mon, int *dom, int *dow)
497
This routine take a <year>, and a zero-based <doy> within the year,
498
and determines the corresponding month, day of month, and day of week.
500
*---------------------------------------------------------------------------*/
502
ink_time_doy_to_mdy(int doy, int year, int *mon, int *dom, int *dow)
504
int month, daysinmonth, days_so_far, next_days_so_far;
507
for (month = 1; month <= 12; month++) {
508
daysinmonth = ink_time_days_in_month(month, year);
509
next_days_so_far = days_so_far + daysinmonth;
510
if (doy >= days_so_far && doy < next_days_so_far) {
512
*dom = doy - days_so_far + 1;
513
*dow = ink_time_mdy_to_dow(month, *dom, year);
516
days_so_far = next_days_so_far;
518
} /* End ink_time_doy_to_mdy */
521
/*---------------------------------------------------------------------------*
523
int ink_time_mdy_to_dow(int month, int dom, int year)
525
What day of the week does <month> <dom>, <year> fall on?
527
*---------------------------------------------------------------------------*/
529
ink_time_mdy_to_dow(int month, int dom, int year)
533
base = ink_time_first_day_of_year(year);
534
for (i = 0; i < month - 1; i++) {
535
base = (base + ink_time_days_in_month(i + 1, year)) % 7;
537
return ((base + dom - 1) % 7);
538
} /* End ink_time_mdy_to_dow */
541
/*---------------------------------------------------------------------------*
543
int ink_time_days_in_month(int month, int year)
545
This routine returns the number of days in a particular <month> and <year>.
547
*---------------------------------------------------------------------------*/
549
ink_time_days_in_month(int month, int year)
551
return (_base_daysinmonth[month - 1] + (month == 2 ? ink_time_leap_year_correction(year) : 0));
552
} /* End ink_time_days_in_month */
555
/*---------------------------------------------------------------------------*
557
int ink_time_days_in_year(int year)
559
This routine returns the number of days in the year <year>, compensating
562
*---------------------------------------------------------------------------*/
564
ink_time_days_in_year(int year)
566
return (365 + ink_time_leap_year_correction(year));
567
} /* End ink_time_days_in_year */
570
/*---------------------------------------------------------------------------*
572
int ink_time_first_day_of_year(int year)
574
What day is January 1 on in this year?
576
*---------------------------------------------------------------------------*/
578
ink_time_first_day_of_year(int year)
583
if (year > _base_year) {
584
for (i = _base_year; i < year; i++)
585
base = (base + ink_time_days_in_year(i)) % 7;
586
} else if (year < _base_year) {
587
for (i = _base_year - 1; i >= year; i--)
588
base = ((base - ink_time_days_in_year(i)) % 7 + 7) % 7;
591
} /* End ink_time_first_day_of_year */
594
/*---------------------------------------------------------------------------*
596
void ink_time_day_to_string(int day, char *buffer)
598
This routine takes a day number and places a 3 character, NUL terminated
599
string representing this day in the buffer pointed to by <buffer>.
601
*---------------------------------------------------------------------------*/
603
ink_time_day_to_string(int day, char *buffer, const size_t bufferSize)
605
ink_strlcpy(buffer, _day_names[day], bufferSize);
606
} /* End ink_time_day_to_string */
609
/*---------------------------------------------------------------------------*
611
void ink_time_month_to_string(int month, char *buffer)
613
This routine takes a month number and places a 3 character, NUL terminated
614
string representing this day in the buffer pointed to by <buffer>.
616
*---------------------------------------------------------------------------*/
618
ink_time_month_to_string(int month, char *buffer, const size_t bufferSize)
620
ink_strlcpy(buffer, _month_names[month - 1], bufferSize);
621
} /* End ink_time_month_to_string */
624
/*---------------------------------------------------------------------------*
626
int ink_time_string_to_month(char *str)
628
This routine takes a name of a month <str>, and returns the corresponding
629
month number, else -1.
631
*---------------------------------------------------------------------------*/
633
ink_time_string_to_month(char *str)
637
for (i = 0; i < 12; i++) {
638
if (strcasecmp(str, _month_names[i]) == 0)
642
} /* End ink_time_string_to_month */
645
/*---------------------------------------------------------------------------*
647
int ink_time_leap_year_correction(int year)
649
Return 1 if <year> is a leap year, 0 if not, and -1 if negative leap year.
651
*---------------------------------------------------------------------------*/
653
ink_time_leap_year_correction(int year)
655
return (ink_time_is_4th_year(year) - ink_time_is_100th_year(year) + ink_time_is_400th_year(year));
656
} /* End ink_time_leap_year_correction */
658
/* asah #ifndef sun asah */
661
99
char *abbrev_month_names[12];
704
141
#define DAYS_OFFSET 25508
707
ink_gmtime_r(const ink_time_t * clock, struct tm *res)
709
static const char months[] = {
710
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
711
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
712
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
713
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4,
714
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
715
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5,
716
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
717
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
718
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
719
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7,
720
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
721
7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8,
722
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
723
8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9,
724
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
725
9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
726
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
727
10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
728
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
729
11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
730
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
731
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
732
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
734
static const int days[12] = {
735
305, 336, -1, 30, 60, 91, 121, 152, 183, 213, 244, 274
746
size_t hour = t % 24;
749
/* Jan 1, 1970 was a Thursday */
750
size_t wday = (4 + t) % 7;
752
/* guess the year and refine the guess */
754
size_t year = yday / 365 + 69;
756
d = dp = (year * 365) + (year / 4) - (year / 100) + (year / 100 + 3) / 4 - DAYS_OFFSET - 1;
761
dp = (year * 365) + (year / 4) - (year / 100) + (year / 100 + 3) / 4 - DAYS_OFFSET - 1;
764
/* convert the days */
769
size_t month = months[d];
773
size_t mday = d - days[month] - 1;
774
// year += 1900; real year
776
res->tm_sec = (int) sec;
777
res->tm_min = (int) min;
778
res->tm_hour = (int) hour;
779
res->tm_mday = (int) mday;
780
res->tm_mon = (int) month;
781
res->tm_year = (int) year;
782
res->tm_wday = (int) wday;
783
res->tm_yday = (int) yday;
790
144
convert_tm(const struct tm * tp)