-
Notifications
You must be signed in to change notification settings - Fork 0
/
date.c
140 lines (122 loc) · 3.32 KB
/
date.c
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <stdlib.h>
#include <stdio.h>
#include "date.h"
static time_t fake_time = 0;
time_t date_now(void)
{
return (fake_time?fake_time:time((time_t*)NULL));
}
void date_set_time(char *s)
{
fake_time = date_parse(s,TIME_CURRENT);
if (fake_time < 0) fake_time = 0;
return;
}
/* return time_t at end of current day */
time_t date_now_eod(void)
{
struct tm* tm;
time_t nowtime;
nowtime = date_now();
tm = localtime(&nowtime);
tm->tm_hour = 23;
tm->tm_min = 59;
tm->tm_sec = 59;
return mktime(tm);
}
/* Parse date in the form dd/mm[/yyyy] If eod is non-zero, returned
* time is set at end of day (23:59:59), otherwise current time of day
* is used.
*/
time_t date_parse(char *s, int eod)
{
int nread, now_year, century;
struct tm* date;
time_t nowtime;
nowtime = (eod?date_now_eod():date_now());
date = localtime(&nowtime);
now_year = date->tm_year;
century = date->tm_year%100;
nread = sscanf(s,"%d/%d/%d",&(date->tm_mday),&(date->tm_mon),
&(date->tm_year));
if (nread == EOF || nread < 2 ) return 0; /* not a date */
if (nread == 3) {
if (date->tm_year < 100 && date->tm_year != 0) {
/* two digit year specified */
date->tm_year += century*100;
}
else {
date->tm_year -= 1900;
}
}
if ((date->tm_mday < 1 || date->tm_mday > 31) ||
(date->tm_mon < 1 || date->tm_mon > 12)) return -1; /* malformed date */
date->tm_mon--;
/* let mktime figure out if date is dst */
date->tm_isdst = -1;
return mktime(date);
}
/* Convert periodic action time to current year and, if month is
* non-zero, current month */
time_t date_make_current(time_t t, int month)
{
struct tm* date;
time_t nowtime;
int cur_year, cur_mon, cur_mday;
nowtime = date_now();
date = localtime(&nowtime);
cur_year = date->tm_year;
cur_mon = date->tm_mon;
cur_mday = date->tm_mday;
date = localtime(&t);
date->tm_year = cur_year;
if (month) {
date->tm_mon = (date->tm_mday>=cur_mday)?cur_mon:cur_mon+1;
/* new month, different dst? */
date->tm_isdst = -1;
}
else {
time_t event_time = mktime(date);
if (difftime(event_time,nowtime) < 0) {
/* event_time in the past; push to next year, to allow for
* crossing year boundaries */
date->tm_year++;
}
}
return mktime(date);
}
time_t date_make_days_match(time_t t, int wday)
{
struct tm* st;
int day_diff;
st = localtime(&t);
day_diff = wday - st->tm_wday;
if (day_diff == 0) return t;
if (day_diff < 0) day_diff += 7;
st->tm_mday += day_diff;
return mktime(st);
}
enum {
DATESTRSIZE = 11,
DATEFULLSTRSIZE = 25
};
char* date_str(time_t t)
{
struct tm* st;
static char dstr[DATESTRSIZE];
st = localtime(&t);
snprintf(dstr,DATESTRSIZE,"%02d/%02d/%02d", st->tm_mday, st->tm_mon+1,
st->tm_year+1900);
return dstr;
}
char* date_full_str(time_t t)
{
struct tm* st;
static char dstr[DATEFULLSTRSIZE];
st = localtime(&t);
snprintf(dstr,DATEFULLSTRSIZE,"%02d/%02d/%02dT%02d:%02d:%02d %s",
st->tm_mday, st->tm_mon+1, st->tm_year+1900,
st->tm_hour, st->tm_min, st->tm_sec,
st->tm_zone);
return dstr;
}