Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | # Functions for dealing with dates and times. |
2 | ||
3 | import re | |
4 | import string | |
5 | ||
6 | def timestringtoseconds(text, separator = ':'): | |
7 | inputList = string.split(string.strip(text), separator) | |
8 | if len(inputList) != 3: | |
9 | raise ValueError, 'invalid value: ' + text | |
10 | ||
11 | sign = 1 | |
12 | if len(inputList[0]) > 0 and inputList[0][0] in ('+', '-'): | |
13 | if inputList[0][0] == '-': | |
14 | sign = -1 | |
15 | inputList[0] = inputList[0][1:] | |
16 | ||
17 | if re.search('[^0-9]', string.join(inputList, '')) is not None: | |
18 | raise ValueError, 'invalid value: ' + text | |
19 | ||
20 | hour = string.atoi(inputList[0]) | |
21 | minute = string.atoi(inputList[1]) | |
22 | second = string.atoi(inputList[2]) | |
23 | ||
24 | if minute >= 60 or second >= 60: | |
25 | raise ValueError, 'invalid value: ' + text | |
26 | return sign * (hour * 60 * 60 + minute * 60 + second) | |
27 | ||
28 | _year_pivot = 50 | |
29 | _century = 2000 | |
30 | ||
31 | def setyearpivot(pivot, century = None): | |
32 | global _year_pivot | |
33 | global _century | |
34 | oldvalues = (_year_pivot, _century) | |
35 | _year_pivot = pivot | |
36 | if century is not None: | |
37 | _century = century | |
38 | return oldvalues | |
39 | ||
40 | def datestringtojdn(text, format = 'ymd', separator = '/'): | |
41 | inputList = string.split(string.strip(text), separator) | |
42 | if len(inputList) != 3: | |
43 | raise ValueError, 'invalid value: ' + text | |
44 | ||
45 | if re.search('[^0-9]', string.join(inputList, '')) is not None: | |
46 | raise ValueError, 'invalid value: ' + text | |
47 | formatList = list(format) | |
48 | day = string.atoi(inputList[formatList.index('d')]) | |
49 | month = string.atoi(inputList[formatList.index('m')]) | |
50 | year = string.atoi(inputList[formatList.index('y')]) | |
51 | ||
52 | if _year_pivot is not None: | |
53 | if year >= 0 and year < 100: | |
54 | if year <= _year_pivot: | |
55 | year = year + _century | |
56 | else: | |
57 | year = year + _century - 100 | |
58 | ||
59 | jdn = ymdtojdn(year, month, day) | |
60 | if jdntoymd(jdn) != (year, month, day): | |
61 | raise ValueError, 'invalid value: ' + text | |
62 | return jdn | |
63 | ||
64 | def _cdiv(a, b): | |
65 | # Return a / b as calculated by most C language implementations, | |
66 | # assuming both a and b are integers. | |
67 | ||
68 | if a * b > 0: | |
69 | return a / b | |
70 | else: | |
71 | return -(abs(a) / abs(b)) | |
72 | ||
73 | def ymdtojdn(year, month, day, julian = -1, papal = 1): | |
74 | ||
75 | # set Julian flag if auto set | |
76 | if julian < 0: | |
77 | if papal: # Pope Gregory XIII's decree | |
78 | lastJulianDate = 15821004L # last day to use Julian calendar | |
79 | else: # British-American usage | |
80 | lastJulianDate = 17520902L # last day to use Julian calendar | |
81 | ||
82 | julian = ((year * 100L) + month) * 100 + day <= lastJulianDate | |
83 | ||
84 | if year < 0: | |
85 | # Adjust BC year | |
86 | year = year + 1 | |
87 | ||
88 | if julian: | |
89 | return 367L * year - _cdiv(7 * (year + 5001L + _cdiv((month - 9), 7)), 4) + \ | |
90 | _cdiv(275 * month, 9) + day + 1729777L | |
91 | else: | |
92 | return (day - 32076L) + \ | |
93 | _cdiv(1461L * (year + 4800L + _cdiv((month - 14), 12)), 4) + \ | |
94 | _cdiv(367 * (month - 2 - _cdiv((month - 14), 12) * 12), 12) - \ | |
95 | _cdiv((3 * _cdiv((year + 4900L + _cdiv((month - 14), 12)), 100)), 4) + \ | |
96 | 1 # correction by rdg | |
97 | ||
98 | def jdntoymd(jdn, julian = -1, papal = 1): | |
99 | ||
100 | # set Julian flag if auto set | |
101 | if julian < 0: | |
102 | if papal: # Pope Gregory XIII's decree | |
103 | lastJulianJdn = 2299160L # last jdn to use Julian calendar | |
104 | else: # British-American usage | |
105 | lastJulianJdn = 2361221L # last jdn to use Julian calendar | |
106 | ||
107 | julian = (jdn <= lastJulianJdn); | |
108 | ||
109 | x = jdn + 68569L | |
110 | if julian: | |
111 | x = x + 38 | |
112 | daysPer400Years = 146100L | |
113 | fudgedDaysPer4000Years = 1461000L + 1 | |
114 | else: | |
115 | daysPer400Years = 146097L | |
116 | fudgedDaysPer4000Years = 1460970L + 31 | |
117 | ||
118 | z = _cdiv(4 * x, daysPer400Years) | |
119 | x = x - _cdiv((daysPer400Years * z + 3), 4) | |
120 | y = _cdiv(4000 * (x + 1), fudgedDaysPer4000Years) | |
121 | x = x - _cdiv(1461 * y, 4) + 31 | |
122 | m = _cdiv(80 * x, 2447) | |
123 | d = x - _cdiv(2447 * m, 80) | |
124 | x = _cdiv(m, 11) | |
125 | m = m + 2 - 12 * x | |
126 | y = 100 * (z - 49) + y + x | |
127 | ||
128 | # Convert from longs to integers. | |
129 | yy = int(y) | |
130 | mm = int(m) | |
131 | dd = int(d) | |
132 | ||
133 | if yy <= 0: | |
134 | # Adjust BC years. | |
135 | yy = yy - 1 | |
136 | ||
137 | return (yy, mm, dd) | |
138 | ||
139 | def stringtoreal(text, separator = '.'): | |
140 | if separator != '.': | |
141 | if string.find(text, '.') >= 0: | |
142 | raise ValueError, 'invalid value: ' + text | |
143 | index = string.find(text, separator) | |
144 | if index >= 0: | |
145 | text = text[:index] + '.' + text[index + 1:] | |
146 | return string.atof(text) |