File: | libsynthesis/src/sysync_SDK/Sources/lineartime.cpp |
Warning: | line 295, column 5 Value stored to 'B' is never read |
1 | /* |
2 | * File: lineartime.c |
3 | * |
4 | * Author: Lukas Zeller (luz@plan44.ch) |
5 | * |
6 | * conversion from/to linear time scale. |
7 | * |
8 | * Copyright (c) 2002-2011 by Synthesis AG + plan44.ch |
9 | * |
10 | * 2002-04-14 : luz : created from pascal source (plani.ch) |
11 | * |
12 | */ |
13 | #include "prefix_file.h" |
14 | #include "sync_include.h" |
15 | #include "lineartime.h" |
16 | #include "timezones.h" |
17 | |
18 | #if defined(SYSYNC_TOOL) |
19 | #include "syncappbase.h" // for CONSOLEPRINTF |
20 | #include "vtimezone.h" // for CONSOLEPRINTF |
21 | #endif |
22 | |
23 | namespace sysync { |
24 | |
25 | // Support for SySync Diagnostic Tool |
26 | #ifdef SYSYNC_TOOL |
27 | |
28 | // convert between different time formats and zones |
29 | int timeConv(int argc, const char *argv[]) |
30 | { |
31 | if (argc<0) { |
32 | // help requested |
33 | CONSOLEPRINTF((" time <input zone> <output zone> [<input in ISO8601 or lineartime>]"))SySync_ConsolePrintf(stderr, "SYSYNC " " time <input zone> <output zone> [<input in ISO8601 or lineartime>]" "\n"); |
34 | CONSOLEPRINTF((" Convert between time zone representations:"))SySync_ConsolePrintf(stderr, "SYSYNC " " Convert between time zone representations:" "\n"); |
35 | CONSOLEPRINTF((" special input zone names: "))SySync_ConsolePrintf(stderr, "SYSYNC " " special input zone names: " "\n"); |
36 | CONSOLEPRINTF((" - \"now\" : input is current system time (no <input> required)"))SySync_ConsolePrintf(stderr, "SYSYNC " " - \"now\" : input is current system time (no <input> required)" "\n"); |
37 | CONSOLEPRINTF((" - \"floating\" : floating time (when no zone from ISO8601 input"))SySync_ConsolePrintf(stderr, "SYSYNC " " - \"floating\" : floating time (when no zone from ISO8601 input" "\n"); |
38 | CONSOLEPRINTF((" - \"vtimezone\" : output zone as VTIMEZONE"))SySync_ConsolePrintf(stderr, "SYSYNC " " - \"vtimezone\" : output zone as VTIMEZONE" "\n"); |
39 | return EXIT_SUCCESS0; |
40 | } |
41 | |
42 | // check for argument |
43 | if (argc<2 || argc>3) { |
44 | CONSOLEPRINTF(("2 or 3 arguments required"))SySync_ConsolePrintf(stderr, "SYSYNC " "2 or 3 arguments required" "\n"); |
45 | return EXIT_FAILURE1; |
46 | } |
47 | // mode |
48 | string inzone,outzone,s,z; |
49 | // internal representation |
50 | lineartime_t intime; |
51 | sInt16 minOffs; |
52 | timecontext_t incontext,outcontext; |
53 | GZones zones; |
54 | // get input mode |
55 | inzone=argv[0]; |
56 | outzone=argv[1]; |
57 | // check special "now" case |
58 | if (strucmp(inzone.c_str(),"now")==0) { |
59 | // input time is current time in system zone |
60 | incontext = TCTX_SYSTEM((timecontext_t) ((tctx_tz_system) | TCTX_SYMBOLIC_TZ)); |
61 | intime = getSystemNowAs(incontext,&zones); |
62 | } |
63 | else { |
64 | // get input context from name (internal or olson) |
65 | if (!TimeZoneNameToContext(inzone.c_str(),incontext,&zones, true)) |
66 | incontext=TCTX_UNKNOWN((timecontext_t) ((tctx_tz_unknown) | TCTX_SYMBOLIC_TZ)); |
67 | // input time from 3rd argument |
68 | if (argc!=3) { |
69 | CONSOLEPRINTF(("input time required as 3rd argument"))SySync_ConsolePrintf(stderr, "SYSYNC " "input time required as 3rd argument" "\n"); |
70 | return EXIT_FAILURE1; |
71 | } |
72 | // try to parse as ISO8601 |
73 | timecontext_t inpctx; |
74 | uInt16 n=ISO8601StrToTimestamp(argv[2],intime,inpctx); |
75 | if (n==0 || argv[2][n]!=0) { |
76 | // no ISO, read as lineartime |
77 | inpctx=TCTX_UNKNOWN((timecontext_t) ((tctx_tz_unknown) | TCTX_SYMBOLIC_TZ)); |
78 | n=StrToLongLong(argv[2],intime); |
79 | if (n==0) { |
80 | CONSOLEPRINTF(("input time must be either ISO8601 or decimal lineartime units"))SySync_ConsolePrintf(stderr, "SYSYNC " "input time must be either ISO8601 or decimal lineartime units" "\n"); |
81 | return EXIT_FAILURE1; |
82 | } |
83 | } |
84 | if (!TCTX_IS_UNKNOWN(inpctx)) |
85 | incontext=inpctx; |
86 | } |
87 | // get output context |
88 | if (strucmp(outzone.c_str(),"vtimezone")==0) { |
89 | // show input time zone as VTIMEZONE and DAYLIGHT (for current date) |
90 | intime = getSystemNowAs(incontext,&zones); |
91 | internalToVTIMEZONE(incontext,z,&zones); |
92 | CONSOLEPRINTF(("Input time zone represented as VTIMEZONE :\n\nBEGIN:VTIMEZONE\n%sEND:VTIMEZONE\n",z.c_str()))SySync_ConsolePrintf(stderr, "SYSYNC " "Input time zone represented as VTIMEZONE :\n\nBEGIN:VTIMEZONE\n%sEND:VTIMEZONE\n" "\n",z.c_str()); |
93 | timecontext_t stdoffs; |
94 | ContextToTzDaylight(incontext,intime,z,stdoffs,&zones); |
95 | s.erase(); ContextToISO8601StrAppend(s, stdoffs, true); |
96 | CONSOLEPRINTF(("Input time zone represented as TZ/DAYLIGHT :\n\nTZ:%s\nDAYLIGHT:%s\n",s.c_str(),z.c_str()))SySync_ConsolePrintf(stderr, "SYSYNC " "Input time zone represented as TZ/DAYLIGHT :\n\nTZ:%s\nDAYLIGHT:%s\n" "\n",s.c_str(),z.c_str()); |
97 | } |
98 | else if (!TimeZoneNameToContext(outzone.c_str(),outcontext,&zones, true)) |
99 | outcontext=TCTX_UNKNOWN((timecontext_t) ((tctx_tz_unknown) | TCTX_SYMBOLIC_TZ)); |
100 | // now show |
101 | CONSOLEPRINTF((""))SySync_ConsolePrintf(stderr, "SYSYNC " "" "\n"); |
102 | // - input |
103 | TimestampToISO8601Str(s, intime, incontext, true, true); |
104 | TimeZoneContextToName(incontext, z, &zones); |
105 | TzResolveToOffset(incontext, minOffs, intime, false, &zones); |
106 | CONSOLEPRINTF(("Input : %-25s (%+03hd:%02hd - '%s')", s.c_str(), minOffs/MinsPerHour, abs(minOffs)%MinsPerHour, z.c_str()))SySync_ConsolePrintf(stderr, "SYSYNC " "Input : %-25s (%+03hd:%02hd - '%s')" "\n", s.c_str(), minOffs/MinsPerHour, abs(minOffs)%MinsPerHour , z.c_str()); |
107 | // - convert to output |
108 | if (!TzConvertTimestamp(intime,incontext,outcontext,&zones)) { |
109 | CONSOLEPRINTF(("input zone cannot be converted to output zone"))SySync_ConsolePrintf(stderr, "SYSYNC " "input zone cannot be converted to output zone" "\n"); |
110 | return EXIT_FAILURE1; |
111 | } |
112 | else { |
113 | // - input |
114 | TimestampToISO8601Str(s, intime, outcontext, true, true); |
115 | TimeZoneContextToName(outcontext, z, &zones); |
116 | TzResolveToOffset(outcontext, minOffs, intime, false, &zones); |
117 | CONSOLEPRINTF(("Output : %-25s (%+03hd:%02hd - '%s')", s.c_str(), minOffs/MinsPerHour, abs(minOffs)%MinsPerHour, z.c_str()))SySync_ConsolePrintf(stderr, "SYSYNC " "Output : %-25s (%+03hd:%02hd - '%s')" "\n", s.c_str(), minOffs/MinsPerHour, abs(minOffs)%MinsPerHour , z.c_str()); |
118 | } |
119 | return EXIT_SUCCESS0; |
120 | } // timeConv |
121 | |
122 | #endif // SYSYNC_TOOL |
123 | |
124 | |
125 | |
126 | |
127 | #ifndef PLATFORM_LROUND |
128 | // use generic implementation of lround |
129 | static sInt32 lround(double x) { |
130 | sInt32 l; |
131 | l=(sInt32)(x+0.5); |
132 | return l; |
133 | } |
134 | #endif |
135 | |
136 | #ifndef PLATFORM_TRUNC |
137 | // use generic implementation of trunc |
138 | static double trunc(double x) { |
139 | sInt64 ll; |
140 | ll=(sInt64)(x); |
141 | return (double)ll; |
142 | } |
143 | #endif |
144 | |
145 | |
146 | #ifndef PLATFORM_DATE2LINEARDATE |
147 | |
148 | // helper: Returns the biggest integer smaller than x |
149 | static sInt32 lfloor(double x) { |
150 | #if ( defined __MACH__ && defined __GNUC__4 ) || defined _MSC_VER // XCode or Visual Studio |
151 | if (x<0) x= x-1; |
152 | return lround( x-0.5 ); |
153 | #else |
154 | return (sInt32)floor( x ); |
155 | #endif |
156 | } // lfloor |
157 | |
158 | // convert date to linear date (generic version using our internal scale) |
159 | /* procedure calcEphTime(year:integer;month,day:byte;hour:single;var julDat:double); |
160 | { Berechnet Julianisches Datum aus Weltzeit } */ |
161 | lineardate_t date2lineardate(sInt16 aYear, sInt16 aMonth, sInt16 aDay) |
162 | { |
163 | // use custom algorithm that goes back to year -4712... |
164 | |
165 | /* const MinYear= -4712; */ |
166 | const sInt32 MinYear = -4712; |
167 | |
168 | /* var a,b:integer; */ |
169 | sInt32 a,b; |
170 | |
171 | /* if aMonth<3 then begin year:=year-1; aMonth:=aMonth+12; end; */ |
172 | if (aMonth<3) { aYear--; aMonth+=12; } |
173 | /* if (aYear<1582) or |
174 | ((aYear=1582) and (aMonth<10)) or |
175 | ((aYear=1582) and (aMonth=10) and (aDay<15)) */ |
176 | if ( |
177 | aYear<1582 || |
178 | (aYear==1582 && aMonth<10) || |
179 | (aYear==1582 && aMonth==10 && aDay<15) |
180 | ) { |
181 | // julian |
182 | /* then b:=0 { julianisch } */ |
183 | b=0; |
184 | } |
185 | else { |
186 | // gregorian |
187 | /* else begin a:=floor(aYear/100); b:=2-a+floor(a/4) end; { gregorianisch } */ |
188 | a=lfloor(aYear/100); |
189 | b=2-a+lfloor(a/4); |
190 | } |
191 | // now calc julian date |
192 | /*JulDat:=floor(365.25*(aYear-minYear)+1E-6)+round(30.6*(aMonth-3))+aDay+b+58.5; |
193 | JulDat:=JulDat+hour/24; */ |
194 | return( |
195 | (lfloor(365.25*(aYear-MinYear)+1E-6)+lround(30.6*(aMonth-3))+aDay+b+59) |
196 | - linearDateOriginOffset // apply offset used for this target platform |
197 | ); |
198 | } // date2lineardate |
199 | |
200 | #endif // PLATFORM_DATE2LINEARDATE |
201 | |
202 | |
203 | // convert date to linear time |
204 | lineartime_t date2lineartime(sInt16 aYear, sInt16 aMonth, sInt16 aDay) |
205 | { |
206 | return date2lineardate(aYear,aMonth,aDay) * linearDateToTimeFactor; |
207 | } // date2lineartime |
208 | |
209 | |
210 | // convert time to linear time |
211 | lineartime_t time2lineartime(sInt16 aHour, sInt16 aMinute, sInt16 aSecond, sInt16 aMS) |
212 | { |
213 | lineartime_t ti = |
214 | ((((lineartime_t)aHour)*60 + |
215 | (lineartime_t)aMinute)*60 + |
216 | (lineartime_t)aSecond)*secondToLinearTimeFactor; |
217 | if (secondToLinearTimeFactor==1000) |
218 | ti+=aMS; |
219 | return ti; |
220 | } // time2lineartime |
221 | |
222 | |
223 | // convert lineardate to weekday |
224 | // 0=sunday, 1=monday ... 6=saturday |
225 | sInt16 lineardate2weekday(lineardate_t aLinearDate) |
226 | { |
227 | return (aLinearDate+linearDateOriginWeekday) % 7; |
228 | } // lineardate2weekday |
229 | |
230 | |
231 | // convert lineartime to weekday |
232 | // 0=sunday, 1=monday ... 6=saturday |
233 | sInt16 lineartime2weekday(lineartime_t aLinearTime) |
234 | { |
235 | // juldat seems to be sunday-based :-) |
236 | return lineardate2weekday(aLinearTime / linearDateToTimeFactor); |
237 | } // lineardate2weekday |
238 | |
239 | |
240 | // get number of days in a month |
241 | sInt16 getMonthDays(lineardate_t aLinearDate) |
242 | { |
243 | sInt16 y,m,d; |
244 | lineardate_t ld; |
245 | |
246 | // get year and month of given date |
247 | lineardate2date(aLinearDate,&y,&m,&d); |
248 | // get first of this month |
249 | ld = date2lineardate(y,m,1); |
250 | // calculate next month |
251 | m++; |
252 | if (m>12) { m=1; y++; } |
253 | // return difference between 1st of current and 1st of next month = number of days in month |
254 | return date2lineardate(y,m,1) - ld; |
255 | } // getMonthDays |
256 | |
257 | |
258 | |
259 | #ifndef PLATFORM_LINEARDATE2DATE |
260 | |
261 | // convert lineardate to year/month/day |
262 | /* |
263 | procedure calcDat(zeitZone,julDat:double;var year:integer;var month,day,hour,min:byte;var sec:single); |
264 | { Berechnet das Kalenderdatum und Weltzeit aus Julianischem Datum } |
265 | */ |
266 | void lineardate2date(lineardate_t aLinearDate,sInt16 *aYearP, sInt16 *aMonthP, sInt16 *aDayP) |
267 | { |
268 | // custom algorithm |
269 | |
270 | /* |
271 | var JD0,JD,C,E:double; |
272 | B,D,F:integer; |
273 | hh:single; |
274 | */ |
275 | double C,E; |
276 | sInt32 B,D,F; |
277 | |
278 | // apply offset correction |
279 | aLinearDate+=linearDateOriginOffset; |
280 | |
281 | // no time, no "correction" for date change at noon |
282 | /* JD:=julDat+zeitZone/24; |
283 | JD0:=sInt32(Jd+0.5); */ |
284 | /* |
285 | if JD0<2299161 then begin |
286 | B:=0; |
287 | C:=JD0+1524; |
288 | end |
289 | else begin |
290 | B:=trunc((JD0-1867216.25)/36524.25); |
291 | C:=Jd0+(B-trunc(B/4))+1525.0; |
292 | end; |
293 | */ |
294 | if (aLinearDate<2299161) { |
295 | B=0; |
Value stored to 'B' is never read | |
296 | C=aLinearDate+1524; |
297 | } |
298 | else { |
299 | B=(sInt32)(trunc((aLinearDate-1867216.25)/36524.25)); |
300 | C=aLinearDate+(B-trunc((double)B/4))+1525.0; |
301 | } |
302 | /* |
303 | D:=trunc((C-122.1)/365.25); |
304 | E:=365.0*D+trunc(D/4); |
305 | F:=trunc((C-E)/30.6001); |
306 | day:=trunc(C-E+0.5)-trunc(30.6001*F); |
307 | month:=F-1-12*trunc(F/14); |
308 | year:=D-4715-trunc((7+month)/10); |
309 | */ |
310 | D=(sInt32)(trunc((C-122.1)/365.25)); |
311 | E=365.0*D+trunc((double)D/4); |
312 | F=(sInt32)(trunc((C-E)/30.6001)); |
313 | // return date |
314 | sInt16 month = (sInt16)(F-1-12*trunc((double)F/14)); |
315 | if (aDayP) *aDayP=(sInt16)(trunc(C-E+0.5)-trunc(30.6001*F)); |
316 | if (aMonthP) *aMonthP=month; |
317 | if (aYearP) *aYearP=(sInt16)(D-4715-trunc((double)(7+month)/10.0)); |
318 | // no time |
319 | /* |
320 | hh:=24*(JD+0.5-JD0); |
321 | hour:=trunc(hh); |
322 | hh:=(hh-hour)*60; |
323 | min:=trunc(hh); |
324 | hh:=(hh-min)*60; |
325 | sec:=trunc(hh); |
326 | */ |
327 | } // lineardate2date |
328 | |
329 | #endif // PLATFORM_LINEARDATE2DATE |
330 | |
331 | |
332 | // convert lineartime to year/month/day |
333 | void lineartime2date(lineartime_t aLinearTime, sInt16 *aYearP, sInt16 *aMonthP, sInt16 *aDayP) |
334 | { |
335 | lineardate2date(lineartime2dateonly(aLinearTime), aYearP, aMonthP, aDayP); |
336 | } // lineartime2date |
337 | |
338 | |
339 | // convert lineartime to h,m,s,ms |
340 | void lineartime2time(lineartime_t aLinearTime, sInt16 *aHourP, sInt16 *aMinP, sInt16 *aSecP, sInt16 *aMSP) |
341 | { |
342 | if (aLinearTime<0) { |
343 | // negative time, create wrap around to make sure time remains positive |
344 | aLinearTime = lineartime2timeonly(aLinearTime); |
345 | } |
346 | if (secondToLinearTimeFactor==1) { |
347 | // no sub-seconds |
348 | if (aMSP) *aMSP = 0; |
349 | } |
350 | else { |
351 | // we have sub-seconds |
352 | if (aMSP) *aMSP = aLinearTime % secondToLinearTimeFactor; |
353 | aLinearTime /= secondToLinearTimeFactor; |
354 | } |
355 | if (aSecP) *aSecP = aLinearTime % 60; |
356 | aLinearTime /= 60; |
357 | if (aMinP) *aMinP = aLinearTime % 60; |
358 | aLinearTime /= 60; |
359 | if (aHourP) *aHourP = aLinearTime % 24; // to make sure we don't convert date part |
360 | } // lineartime2time |
361 | |
362 | |
363 | // convert seconds to linear time |
364 | lineartime_t seconds2lineartime(sInt32 aSeconds) |
365 | { |
366 | return aSeconds*secondToLinearTimeFactor; |
367 | } // seconds2lineartime |
368 | |
369 | |
370 | // convert linear time to seconds |
371 | sInt32 lineartime2seconds(lineartime_t aLinearTime) |
372 | { |
373 | return aLinearTime/secondToLinearTimeFactor; |
374 | } // lineartime2seconds |
375 | |
376 | |
377 | // get time-only part of a linear time |
378 | lineartime_t lineartime2timeonly(lineartime_t aLinearTime) |
379 | { |
380 | //return aLinearTime % linearDateToTimeFactor; |
381 | return aLinearTime-lineartime2dateonlyTime(aLinearTime); |
382 | } // lineartime2timeonly |
383 | |
384 | |
385 | // get date-only part of a linear time |
386 | lineardate_t lineartime2dateonly(lineartime_t aLinearTime) |
387 | { |
388 | return aLinearTime/linearDateToTimeFactor - (aLinearTime<0 ? 1 : 0); |
389 | } // lineartime2dateonly |
390 | |
391 | |
392 | // get date-only part of a linear time, in lineartime_t units |
393 | lineartime_t lineartime2dateonlyTime(lineartime_t aLinearTime) |
394 | { |
395 | lineartime_t ts = lineartime2dateonly(aLinearTime); |
396 | ts *= linearDateToTimeFactor; |
397 | return ts; |
398 | } // lineartime2dateonlyTime |
399 | |
400 | |
401 | } // namespace sysync |
402 | |
403 | /* eof */ |