PLplot
5.15.0
Toggle main menu visibility
Loading...
Searching...
No Matches
qsastime_extra.c
Go to the documentation of this file.
1
//
2
// This software originally contributed under the LGPL in January 2009 to
3
// PLplot by the
4
// Cluster Science Centre
5
// QSAS team,
6
// Imperial College, London
7
// Copyright (C) 2009 Imperial College, London
8
//
9
// This file is part of PLplot.
10
//
11
// PLplot is free software; you can redistribute it and/or modify
12
// it under the terms of the GNU Library General Public License as published
13
// by the Free Software Foundation; either version 2 of the License, or
14
// (at your option) any later version.
15
//
16
// PLplot is distributed in the hope that it will be useful,
17
// but WITHOUT ANY WARRANTY; without even the implied warranty of
18
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
// GNU Library General Public License for more details.
20
//
21
// You should have received a copy of the GNU Library General Public License
22
// along with PLplot; if not, write to the Free Software
23
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24
//
25
//
26
27
// MJD measures from the start of 17 Nov 1858
28
29
// These utilities use the Gregorian calendar after 4 Oct 1582 (Julian) i.e. from 15 Oct 1582 Gregoriam
30
// Note C libraries use Gregorian only from 14 Sept 1752
31
// More detailed discussion can be found at http://aa.usno.navy.mil/data/docs/JulianDate.php
32
// These routines have been compared with the results of the US Naval Observatory online converter.
33
// Modified Julian Date (MJD) = Julian Date (JD) - 2400000.5
34
//
35
// In all routines, specifying a day, hour, minute or second field greater than would be valid is
36
// handled with modulo arithmetic and safe.
37
// Thus 2006-12-32 00:62:00.0 will safely, and correctly, be treated as 2007-01-01 01:02:00.0
38
//
39
//
40
41
#include "
qsastime_extra.h
"
42
43
static
double
MJDtoJD
= 2400000.5;
44
static
double
SecInDay
= 86400;
// we ignore leap seconds
45
46
int
setFromISOstring
(
const
char
* ISOstring,
MJDtime
*MJD,
int
forceJulian )
47
{
48
double
seconds;
49
int
y, m, d, h,
min
;
50
int
startAt = 0;
51
int
len = strlen( ISOstring );
52
53
// ISO is "1995-01-23 02:33:17.235" or "1995-01-23T02:33:17.235Z"
54
55
// parse off year
56
57
y = strtol( &( ISOstring[startAt] ), NULL, 10 );
58
if
( ISOstring[startAt] ==
'-'
|| ISOstring[startAt] ==
'+'
)
59
startAt++;
60
startAt += 5;
61
if
( startAt > len )
62
return
1;
63
64
m = strtol( &( ISOstring[startAt] ), NULL, 10 );
65
startAt += 3;
66
if
( startAt > len )
67
return
1;
68
69
d = strtol( &( ISOstring[startAt] ), NULL, 10 );
70
startAt += 3;
71
if
( startAt > len )
72
return
1;
73
74
h = strtol( &( ISOstring[startAt] ), NULL, 10 );
75
startAt += 3;
76
if
( startAt > len )
77
return
1;
78
79
min
= strtol( &( ISOstring[startAt] ), NULL, 10 );
80
startAt += 3;
81
if
( startAt > len )
82
return
1;
83
84
seconds = strtod( &( ISOstring[startAt] ), NULL );
85
setFromUT
( y, m - 1, d, h,
min
, seconds, MJD, forceJulian );
86
87
return
0;
88
}
89
90
91
void
setFromDOY
(
int
year,
int
doy,
int
hour,
int
min
,
double
sec,
MJDtime
*MJD,
int
forceJulian )
92
{
93
// Set from Day Of Year format
94
95
// convert Gregorian date plus time to MJD
96
// MJD measures from the start of 17 Nov 1858
97
98
// the int flag forceJulian forces use of Julian calendar whatever the year
99
// default is to use Gregorian after 4 Oct 1582 (Julian) i.e. from 15 Oct 1582 Gregorian
100
// Note C libraries use Gregorian only from 14 Sept 1752 onwards
101
102
int
leaps, lastyear, extraDays;
103
104
// N.B. There were known problems (both for the Julian and Gregorian
105
// cases) with the following leap year logic that were completely fixed
106
// in qsastime.c, but I (AWI) am not going to bother with these fixups
107
// here since this code only used for a specific test routine for limited
108
// date range and not for anything general.
109
if
( forceJulian && year <= 0 )
110
{
111
// count leap years on Julian Calendar
112
// MJD for Jan 1 0000 (correctly Jan 01, BCE 1) is - 678943, count from there
113
// negative CE (AD) years convert to BCE (BC) as BCE = 1 - CE, e.g. 2 BCE = -1 CE
114
115
leaps = ( year - 4 ) / 4;
// (note leaps is negative here and year 0 (1 BCE) was a leap year
116
MJD->
base_day
= year * 365 + leaps + doy - 678943;
117
}
118
else
if
( forceJulian )
119
{
120
// count leap years on Julian Calendar
121
// MJD for Jan 1 0000 (correctly Jan 01, BCE 1) is - 678943, count from there
122
123
leaps = ( year - 1 ) / 4;
124
MJD->
base_day
= year * 365 + leaps + doy - 678943;
125
}
126
else
127
{
128
// count leap years Gregorian Calendar - modern dates
129
// Algorithm below for 17 Nov 1858 (0 MJD) gives
130
// leaps = 450 and hence base_day of 678941, so subtract it to give MJD day
131
132
lastyear = year - 1;
133
leaps = lastyear / 4 - lastyear / 100 + lastyear / 400;
134
MJD->
base_day
= year * 365 + leaps + doy - 678941;
135
}
136
137
MJD->
time_sec
= sec + ( (double)
min
+ (double) hour * 60. ) * 60.;
138
139
if
( MJD->
time_sec
>=
SecInDay
)
140
{
141
extraDays = (int) ( MJD->
time_sec
/
SecInDay
);
142
MJD->
base_day
+= extraDays;
143
MJD->
time_sec
-= extraDays *
SecInDay
;
144
}
145
146
return
;
147
}
148
149
150
void
setFromBCE
(
int
yearBCE,
int
month,
int
day,
int
hour,
int
min
,
double
sec,
MJDtime
*MJD,
int
forceJulian )
151
{
152
// utility to allow user to input dates BCE (BC)
153
154
int
year = 1 - yearBCE;
155
setFromUT
( year, month, day, hour,
min
, sec, MJD, forceJulian );
156
}
157
158
void
setFromMJD
(
double
ModifiedJulianDate,
MJDtime
*MJD )
159
{
160
// convert MJD double into MJD structure
161
MJD->
base_day
= (int) ModifiedJulianDate;
162
MJD->
time_sec
= ( ModifiedJulianDate - MJD->
base_day
) *
SecInDay
;
163
}
164
165
void
setFromJD
(
double
JulianDate,
MJDtime
*MJD )
166
{
167
// break JD double into MJD based structure
168
// Note Julian Day starts Noon, so convert to MJD first
169
170
MJD->
base_day
= (int) ( JulianDate -
MJDtoJD
);
171
MJD->
time_sec
= ( JulianDate -
MJDtoJD
- (double) MJD->
base_day
) *
SecInDay
;
172
}
173
174
void
setFromCDFepoch
(
double
cdfepoch,
MJDtime
*MJD )
175
{
176
// convert cdf epoch double into MJD structure
177
// Note that cdfepoch is msec from 0 AD on the Gregorian calendar
178
179
double
seconds = cdfepoch * 0.001;
180
181
MJD->
base_day
= (int) ( seconds / 86400.0 );
182
MJD->
time_sec
= seconds - MJD->
base_day
*
SecInDay
;
183
MJD->
base_day
-= 678941;
184
}
185
186
double
getCDFepoch
(
MJDtime
*MJD )
187
{
188
// convert MJD structure into cdf epoch double
189
// Note that cdfepoch is msec from 0 AD on the Gregorian Calendar
190
191
int
days = MJD->
base_day
+ 678941;
192
double
seconds = days *
SecInDay
+ MJD->
time_sec
;
193
return
seconds * 1000.;
194
}
195
196
double
getMJD
(
MJDtime
*MJD )
197
{
198
// Return MJD as a double
199
return
(
double
) MJD->
base_day
+ MJD->
time_sec
/
SecInDay
;
200
}
201
202
double
getJD
(
MJDtime
*MJD )
203
{
204
// Return JD as a double
205
double
JD =
getMJD
( MJD ) +
MJDtoJD
;
206
return
JD;
207
}
208
209
double
getDiffDays
(
MJDtime
*MJD1,
MJDtime
*MJD2 )
210
{
211
// Return difference MJD1 - MJD2 in days as a double
212
double
diff = (double) ( MJD1->
base_day
- MJD2->
base_day
) + ( MJD1->
time_sec
- MJD2->
time_sec
) /
SecInDay
;
213
return
diff;
214
}
215
216
double
getDiffSecs
(
MJDtime
*MJD1,
MJDtime
*MJD2 )
217
{
218
// Return difference MJD1 - MJD2 in seconds as a double
219
double
diff = (double) ( MJD1->
base_day
- MJD2->
base_day
) *
SecInDay
+ ( MJD1->
time_sec
- MJD2->
time_sec
);
220
return
diff;
221
}
222
223
const
char
*
getISOString
(
MJDtime
* MJD,
int
delim,
int
forceJulian )
224
{
225
// ISO time string for UTC
226
// uses default behaviour for Julian/Gregorian switch over
227
//**
228
// Warning getISOString is not thread safe
229
// as it writes to a static variable DateTime
230
//*
231
232
static
char
DateTime[50];
233
int
y, m, d, hour,
min
;
234
int
sec1, ysign;
235
double
sec;
236
int
slen;
237
char
* ptr;
238
239
breakDownMJD
( &y, &m, &d, &hour, &
min
, &sec, MJD, forceJulian );
240
241
if
( y < 0 )
242
{
243
ysign = 1;
244
y = -y;
245
}
246
else
247
ysign = 0;
248
249
sec1 = (int) sec / 10;
250
sec -= (double) sec1 * 10;
251
252
if
( delim == 1 )
253
{
254
if
( ysign == 0 )
255
sprintf( DateTime,
"%04d-%02d-%02dT%02d:%02d:%01d%-11.10f"
, y, m + 1, d, hour,
min
, sec1, sec );
256
else
257
sprintf( DateTime,
"-%04d-%02d-%02dT%02d:%02d:%01d%-11.10f"
, y, m + 1, d, hour,
min
, sec1, sec );
258
259
// remove trailing white space
260
while
( ( ptr = strrchr( &( DateTime[0] ),
' '
) ) != NULL )
261
ptr[0] =
'\0'
;
262
strcat( &( DateTime[0] ),
"Z"
);
263
}
264
else
265
{
266
if
( ysign == 0 )
267
sprintf( DateTime,
"%04d-%02d-%02d %02d:%02d:%01d%-11.10f"
, y, m + 1, d, hour,
min
, sec1, sec );
268
else
269
sprintf( DateTime,
"-%04d-%02d-%02d %02d:%02d:%01d%-11.10f"
, y, m + 1, d, hour,
min
, sec1, sec );
270
271
// remove trailing white space
272
slen = strlen( DateTime ) - 1;
273
while
( DateTime[slen] ==
' '
)
274
{
275
DateTime[slen] =
'\0'
;
276
slen--;
277
}
278
}
279
return
&( DateTime[0] );
280
}
min
#define min(x, y)
Definition
nnpi.c:87
MJDtime
struct MJDtimeStruct MJDtime
SecInDay
static const double SecInDay
Definition
qsastime.c:61
setFromUT
int setFromUT(int year, int month, int day, int hour, int min, double sec, MJDtime *MJD, int forceJulian)
Definition
qsastime.c:71
breakDownMJD
void breakDownMJD(int *year, int *month, int *day, int *hour, int *min, double *sec, const MJDtime *MJD, int forceJulian)
Definition
qsastime.c:289
setFromBCE
void setFromBCE(int yearBCE, int month, int day, int hour, int min, double sec, MJDtime *MJD, int forceJulian)
Definition
qsastime_extra.c:150
setFromISOstring
int setFromISOstring(const char *ISOstring, MJDtime *MJD, int forceJulian)
Definition
qsastime_extra.c:46
getDiffDays
double getDiffDays(MJDtime *MJD1, MJDtime *MJD2)
Definition
qsastime_extra.c:209
getMJD
double getMJD(MJDtime *MJD)
Definition
qsastime_extra.c:196
MJDtoJD
static double MJDtoJD
Definition
qsastime_extra.c:43
setFromCDFepoch
void setFromCDFepoch(double cdfepoch, MJDtime *MJD)
Definition
qsastime_extra.c:174
setFromJD
void setFromJD(double JulianDate, MJDtime *MJD)
Definition
qsastime_extra.c:165
setFromDOY
void setFromDOY(int year, int doy, int hour, int min, double sec, MJDtime *MJD, int forceJulian)
Definition
qsastime_extra.c:91
getDiffSecs
double getDiffSecs(MJDtime *MJD1, MJDtime *MJD2)
Definition
qsastime_extra.c:216
getJD
double getJD(MJDtime *MJD)
Definition
qsastime_extra.c:202
setFromMJD
void setFromMJD(double ModifiedJulianDate, MJDtime *MJD)
Definition
qsastime_extra.c:158
getCDFepoch
double getCDFepoch(MJDtime *MJD)
Definition
qsastime_extra.c:186
getISOString
const char * getISOString(MJDtime *MJD, int delim, int forceJulian)
Definition
qsastime_extra.c:223
qsastime_extra.h
MJDtimeStruct::base_day
int base_day
Definition
qsastimeP.h:19
MJDtimeStruct::time_sec
double time_sec
Definition
qsastimeP.h:20
lib
qsastime
qsastime_extra.c
Generated on
for PLplot by
1.17.0