aboutsummaryrefslogtreecommitdiff
path: root/src/lib9/tm2sec.c
blob: 58bbe992705c9e362f93099c2a9b9127c09d0e16 (plain)
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <u.h>
#include <libc.h>

#include "zoneinfo.h"

#define SEC2MIN 60L
#define SEC2HOUR (60L*SEC2MIN)
#define SEC2DAY (24L*SEC2HOUR)

/*
 *  days per month plus days/year
 */
static	int	dmsize[] =
{
	365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
static	int	ldmsize[] =
{
	366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

/*
 *  return the days/month for the given year
 */
static int *
yrsize(int y)
{
	if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
		return ldmsize;
	else
		return dmsize;
}

/*
 * compute seconds since Jan 1 1970 GMT
 * and convert to our timezone.
 */
long
tm2sec(Tm *tm)
{
	Tinfo ti0, ti1, *ti;
	long secs;
	int i, yday, year, *d2m;

	secs = 0;

	/*
	 *  seconds per year
	 */
	year = tm->year + 1900;
	for(i = 1970; i < year; i++){
		d2m = yrsize(i);
		secs += d2m[0] * SEC2DAY;
	}

	/*
	 *  if mday is set, use mon and mday to compute yday
	 */
	if(tm->mday){
		yday = 0;
		d2m = yrsize(year);
		for(i=0; i<tm->mon; i++)
			yday += d2m[i+1];
		yday += tm->mday-1;
	}else{
		yday = tm->yday;
	}
	secs += yday * SEC2DAY;

	/*
	 * hours, minutes, seconds
	 */
	secs += tm->hour * SEC2HOUR;
	secs += tm->min * SEC2MIN;
	secs += tm->sec;

	/*
	 * Assume the local time zone if zone is not GMT
	 */
	if(strcmp(tm->zone, "GMT") != 0) {
		i = zonelookuptinfo(&ti0, secs);
		ti = &ti0;
		if (i != -1)
		if (ti->tzoff!=0) {
			/*
			 * to what local time period `secs' belongs?
			 */
			if (ti->tzoff>0) {
				/*
				 * east of GMT; check previous local time transition
				 */
				if (ti->t+ti->tzoff > secs)
				if (zonetinfo(&ti1, i-1)!=-1)
					ti = &ti1;
			} else
				/*
				 * west of GMT; check next local time transition
				 */
				if (zonetinfo(&ti1, i+1))
				if (ti1.t+ti->tzoff < secs)
					ti = &ti1;
//			fprint(2, "tt: %ld+%d %ld\n", (long)ti->t, ti->tzoff, (long)secs);
			secs -= ti->tzoff;
		}
	}

	if(secs < 0)
		secs = 0;
	return secs;
}