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
|
#include "psitime.h"
#include <stdlib.h>
PsiTime::PsiTime(psi_timeval *_ptv, psi_timezone *_ptz) {
if (_ptv != 0L)
ptv = *_ptv;
if (_ptz != 0L) {
ptz = *_ptz;
ptzValid = true;
} else
ptzValid = false;
/* get our own timezone */
gettimeofday(NULL, &utz);
psi2unix();
}
PsiTime::~PsiTime() {
}
void PsiTime::setUnixTime(struct timeval *_utv) {
if (_utv != 0L)
utv = *_utv;
unix2psi();
}
void PsiTime::setUnixNow(void) {
gettimeofday(&utv, &utz);
unix2psi();
}
void PsiTime::setPsiTime(psi_timeval *_ptv) {
if (_ptv != 0L)
ptv = *_ptv;
psi2unix();
}
void PsiTime::setPsiZone(psi_timezone *_ptz) {
if (_ptz != 0L) {
ptz = *_ptz;
ptzValid = true;
}
psi2unix();
}
struct timeval &PsiTime::getTimeval(void) {
return utv;
}
time_t PsiTime::getTime(void) {
return utv.tv_sec;
}
psi_timeval &PsiTime::getPsiTimeval(void) {
return ptv;
}
ostream &operator<<(ostream &s, const PsiTime &t) {
const char *fmt = "%c";
char buf[100];
strftime(buf, sizeof(buf), fmt, localtime(&t.utv.tv_sec));
s << buf;
return s;
}
/**
* The difference between
* EPOC epoch (01.01.0001 00:00:00)
* and Unix epoch (01.01.1970 00:00:00)
* in microseconds.
*/
#define EPOCH_DIFF 0x00dcddb30f2f8000ULL
static unsigned long long
evalOffset(psi_timezone ptz, bool valid) {
unsigned long long offset = 0;
if (valid) {
offset = ptz.utc_offset;
if ((ptz.dst_zones & 0x40000000) || (ptz.dst_zones & ptz.home_zone))
offset += 3600;
} else {
const char *offstr = getenv("PSI_TZ");
if (offstr != 0L) {
char *err = 0L;
offset = strtoul(offstr, &err, 0);
if (err != 0L)
offset = 0;
}
}
offset *= 1000000;
return offset;
}
void PsiTime::psi2unix(void) {
unsigned long long micro = ptv.tv_high;
micro = (micro << 32) | ptv.tv_low;
/* Substract Psion's idea of UTC offset */
micro -= evalOffset(ptz, ptzValid);
micro -= EPOCH_DIFF;
utv.tv_sec = micro / 1000000;
utv.tv_usec = micro % 1000000;
}
void PsiTime::unix2psi(void) {
unsigned long long micro = utv.tv_sec * 1000000 + utv.tv_usec;
/* Add Psion's idea of UTC offset */
micro += EPOCH_DIFF;
micro += evalOffset(ptz, ptzValid);
ptv.tv_low = micro & 0x0ffffffff;
ptv.tv_high = (micro >> 32) & 0x0ffffffff;
}
|