1 /* Copyright (c) 1993 by Sanjay Ghemawat */
2 
3 #include <stddef.h>
4 #include <sys/types.h>
5 #include <math.h>
6 #include <string.h>
7 #include <stdlib.h>
8 
9 #include "config.h"
10 
11 #include "Month.h"
12 #include "WeekDay.h"
13 #include "Time_.h"
14 
15 /*
16  * Want to get high resolution for region of time that will be most
17  * heavily used.  This region will probably be around now. Therefore,
18  * rep will be number of seconds elapsed since we construct the first
19  * Time value for this run of the program.
20  */
21 
22 int    Time::initialized = 0;   /* Initialized yet? */
23 double Time::offset = 0.0;      /* Offset for time values */
24 int    Time::junkInt = 0;
25 
Initialize()26 void Time::Initialize() {
27     struct timeval buf;
28     gettimeofday(&buf, 0);
29 
30     offset = buf.tv_sec;
31     initialized = 1;
32 }
33 
Now()34 Time Time::Now() {
35     struct timeval buf;
36     gettimeofday(&buf, 0);
37     return Time(buf);
38 }
39 
BreakDownDate(int & mday,WeekDay & wday,Month & month,int & year)40 void Time::BreakDownDate(int& mday,WeekDay& wday,Month& month, int& year) const
41 {
42     this->BreakDown(mday, wday, month, year);
43 }
44 
BreakDownClock(int & hour,int & min,int & sec,int & milli)45 void Time::BreakDownClock(int& hour, int& min, int& sec, int& milli) const {
46     WeekDay junkWDay;
47     Month   junkMonth;
48 
49     BreakDown(junkInt,junkWDay,junkMonth,junkInt, hour, min, sec, milli);
50 }
51 
BreakDown(int & mday,WeekDay & wday,Month & month,int & year,int & hour,int & min,int & sec,int & milli,const char * tz)52 void Time::BreakDown(int& mday, WeekDay& wday, Month& month, int& year,
53                      int& hour, int& min, int& sec, int& milli,
54                      const char *tz) const
55 {
56     char *old;
57     if (! initialized) Initialize();
58 
59     time_t clock = (time_t) round(rep + offset);
60 
61     if (tz) {
62         if ((old=getenv("TZ"))) old=strdup(old);
63         setenv("TZ", tz, 1);
64         tzset();
65     }
66 
67     struct tm* t = localtime(&clock);
68 
69     if (tz) {
70         if (old) setenv("TZ", old, 1); else unsetenv("TZ");
71         tzset();
72         free(old);
73     }
74 
75     mday  = t->tm_mday;                         /* tm_mday in 1..31 */
76     wday  = WeekDay::Sunday() + t->tm_wday;     /* tm_wday in 0..6.  Sun = 0 */
77     month = Month::January() + t->tm_mon;       /* tm_mon  in 0..11. Jan = 0 */
78     year  = t->tm_year + 1900;
79     hour  = t->tm_hour;
80     min   = t->tm_min;
81     sec   = t->tm_sec;
82     milli = (int)round((rep - floor(rep)) * 1000);
83 }
84 
Time(const struct timeval & tv)85 Time::Time(const struct timeval& tv) {
86     if (! initialized) Initialize();
87     rep = (tv.tv_sec - offset) + ((double) tv.tv_usec) / 1000000.0;
88 }
89 
Convert(struct timeval & tv)90 void Time::Convert(struct timeval& tv) const {
91     if (! initialized) Initialize();
92 
93     tv.tv_sec  = (long) floor(rep + offset);
94     tv.tv_usec = (long) round((rep + offset - tv.tv_sec) * 1000000.0);
95 }
96 
97 #if 0
98 time_t timezone_to_local(time_t clock, const char *tz) {
99     const char *old=getenv("TZ");
100     if (old) old=strdupa(old);
101 
102     struct tm* t = localtime(&clock);
103     setenv("TZ", tz, 1);
104     tzset();
105 
106     clock = mktime(t);
107     if (old) setenv("TZ", old, 1); else unsetenv("TZ");
108     tzset();
109 
110     return clock;
111 }
112 
113 time_t local_to_timezone(time_t clock, const char *tz) {
114     const char *old=getenv("TZ");
115     if (old) old=strdupa(old);
116 
117     setenv("TZ", tz, 1);
118     tzset();
119     struct tm* t = localtime(&clock);
120 
121     if (old) setenv("TZ", old, 1); else unsetenv("TZ");
122     tzset();
123     clock = mktime(t);
124 
125     return clock;
126 }
127 #endif
128 
Duration(const struct timeval & tv)129 Duration::Duration(const struct timeval& tv) {
130     rep = tv.tv_sec + ((double) tv.tv_usec) / 1000000.0;
131 }
132 
Convert(struct timeval & tv)133 void Duration::Convert(struct timeval& tv) const {
134     tv.tv_sec  = (long) floor(rep);
135     tv.tv_usec = (long) round((rep - tv.tv_sec) / 1000000.0);
136 }
137