File: gmtime.h

package info (click to toggle)
dateutils 0.4.3-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 4,924 kB
  • sloc: ansic: 22,097; makefile: 1,666; yacc: 198; sh: 168; lex: 108
file content (95 lines) | stat: -rw-r--r-- 2,379 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/* metaprogramming */
#if !defined INCLUDED_gmtime_h_
#define INCLUDED_gmtime_h_
#include <stdint.h>

/* UTC has a constant day length */
#define UTC_SECS_PER_DAY	(86400)

static void
ffff_gmtime(struct tm *tm, const time_t t)
{
	static uint16_t __mon_yday[] = {
		/* this is \sum ml,
		 * first element is a bit set of leap days to add */
		0xfff8, 0,
		31, 59, 90, 120, 151, 181,
		212, 243, 273, 304, 334, 365
	};
	register int days;
	register unsigned int yy;
	const uint16_t *ip;
#if defined FFFF_GMTIME_SUBDAY
	int secs;
#endif	/* FFFF_GMTIME_SUBDAY */

	/* just go to day computation */
	days = (int)(t / UTC_SECS_PER_DAY);
#if defined FFFF_GMTIME_SUBDAY
	secs = (int)(t % UTC_SECS_PER_DAY);
#endif	/* FFFF_GMTIME_SUBDAY */
	/* week day computation, that one's easy, 1 jan '70 was Thu */
	tm->tm_wday = (days + 4) % GREG_DAYS_P_WEEK;

	/* gotta do the date now */
	yy = 1970;
	/* stolen from libc */
#define DIV(a, b)		((a) / (b))
/* we only care about 1901 to 2099 and there are no bullshit leap years */
#define LEAPS_TILL(y)		(DIV(y, 4))
	while (days < 0 || days >= (!__leapp(yy) ? 365 : 366)) {
		/* Guess a corrected year, assuming 365 days per year. */
		register unsigned int yg = yy + days / 365 - (days % 365 < 0);

		/* Adjust DAYS and Y to match the guessed year.  */
		days -= (yg - yy) * 365 +
			LEAPS_TILL(yg - 1) - LEAPS_TILL(yy - 1);
		yy = yg;
	}
	/* set the year */
	tm->tm_year = (int)yy;

	ip = __mon_yday;
	/* unrolled */
	yy = 13;
	if (days < ip[--yy] &&
	    days < ip[--yy] &&
	    days < ip[--yy] &&
	    days < ip[--yy] &&
	    days < ip[--yy] &&
	    days < ip[--yy] &&
	    days < ip[--yy] &&
	    days < ip[--yy] &&
	    days < ip[--yy] &&
	    days < ip[--yy] &&
	    days < ip[--yy]) {
		yy = 1;
	}
	/* set the rest of the tm structure */
	tm->tm_mday = days - ip[yy] + 1;
	tm->tm_yday = days;
	tm->tm_mon = (int)yy;
	/* fix up leap years */
	if (UNLIKELY(__leapp(tm->tm_year))) {
		if ((ip[0] >> (yy)) & 1) {
			if (UNLIKELY(tm->tm_yday == 59)) {
				tm->tm_mon = 2;
				tm->tm_mday = 29;
			} else if (UNLIKELY(tm->tm_yday == ip[yy])) {
				tm->tm_mday = tm->tm_yday - ip[--tm->tm_mon];
			} else {
				tm->tm_mday--;
			}
		}
	}
#if defined FFFF_GMTIME_SUBDAY
	tm->tm_sec = secs % 60U;
	secs /= 60U;
	tm->tm_min = secs % 60U;
	secs /= 60U;
	tm->tm_hour = secs;
#endif	/* FFFF_GMTIME_SUBDAY */
	return;
}

#endif	/* INCLUDED_gmtime_h_ */