| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
=head1 NAME |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
Date::MSD - conversion between flavours of Mars Sol Date |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use Date::MSD qw(js_to_msd msd_to_cmsdnf cmsdn_to_js); |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
$msd = js_to_msd($js); |
|
10
|
|
|
|
|
|
|
($cmsdn, $cmsdf) = msd_to_cmsdnf($msd, $tz); |
|
11
|
|
|
|
|
|
|
$js = cmsdn_to_js($cmsdn, $cmsdf, $tz); |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# and 69 other conversion functions |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
For date and time calculations it is convenient to represent dates by |
|
18
|
|
|
|
|
|
|
a simple linear count of days, rather than in a particular calendar. |
|
19
|
|
|
|
|
|
|
This module performs conversions between different flavours of linear |
|
20
|
|
|
|
|
|
|
count of Martian solar days ("sols"). |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
Among Martian day count systems there are also some non-trivial |
|
23
|
|
|
|
|
|
|
differences of concept. There are systems that count only complete days, |
|
24
|
|
|
|
|
|
|
and those that count fractional days also. There are some that are fixed |
|
25
|
|
|
|
|
|
|
to Airy Mean Time (time on the Martian prime meridian), and others that |
|
26
|
|
|
|
|
|
|
are interpreted according to a timezone. The functions of this module |
|
27
|
|
|
|
|
|
|
appropriately handle the semantics of all the non-trivial conversions. |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
The day count systems supported by this module are Mars Sol Date, |
|
30
|
|
|
|
|
|
|
Julian Sol, and Chronological Mars Solar Date, each in both integral |
|
31
|
|
|
|
|
|
|
and fractional forms. |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=head2 Flavours of day count |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
In the interests of orthogonality, all flavours of day count come in |
|
36
|
|
|
|
|
|
|
both integral and fractional varieties. Generally, there is a quantity |
|
37
|
|
|
|
|
|
|
named "XYZ" which is a real count of days since a particular epoch (an |
|
38
|
|
|
|
|
|
|
integer plus a fraction) and a corresponding quantity named "XYZN" ("XYZ |
|
39
|
|
|
|
|
|
|
Number") which is a count of complete days since the same epoch. XYZN is |
|
40
|
|
|
|
|
|
|
the integral part of XYZ. There is also a quantity named "XYZF" ("XYZ |
|
41
|
|
|
|
|
|
|
Fraction") which is a count of fractional days since the XYZN changed |
|
42
|
|
|
|
|
|
|
(at midnight). XYZF is the fractional part of XYZ, in the range [0, 1). |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
This quantity naming pattern is derived from the naming of Terran day |
|
45
|
|
|
|
|
|
|
counts, particularly JD (Julian Date) and JDN (Julian Day Number) which |
|
46
|
|
|
|
|
|
|
have the described correspondence. The "XYZF" name type is a neologism, |
|
47
|
|
|
|
|
|
|
invented for L. |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
All calendar dates given are in the Darian calendar for Mars. An hour |
|
50
|
|
|
|
|
|
|
number is appended to each date, separated by a "T"; hour 00 is midnight |
|
51
|
|
|
|
|
|
|
at the start of the day. An appended "Z" indicates that the date is to |
|
52
|
|
|
|
|
|
|
be interpreted in the timezone of the prime meridian (Airy Mean Time), |
|
53
|
|
|
|
|
|
|
and so is absolute; where any other timezone is to be used then this is |
|
54
|
|
|
|
|
|
|
explicitly noted. |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=over |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=item MSD (Mars Sol Date) |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
days elapsed since 0140-19-26T00Z (approximately MJD 5521.50 |
|
61
|
|
|
|
|
|
|
in Terrestrial Time). This epoch is the most recent near |
|
62
|
|
|
|
|
|
|
coincidence of midnight on the Martian prime meridian with noon |
|
63
|
|
|
|
|
|
|
on the Terran prime meridian. MSD is defined by the paper at |
|
64
|
|
|
|
|
|
|
L. |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=item JS (Julian Sol) |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
days elapsed since 0000-01-01T00Z (MSD -94129.0) (approximately |
|
69
|
|
|
|
|
|
|
MJD -91195.22 in Terrestrial Time). This epoch is an Airy |
|
70
|
|
|
|
|
|
|
midnight approximating the last northward equinox prior to |
|
71
|
|
|
|
|
|
|
the first telescopic observations of Mars. The same epoch is |
|
72
|
|
|
|
|
|
|
used for the Darian calendar for Mars. JS is defined (but not |
|
73
|
|
|
|
|
|
|
explicitly) by the document describing the Darian calendar, at |
|
74
|
|
|
|
|
|
|
L. |
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=item CMSD (Chronological Mars Solar Date) |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
days elapsed since -0608-23-20T00 in the timezone of interest. |
|
79
|
|
|
|
|
|
|
CMSD = MSD + 500000.0 + Zoff, where Zoff is the timezone |
|
80
|
|
|
|
|
|
|
offset in fractional days. CMSD is defined by the memo at |
|
81
|
|
|
|
|
|
|
L. |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=back |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=head2 Meaning of the day |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
A day count has meaning only in the context of a particular definition |
|
88
|
|
|
|
|
|
|
of "day". Potentially several time scales could be expressed in terms |
|
89
|
|
|
|
|
|
|
of a day count, just as Terran day counts such as MJD are used in the |
|
90
|
|
|
|
|
|
|
timescales UT1, UT2, UTC, TAI, TT, TCG, and others. For a day number |
|
91
|
|
|
|
|
|
|
to be meaningful it is necessary to be aware of which kind of day it |
|
92
|
|
|
|
|
|
|
is counting. Conversion between the different time scales is out of |
|
93
|
|
|
|
|
|
|
scope for this module. |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=cut |
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
package Date::MSD; |
|
98
|
|
|
|
|
|
|
|
|
99
|
1
|
|
|
1
|
|
86024
|
{ use 5.006; } |
|
|
1
|
|
|
|
|
7
|
|
|
100
|
1
|
|
|
1
|
|
8
|
use warnings; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
43
|
|
|
101
|
1
|
|
|
1
|
|
7
|
use strict; |
|
|
1
|
|
|
|
|
9
|
|
|
|
1
|
|
|
|
|
47
|
|
|
102
|
|
|
|
|
|
|
|
|
103
|
1
|
|
|
1
|
|
8
|
use Carp qw(croak); |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
90
|
|
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
our $VERSION = "0.005"; |
|
106
|
|
|
|
|
|
|
|
|
107
|
1
|
|
|
1
|
|
422
|
use parent "Exporter"; |
|
|
1
|
|
|
|
|
669
|
|
|
|
1
|
|
|
|
|
7
|
|
|
108
|
|
|
|
|
|
|
our @EXPORT_OK; |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
my %msd_flavours = ( |
|
111
|
|
|
|
|
|
|
msd => { epoch_msd => 0 }, |
|
112
|
|
|
|
|
|
|
js => { epoch_msd => -94129.0 }, |
|
113
|
|
|
|
|
|
|
cmsd => { epoch_msd => -500000.0, zone => 1 }, |
|
114
|
|
|
|
|
|
|
); |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=head1 FUNCTIONS |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
Day counts in this API may be native Perl numbers or C |
|
119
|
|
|
|
|
|
|
objects. Both are acceptable for all parameters, in any combination. |
|
120
|
|
|
|
|
|
|
In all conversion functions, the result is of the same type as the |
|
121
|
|
|
|
|
|
|
input, provided that the inputs are of consistent type. If native Perl |
|
122
|
|
|
|
|
|
|
numbers are supplied then the conversion is subject to floating point |
|
123
|
|
|
|
|
|
|
rounding, and possible overflow if the numbers are extremely large. |
|
124
|
|
|
|
|
|
|
The use of C is recommended to avoid these problems. |
|
125
|
|
|
|
|
|
|
With C the results are exact. |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
There are conversion functions between all pairs of day count systems. |
|
128
|
|
|
|
|
|
|
This is a total of 72 conversion functions (including 12 identity |
|
129
|
|
|
|
|
|
|
functions). |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
When converting between timezone-relative counts (CMSD) and absolute |
|
132
|
|
|
|
|
|
|
counts (MSD, JS), the timezone that is being used must be specified. |
|
133
|
|
|
|
|
|
|
It is given in a ZONE argument as a fractional number of days offset |
|
134
|
|
|
|
|
|
|
from the base time scale (typically Airy Mean Time). Beware of |
|
135
|
|
|
|
|
|
|
floating point rounding when the offset does not have a terminating |
|
136
|
|
|
|
|
|
|
binary representation; use of C avoids this problem. |
|
137
|
|
|
|
|
|
|
A ZONE parameter is not used when converting between absolute day counts |
|
138
|
|
|
|
|
|
|
(e.g., between MSD and JS) or between timezone-relative counts (e.g., |
|
139
|
|
|
|
|
|
|
between CMSD and CMSDN). |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=over |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=item msd_to_msd(MSD) |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=item msd_to_js(MSD) |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=item msd_to_cmsd(MSD, ZONE) |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=item js_to_msd(JS) |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=item js_to_js(JS) |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=item js_to_cmsd(JS, ZONE) |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=item cmsd_to_msd(CMSD, ZONE) |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=item cmsd_to_js(CMSD, ZONE) |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=item cmsd_to_cmsd(CMSD) |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
These functions convert from one continuous day count to another. |
|
162
|
|
|
|
|
|
|
This principally involve a change of epoch. The input identifies a |
|
163
|
|
|
|
|
|
|
point in time, as a continuous day count of input flavour. The function |
|
164
|
|
|
|
|
|
|
returns the same point in time, represented as a continuous day count |
|
165
|
|
|
|
|
|
|
of output flavour. |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=item msd_to_msdnn(MSD) |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=item msd_to_jsnn(MSD) |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=item msd_to_cmsdnn(MSD, ZONE) |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=item js_to_msdnn(JS) |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=item js_to_jsnn(JS) |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=item js_to_cmsdnn(JS, ZONE) |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=item cmsd_to_msdnn(CMSD, ZONE) |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=item cmsd_to_jsnn(CMSD, ZONE) |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=item cmsd_to_cmsdnn(CMSD) |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
These functions convert from a continuous day count to an integral day |
|
186
|
|
|
|
|
|
|
count. The input identifies a point in time, as a continuous day count |
|
187
|
|
|
|
|
|
|
of input flavour. The function returns the day number of output flavour |
|
188
|
|
|
|
|
|
|
that applies at that instant. The process throws away information about |
|
189
|
|
|
|
|
|
|
the time of (output-flavour) day. |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=item msd_to_msdnf(MSD) |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=item msd_to_jsnf(MSD) |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=item msd_to_cmsdnf(MSD, ZONE) |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=item js_to_msdnf(JS) |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=item js_to_jsnf(JS) |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=item js_to_cmsdnf(JS, ZONE) |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=item cmsd_to_msdnf(CMSD, ZONE) |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=item cmsd_to_jsnf(CMSD, ZONE) |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=item cmsd_to_cmsdnf(CMSD) |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
These functions convert from a continuous day count to an integral day |
|
210
|
|
|
|
|
|
|
count with separate fraction. The input identifies a point in time, |
|
211
|
|
|
|
|
|
|
as a continuous day count of input flavour. The function returns a |
|
212
|
|
|
|
|
|
|
list of two items: the day number and fractional day of output flavour, |
|
213
|
|
|
|
|
|
|
which together identify the same point in time as the input. |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=item msd_to_msdn(MSD) |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=item msd_to_jsn(MSD) |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=item msd_to_cmsdn(MSD, ZONE) |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=item js_to_msdn(JS) |
|
222
|
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=item js_to_jsn(JS) |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=item js_to_cmsdn(JS, ZONE) |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=item cmsd_to_msdn(CMSD, ZONE) |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
=item cmsd_to_jsn(CMSD, ZONE) |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=item cmsd_to_cmsdn(CMSD) |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
These functions convert from a continuous day count to an integral day |
|
234
|
|
|
|
|
|
|
count, possibly with separate fraction. The input identifies a point in |
|
235
|
|
|
|
|
|
|
time, as a continuous day count of input flavour. If called in scalar |
|
236
|
|
|
|
|
|
|
context, the function returns the day number of output flavour that |
|
237
|
|
|
|
|
|
|
applies at that instant, throwing away information about the time of |
|
238
|
|
|
|
|
|
|
(output-flavour) day. If called in list context, the function returns a |
|
239
|
|
|
|
|
|
|
list of two items: the day number and fractional day of output flavour, |
|
240
|
|
|
|
|
|
|
which together identify the same point in time as the input. |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
These functions are not recommended, because the context-sensitive |
|
243
|
|
|
|
|
|
|
return convention makes their use error-prone. They are retained for |
|
244
|
|
|
|
|
|
|
backward compatibility. You should prefer to use the more specific |
|
245
|
|
|
|
|
|
|
functions shown above. |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=item msdn_to_msd(MSDN, MSDF) |
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=item msdn_to_js(MSDN, MSDF) |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
=item msdn_to_cmsd(MSDN, MSDF, ZONE) |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=item jsn_to_msd(JSN, JSF) |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=item jsn_to_js(JSN, JSF) |
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=item jsn_to_cmsd(JSN, JSF, ZONE) |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
=item cmsdn_to_msd(CMSDN, CMSDF, ZONE) |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=item cmsdn_to_js(CMSDN, CMSDF, ZONE) |
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
=item cmsdn_to_cmsd(CMSDN, CMSDF) |
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
These functions convert from an integral day count with separate fraction |
|
266
|
|
|
|
|
|
|
to a continuous day count. The input identifies a point in time, as |
|
267
|
|
|
|
|
|
|
an integral day number of input flavour plus day fraction in the range |
|
268
|
|
|
|
|
|
|
[0, 1). The function returns the same point in time, represented as a |
|
269
|
|
|
|
|
|
|
continuous day count of output flavour. |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
=item msdn_to_msdnn(MSDN[, MSDF]) |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=item msdn_to_jsnn(MSDN[, MSDF]) |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=item msdn_to_cmsdnn(MSDN, MSDF, ZONE) |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=item jsn_to_msdnn(JSN[, JSF]) |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=item jsn_to_jsnn(JSN[, JSF]) |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=item jsn_to_cmsdnn(JSN, JSF, ZONE) |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=item cmsdn_to_msdnn(CMSDN, CMSDF, ZONE) |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
=item cmsdn_to_jsnn(CMSDN, CMSDF, ZONE) |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
=item cmsdn_to_cmsdnn(CMSDN[, CMSDF]) |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
These functions convert from an integral day count with separate fraction |
|
290
|
|
|
|
|
|
|
to an integral day count. The input identifies a point in time, as an |
|
291
|
|
|
|
|
|
|
integral day number of input flavour plus day fraction in the range |
|
292
|
|
|
|
|
|
|
[0, 1). The function returns the day number of output flavour that |
|
293
|
|
|
|
|
|
|
applies at that instant. The process throws away information about |
|
294
|
|
|
|
|
|
|
the time of (output-flavour) day. If converting between systems that |
|
295
|
|
|
|
|
|
|
delimit days identically (e.g., between JS and MSD), the day fraction |
|
296
|
|
|
|
|
|
|
makes no difference and may be omitted from the input. |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
=item msdn_to_msdnf(MSDN, MSDF) |
|
299
|
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=item msdn_to_jsnf(MSDN, MSDF) |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=item msdn_to_cmsdnf(MSDN, MSDF, ZONE) |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
=item jsn_to_msdnf(JSN, JSF) |
|
305
|
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=item jsn_to_jsnf(JSN, JSF) |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=item jsn_to_cmsdnf(JSN, JSF, ZONE) |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
=item cmsdn_to_msdnf(CMSDN, CMSDF, ZONE) |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=item cmsdn_to_jsnf(CMSDN, CMSDF, ZONE) |
|
313
|
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
=item cmsdn_to_cmsdnf(CMSDN, CMSDF) |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
These functions convert from one integral day count with separate |
|
317
|
|
|
|
|
|
|
fraction to another. The input identifies a point in time, as an |
|
318
|
|
|
|
|
|
|
integral day number of input flavour plus day fraction in the range |
|
319
|
|
|
|
|
|
|
[0, 1). The function returns a list of two items: the day number and |
|
320
|
|
|
|
|
|
|
fractional day of output flavour, which together identify the same point |
|
321
|
|
|
|
|
|
|
in time as the input. |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=item msdn_to_msdn(MSDN[, MSDF]) |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
=item msdn_to_jsn(MSDN[, MSDF]) |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
=item msdn_to_cmsdn(MSDN, MSDF, ZONE) |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=item jsn_to_msdn(JSN[, JSF]) |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=item jsn_to_jsn(JSN[, JSF]) |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=item jsn_to_cmsdn(JSN, JSF, ZONE) |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
=item cmsdn_to_msdn(CMSDN, CMSDF, ZONE) |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
=item cmsdn_to_jsn(CMSDN, CMSDF, ZONE) |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=item cmsdn_to_cmsdn(CMSDN[, CMSDF]) |
|
340
|
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
These functions convert from an integral day count with separate fraction |
|
342
|
|
|
|
|
|
|
to an integral day count, possibly with separate fraction. The input |
|
343
|
|
|
|
|
|
|
identifies a point in time, as an integral day number of input flavour |
|
344
|
|
|
|
|
|
|
plus day fraction in the range [0, 1). If called in scalar context, the |
|
345
|
|
|
|
|
|
|
function returns the day number of output flavour that applies at that |
|
346
|
|
|
|
|
|
|
instant, throwing away information about the time of (output-flavour) day. |
|
347
|
|
|
|
|
|
|
If called in list context, the function returns a list of two items: |
|
348
|
|
|
|
|
|
|
the day number and fractional day of output flavour, which together |
|
349
|
|
|
|
|
|
|
identify the same point in time as the input. |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
If converting between systems that delimit days identically (e.g., |
|
352
|
|
|
|
|
|
|
between JS and MSD), the day fraction makes no difference to the integral |
|
353
|
|
|
|
|
|
|
day number of the output, and may be omitted from the input. If the day |
|
354
|
|
|
|
|
|
|
fraction is extracted from the output when it wasn't supplied as input, |
|
355
|
|
|
|
|
|
|
it will default to zero. |
|
356
|
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
These functions are not recommended, because the context-sensitive |
|
358
|
|
|
|
|
|
|
return convention makes their use error-prone. They are retained for |
|
359
|
|
|
|
|
|
|
backward compatibility. You should prefer to use the more specific |
|
360
|
|
|
|
|
|
|
functions shown above. |
|
361
|
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=cut |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
eval { local $SIG{__DIE__}; |
|
365
|
|
|
|
|
|
|
require POSIX; |
|
366
|
|
|
|
|
|
|
*_floor = \&POSIX::floor; |
|
367
|
|
|
|
|
|
|
}; |
|
368
|
|
|
|
|
|
|
if($@ ne "") { |
|
369
|
|
|
|
|
|
|
*_floor = sub($) { |
|
370
|
|
|
|
|
|
|
my $i = int($_[0]); |
|
371
|
|
|
|
|
|
|
return $i == $_[0] || $_[0] > 0 ? $i : $i - 1; |
|
372
|
|
|
|
|
|
|
} |
|
373
|
|
|
|
|
|
|
} |
|
374
|
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
sub _check_dn($$) { |
|
376
|
504
|
100
|
|
504
|
|
2650
|
croak "purported day number $_[0] is not an integer" |
|
|
|
50
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
unless ref($_[0]) ? $_[0]->is_int : $_[0] == int($_[0]); |
|
378
|
504
|
50
|
33
|
|
|
10910
|
croak "purported day fraction $_[1] is out of range [0, 1)" |
|
379
|
|
|
|
|
|
|
unless $_[1] >= 0 && $_[1] < 1; |
|
380
|
|
|
|
|
|
|
} |
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
sub _ret_dnn($) { |
|
383
|
720
|
100
|
|
720
|
|
266006
|
my $dn = ref($_[0]) eq "Math::BigRat" ? |
|
384
|
|
|
|
|
|
|
$_[0]->copy->bfloor : _floor($_[0]); |
|
385
|
720
|
|
|
|
|
25352
|
return $dn; |
|
386
|
|
|
|
|
|
|
} |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
sub _ret_dnf($) { |
|
389
|
288
|
|
|
288
|
|
129921
|
my $dn = &_ret_dnn; |
|
390
|
288
|
|
|
|
|
1246
|
return ($dn, $_[0] - $dn); |
|
391
|
|
|
|
|
|
|
} |
|
392
|
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
sub _ret_dn($) { |
|
394
|
288
|
100
|
|
288
|
|
258877
|
return wantarray ? &_ret_dnf : &_ret_dnn; |
|
395
|
|
|
|
|
|
|
} |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
foreach my $src (keys %msd_flavours) { foreach my $dst (keys %msd_flavours) { |
|
398
|
|
|
|
|
|
|
my $ediff = $msd_flavours{$src}->{epoch_msd} - |
|
399
|
|
|
|
|
|
|
$msd_flavours{$dst}->{epoch_msd}; |
|
400
|
|
|
|
|
|
|
my $ediffh = $ediff == int($ediff) ? 0 : 0.5; |
|
401
|
|
|
|
|
|
|
my $src_zone = !!$msd_flavours{$src}->{zone}; |
|
402
|
|
|
|
|
|
|
my $dst_zone = !!$msd_flavours{$dst}->{zone}; |
|
403
|
|
|
|
|
|
|
my($zp, $z1, $z2); |
|
404
|
|
|
|
|
|
|
if($src_zone == $dst_zone) { |
|
405
|
|
|
|
|
|
|
$zp = $z1 = $z2 = ""; |
|
406
|
|
|
|
|
|
|
} else { |
|
407
|
|
|
|
|
|
|
$zp = "\$"; |
|
408
|
|
|
|
|
|
|
my $zsign = $src_zone ? "-" : "+"; |
|
409
|
|
|
|
|
|
|
$z1 = "$zsign \$_[1]"; |
|
410
|
|
|
|
|
|
|
$z2 = "$zsign \$_[2]"; |
|
411
|
|
|
|
|
|
|
} |
|
412
|
16
|
|
|
16
|
1
|
26979
|
eval "sub ${src}_to_${dst}(\$${zp}) { \$_[0] + (${ediff}) ${z1} }"; |
|
|
16
|
|
|
16
|
1
|
38639
|
|
|
|
16
|
|
|
16
|
1
|
35677
|
|
|
|
16
|
|
|
16
|
1
|
32551
|
|
|
|
16
|
|
|
16
|
1
|
29107
|
|
|
|
16
|
|
|
16
|
1
|
26084
|
|
|
|
16
|
|
|
16
|
1
|
37534
|
|
|
|
16
|
|
|
16
|
1
|
32880
|
|
|
|
16
|
|
|
16
|
1
|
136450
|
|
|
413
|
|
|
|
|
|
|
push @EXPORT_OK, "${src}_to_${dst}"; |
|
414
|
16
|
|
|
16
|
1
|
10521
|
eval "sub ${src}_to_${dst}nn(\$${zp}) { |
|
|
16
|
|
|
16
|
1
|
20421
|
|
|
|
16
|
|
|
16
|
1
|
16699
|
|
|
|
16
|
|
|
16
|
1
|
15351
|
|
|
|
16
|
|
|
16
|
1
|
11721
|
|
|
|
16
|
|
|
16
|
1
|
12582
|
|
|
|
16
|
|
|
16
|
1
|
19553
|
|
|
|
16
|
|
|
16
|
1
|
13921
|
|
|
|
16
|
|
|
16
|
1
|
11826
|
|
|
415
|
|
|
|
|
|
|
_ret_dnn(\$_[0] + (${ediff}) ${z1}) |
|
416
|
|
|
|
|
|
|
}"; |
|
417
|
|
|
|
|
|
|
push @EXPORT_OK, "${src}_to_${dst}nn"; |
|
418
|
8
|
|
|
8
|
1
|
6507
|
eval "sub ${src}_to_${dst}nf(\$${zp}) { |
|
|
8
|
|
|
8
|
1
|
9150
|
|
|
|
8
|
|
|
8
|
1
|
7437
|
|
|
|
8
|
|
|
8
|
1
|
8504
|
|
|
|
8
|
|
|
8
|
1
|
7264
|
|
|
|
8
|
|
|
8
|
1
|
8013
|
|
|
|
8
|
|
|
8
|
1
|
9767
|
|
|
|
8
|
|
|
8
|
1
|
8499
|
|
|
|
8
|
|
|
8
|
1
|
7547
|
|
|
419
|
|
|
|
|
|
|
_ret_dnf(\$_[0] + (${ediff}) ${z1}) |
|
420
|
|
|
|
|
|
|
}"; |
|
421
|
|
|
|
|
|
|
push @EXPORT_OK, "${src}_to_${dst}nf"; |
|
422
|
16
|
|
|
16
|
1
|
21788
|
eval "sub ${src}_to_${dst}n(\$${zp}) { |
|
|
16
|
|
|
16
|
1
|
28237
|
|
|
|
16
|
|
|
16
|
1
|
23631
|
|
|
|
16
|
|
|
16
|
1
|
24844
|
|
|
|
16
|
|
|
16
|
1
|
23403
|
|
|
|
16
|
|
|
16
|
1
|
26566
|
|
|
|
16
|
|
|
16
|
1
|
30180
|
|
|
|
16
|
|
|
16
|
1
|
27311
|
|
|
|
16
|
|
|
16
|
1
|
28236
|
|
|
423
|
|
|
|
|
|
|
_ret_dn(\$_[0] + (${ediff}) ${z1}) |
|
424
|
|
|
|
|
|
|
}"; |
|
425
|
|
|
|
|
|
|
push @EXPORT_OK, "${src}_to_${dst}n"; |
|
426
|
16
|
|
|
16
|
1
|
20788
|
eval "sub ${src}n_to_${dst}(\$\$${zp}) { |
|
|
16
|
|
|
16
|
1
|
13680
|
|
|
|
16
|
|
|
16
|
1
|
28463
|
|
|
|
16
|
|
|
16
|
1
|
14044
|
|
|
|
16
|
|
|
16
|
1
|
24479
|
|
|
|
16
|
|
|
16
|
1
|
13613
|
|
|
|
16
|
|
|
16
|
1
|
28210
|
|
|
|
16
|
|
|
16
|
1
|
14089
|
|
|
|
16
|
|
|
16
|
1
|
18784
|
|
|
|
16
|
|
|
|
|
11895
|
|
|
|
16
|
|
|
|
|
19994
|
|
|
|
16
|
|
|
|
|
14159
|
|
|
|
16
|
|
|
|
|
30920
|
|
|
|
16
|
|
|
|
|
16139
|
|
|
|
16
|
|
|
|
|
22739
|
|
|
|
16
|
|
|
|
|
14084
|
|
|
|
16
|
|
|
|
|
23748
|
|
|
|
16
|
|
|
|
|
14574
|
|
|
427
|
|
|
|
|
|
|
_check_dn(\$_[0], \$_[1]); |
|
428
|
|
|
|
|
|
|
\$_[0] + \$_[1] + (${ediff}) ${z2} |
|
429
|
|
|
|
|
|
|
}"; |
|
430
|
|
|
|
|
|
|
push @EXPORT_OK, "${src}n_to_${dst}"; |
|
431
|
|
|
|
|
|
|
my($tp, $tc); |
|
432
|
|
|
|
|
|
|
if($ediffh == 0 && $src_zone == $dst_zone) { |
|
433
|
|
|
|
|
|
|
$tp = ";"; |
|
434
|
|
|
|
|
|
|
$tc = "push \@_, 0 if \@_ == 1;"; |
|
435
|
|
|
|
|
|
|
} else { |
|
436
|
|
|
|
|
|
|
$tp = $tc = ""; |
|
437
|
|
|
|
|
|
|
} |
|
438
|
16
|
50
|
|
16
|
1
|
16837
|
eval "sub ${src}n_to_${dst}nn(\$${tp}\$${zp}) { $tc |
|
|
16
|
50
|
|
16
|
1
|
79
|
|
|
|
16
|
50
|
|
16
|
1
|
13862
|
|
|
|
16
|
50
|
|
16
|
1
|
26868
|
|
|
|
16
|
50
|
|
16
|
1
|
14584
|
|
|
|
16
|
|
|
16
|
1
|
22395
|
|
|
|
16
|
|
|
16
|
1
|
15289
|
|
|
|
16
|
|
|
16
|
1
|
22135
|
|
|
|
16
|
|
|
16
|
1
|
13935
|
|
|
|
16
|
|
|
|
|
15982
|
|
|
|
16
|
|
|
|
|
81
|
|
|
|
16
|
|
|
|
|
12664
|
|
|
|
16
|
|
|
|
|
17889
|
|
|
|
16
|
|
|
|
|
79
|
|
|
|
16
|
|
|
|
|
14395
|
|
|
|
16
|
|
|
|
|
22870
|
|
|
|
16
|
|
|
|
|
14271
|
|
|
|
16
|
|
|
|
|
16572
|
|
|
|
16
|
|
|
|
|
89
|
|
|
|
16
|
|
|
|
|
14402
|
|
|
|
16
|
|
|
|
|
17217
|
|
|
|
16
|
|
|
|
|
80
|
|
|
|
16
|
|
|
|
|
14564
|
|
|
439
|
|
|
|
|
|
|
_check_dn(\$_[0], \$_[1]); |
|
440
|
|
|
|
|
|
|
_ret_dnn(\$_[0] + \$_[1] + ($ediff) ${z2}) |
|
441
|
|
|
|
|
|
|
}"; |
|
442
|
|
|
|
|
|
|
push @EXPORT_OK, "${src}n_to_${dst}nn"; |
|
443
|
8
|
|
|
8
|
1
|
7177
|
eval "sub ${src}n_to_${dst}nf(\$\$${zp}) { |
|
|
8
|
|
|
8
|
1
|
6309
|
|
|
|
8
|
|
|
8
|
1
|
8771
|
|
|
|
8
|
|
|
8
|
1
|
6434
|
|
|
|
8
|
|
|
8
|
1
|
7946
|
|
|
|
8
|
|
|
8
|
1
|
6641
|
|
|
|
8
|
|
|
8
|
1
|
8689
|
|
|
|
8
|
|
|
8
|
1
|
6803
|
|
|
|
8
|
|
|
8
|
1
|
7855
|
|
|
|
8
|
|
|
|
|
7614
|
|
|
|
8
|
|
|
|
|
7130
|
|
|
|
8
|
|
|
|
|
5748
|
|
|
|
8
|
|
|
|
|
8360
|
|
|
|
8
|
|
|
|
|
7358
|
|
|
|
8
|
|
|
|
|
8704
|
|
|
|
8
|
|
|
|
|
6870
|
|
|
|
8
|
|
|
|
|
7940
|
|
|
|
8
|
|
|
|
|
7272
|
|
|
444
|
|
|
|
|
|
|
_check_dn(\$_[0], \$_[1]); |
|
445
|
|
|
|
|
|
|
_ret_dnf(\$_[0] + \$_[1] + ($ediff) ${z2}) |
|
446
|
|
|
|
|
|
|
}"; |
|
447
|
|
|
|
|
|
|
push @EXPORT_OK, "${src}n_to_${dst}nf"; |
|
448
|
16
|
50
|
|
16
|
1
|
14379
|
eval "sub ${src}n_to_${dst}n(\$${tp}\$${zp}) { $tc |
|
|
16
|
50
|
|
16
|
1
|
76
|
|
|
|
16
|
50
|
|
16
|
1
|
16103
|
|
|
|
16
|
50
|
|
16
|
1
|
15795
|
|
|
|
16
|
50
|
|
16
|
1
|
11732
|
|
|
|
16
|
|
|
16
|
1
|
13707
|
|
|
|
16
|
|
|
16
|
1
|
13874
|
|
|
|
16
|
|
|
16
|
1
|
14191
|
|
|
|
16
|
|
|
16
|
1
|
13080
|
|
|
|
16
|
|
|
|
|
15848
|
|
|
|
16
|
|
|
|
|
81
|
|
|
|
16
|
|
|
|
|
13472
|
|
|
|
16
|
|
|
|
|
14257
|
|
|
|
16
|
|
|
|
|
68
|
|
|
|
16
|
|
|
|
|
13921
|
|
|
|
16
|
|
|
|
|
15403
|
|
|
|
16
|
|
|
|
|
14542
|
|
|
|
16
|
|
|
|
|
15900
|
|
|
|
16
|
|
|
|
|
87
|
|
|
|
16
|
|
|
|
|
14818
|
|
|
|
16
|
|
|
|
|
15881
|
|
|
|
16
|
|
|
|
|
79
|
|
|
|
16
|
|
|
|
|
12640
|
|
|
449
|
|
|
|
|
|
|
_check_dn(\$_[0], \$_[1]); |
|
450
|
|
|
|
|
|
|
_ret_dn(\$_[0] + \$_[1] + ($ediff) ${z2}) |
|
451
|
|
|
|
|
|
|
}"; |
|
452
|
|
|
|
|
|
|
push @EXPORT_OK, "${src}n_to_${dst}n"; |
|
453
|
|
|
|
|
|
|
} } |
|
454
|
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
=back |
|
456
|
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
458
|
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
L, |
|
460
|
|
|
|
|
|
|
L |
|
461
|
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
=head1 AUTHOR |
|
463
|
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
Andrew Main (Zefram) |
|
465
|
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
=head1 COPYRIGHT |
|
467
|
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
Copyright (C) 2007, 2009, 2010, 2012, 2017 |
|
469
|
|
|
|
|
|
|
Andrew Main (Zefram) |
|
470
|
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
=head1 LICENSE |
|
472
|
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
This module is free software; you can redistribute it and/or modify it |
|
474
|
|
|
|
|
|
|
under the same terms as Perl itself. |
|
475
|
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
=cut |
|
477
|
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
1; |