1 : #include <stdio.h>
2 : #include <string.h>
3 : #include <stdlib.h>
4 : #include <time.h>
5 : #include <math.h>
6 : #include <ctype.h>
7 : #include "clock.h"
8 : #include "myutil.h"
9 : #include "myassert.h"
10 : #ifdef MEMWATCH
11 : #include "memwatch.h"
12 : #endif
13 :
14 : /* Take a look at the options in:
15 : * http://www.unet.univie.ac.at/aix/cmds/aixcmds2/date.htm#A270961
16 : */
17 : /* Timezone is defined through out as the time needed to add to local time
18 : * to get UTC, rather than the reverse. So EST is +5 not -5. */
19 :
20 : #define PERIOD_YEARS 146097L
21 : #define SEC_DAY 86400L
22 : #define ISLEAPYEAR(y) (((y)%400 == 0) || (((y)%4 == 0) && ((y)%100 != 0)))
23 :
24 : /*****************************************************************************
25 : * ThirdMonday() --
26 : *
27 : * Carl McCalla / MDL
28 : *
29 : * PURPOSE
30 : * Compute the day-of-the-month which is the third Monday of the month.
31 : *
32 : * ARGUMENTS
33 : * monthStartDOW = starting day of the week (e.g., 0 = Sunday, 1 = Monday,
34 : * etc.) (Input)
35 : *
36 : * RETURNS
37 : * int (the day-of-the-month which is the third Monday of the month)
38 : *
39 : * HISTORY
40 : * 6/2006 Carl McCalla, Sr. (MDL): Created
41 : *
42 : * NOTES
43 : * ***************************************************************************
44 : */
45 0 : static int ThirdMonday (int monthStartDOW)
46 : {
47 0 : if (monthStartDOW == 0) {
48 0 : return 16;
49 0 : } else if (monthStartDOW == 1) {
50 0 : return 15;
51 : } else {
52 0 : return ((7 - monthStartDOW) + 16);
53 : }
54 : }
55 :
56 : /*****************************************************************************
57 : * Memorialday() --
58 : *
59 : * Carl McCalla / MDL
60 : *
61 : * PURPOSE
62 : * For the month of May, compute the day-of-the-month which is Memorial Day.
63 : *
64 : * ARGUMENTS
65 : * monthStartDOW = starting day of the week (e.g., 0 = Sunday, 1 = Monday,
66 : * etc.) (Input)
67 : *
68 : * RETURNS
69 : * int (the day-of-the-month which is Memorial Day)
70 : *
71 : * HISTORY
72 : * 6/2006 Carl McCalla, Sr. (MDL): Created
73 : *
74 : * NOTES
75 : * ***************************************************************************
76 : */
77 0 : static int Memorialday (int monthStartDOW)
78 : {
79 0 : if (monthStartDOW == 0) {
80 0 : return 30;
81 0 : } else if (monthStartDOW == 6) {
82 0 : return 31;
83 : } else {
84 0 : return ((5 - monthStartDOW) + 25);
85 : }
86 : }
87 :
88 : /*****************************************************************************
89 : * Laborday() --
90 : *
91 : * Carl McCalla / MDL
92 : *
93 : * PURPOSE
94 : * For the month of September, compute the day-of-the-month which is Labor
95 : * Day.
96 : *
97 : * ARGUMENTS
98 : * monthStartDOW = starting day of the week (e.g., 0 = Sunday, 1 = Monday,
99 : * etc.) (Input)
100 : *
101 : * RETURNS
102 : * int (the day-of-the-month which is Labor Day)
103 : *
104 : * HISTORY
105 : * 6/2006 Carl McCalla, Sr. (MDL): Created
106 : *
107 : * NOTES
108 : * ***************************************************************************
109 : */
110 0 : static int Laborday (int monthStartDOW)
111 : {
112 0 : if (monthStartDOW == 0) {
113 0 : return 2;
114 0 : } else if (monthStartDOW == 1) {
115 0 : return 1;
116 : } else {
117 0 : return ((6 - monthStartDOW) + 3);
118 : }
119 : }
120 :
121 : /*****************************************************************************
122 : * Columbusday() --
123 : *
124 : * Carl McCalla /MDL
125 : *
126 : * PURPOSE
127 : * For the month of October, compute the day-of-the-month which is Columbus
128 : * Day.
129 : *
130 : * ARGUMENTS
131 : * monthStartDOW = starting day of the week (e.g., 0 = Sunday, 1 = Monday,
132 : * etc.) (Input)
133 : *
134 : * RETURNS
135 : * int (the day-of-the-month which is Columbus Day)
136 : *
137 : * HISTORY
138 : * 6/2006 Carl McCalla, Sr. (MDL): Created
139 : *
140 : * NOTES
141 : * ***************************************************************************
142 : */
143 0 : static int Columbusday (int monthStartDOW)
144 : {
145 0 : if ((monthStartDOW == 0) || (monthStartDOW == 1)) {
146 0 : return (9 - monthStartDOW);
147 : } else {
148 0 : return (16 - monthStartDOW);
149 : }
150 : }
151 :
152 : /*****************************************************************************
153 : * Thanksgivingday() --
154 : *
155 : * Carl McCalla /MDL
156 : *
157 : * PURPOSE
158 : * For the month of November, compute the day-of-the-month which is
159 : * Thanksgiving Day.
160 : *
161 : * ARGUMENTS
162 : * monthStartDOW = starting day of the week (e.g., 0 = Sunday, 1 = Monday,
163 : * etc.) (Input)
164 : *
165 : * RETURNS
166 : * int (the day-of-the-month which is Thanksgiving Day)
167 : *
168 : * HISTORY
169 : * 6/2006 Carl McCalla, Sr. (MDL): Created
170 : *
171 : * NOTES
172 : * ***************************************************************************
173 : */
174 0 : static int Thanksgivingday (int monthStartDOW)
175 : {
176 0 : if ((monthStartDOW >= 0) && (monthStartDOW <= 4)) {
177 0 : return (26 - monthStartDOW);
178 0 : } else if (monthStartDOW == 5) {
179 0 : return 28;
180 : } else {
181 0 : return 27;
182 : }
183 : }
184 :
185 : /*****************************************************************************
186 : * Clock_Holiday() --
187 : *
188 : * Carl McCalla /MDL
189 : *
190 : * PURPOSE
191 : * Return a holiday string (e.g., Christmas Day, Thanksgiving Day, etc.), if
192 : * the current day of the month is a federal holiday.
193 : *
194 : * ARGUMENTS
195 : * month = month of the year (e.g., 1 = Jan, 2 = Feb, etc.) (Input)
196 : * day = the current day of the month (e.g., 1, 2, 3 ...) (Input)
197 : * monthStartDOW = the day-of-the-month which is the first day of the month
198 : * (e.g., 0 = Sunday, 1 = Monday, etc.)
199 : * answer = String containing the holiday string, if the current day is
200 : * a federal holiday, or a "", if the current day is not a
201 : * federal holiday.
202 : *
203 : * RETURNS
204 : * void
205 : *
206 : * HISTORY
207 : * 6/2006 Carl McCalla, Sr. (MDL): Created
208 : *
209 : * NOTES
210 : * ***************************************************************************
211 : */
212 0 : static void Clock_Holiday (int month, int day, int monthStartDOW,
213 : char answer[100])
214 : {
215 0 : switch (month) {
216 : case 1: /* January */
217 0 : if (day == 1) {
218 0 : strcpy (answer, "New Years Day");
219 0 : return;
220 0 : } else if (ThirdMonday (monthStartDOW) == day) {
221 0 : strcpy (answer, "Martin Luther King Jr Day");
222 0 : return;
223 : }
224 0 : break;
225 : case 2: /* February */
226 0 : if (ThirdMonday (monthStartDOW) == day) {
227 0 : strcpy (answer, "Presidents Day");
228 0 : return;
229 : }
230 0 : break;
231 : case 5: /* May */
232 0 : if (Memorialday (monthStartDOW) == day) {
233 0 : strcpy (answer, "Memorial Day");
234 0 : return;
235 : }
236 0 : break;
237 : case 7: /* July */
238 0 : if (day == 4) {
239 0 : strcpy (answer, "Independence Day");
240 0 : return;
241 : }
242 0 : break;
243 : case 9: /* September */
244 0 : if (Laborday (monthStartDOW) == day) {
245 0 : strcpy (answer, "Labor Day");
246 0 : return;
247 : }
248 0 : break;
249 : case 10: /* October */
250 0 : if (Columbusday (monthStartDOW) == day) {
251 0 : strcpy (answer, "Columbus Day");
252 0 : return;
253 : }
254 0 : break;
255 : case 11: /* November */
256 0 : if (day == 11) {
257 0 : strcpy (answer, "Veterans Day");
258 0 : return;
259 0 : } else if (Thanksgivingday (monthStartDOW) == day) {
260 0 : strcpy (answer, "Thanksgiving Day");
261 0 : return;
262 : }
263 0 : break;
264 : case 12: /* December */
265 0 : if (day == 25) {
266 0 : strcpy (answer, "Christmas Day");
267 0 : return;
268 : }
269 : break;
270 : }
271 0 : strcpy (answer, "");
272 0 : return;
273 : }
274 :
275 : /*****************************************************************************
276 : * Clock_Epock2YearDay() --
277 : *
278 : * Arthur Taylor / MDL
279 : *
280 : * PURPOSE
281 : * To convert the days since the beginning of the epoch to days since
282 : * beginning of the year and years since the beginning of the epoch.
283 : *
284 : * ARGUMENTS
285 : * totDay = Number of days since the beginning of the epoch. (Input)
286 : * Day = The days since the beginning of the year. (Output)
287 : * Yr = The years since the epoch. (Output)
288 : *
289 : * RETURNS: void
290 : *
291 : * HISTORY
292 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
293 : * 6/2004 AAT (MDL): Updated.
294 : *
295 : * NOTES
296 : *****************************************************************************
297 : */
298 12 : void Clock_Epoch2YearDay (sInt4 totDay, int *Day, sInt4 *Yr)
299 : {
300 : sInt4 year; /* Local copy of the year. */
301 :
302 12 : year = 1970;
303 : /* Jump to the correct 400 year period of time. */
304 12 : if ((totDay <= -PERIOD_YEARS) || (totDay >= PERIOD_YEARS)) {
305 0 : year += 400 * (totDay / PERIOD_YEARS);
306 0 : totDay -= PERIOD_YEARS * (totDay / PERIOD_YEARS);
307 : }
308 12 : if (totDay >= 0) {
309 152 : while (totDay >= 366) {
310 232 : if (ISLEAPYEAR (year)) {
311 104 : if (totDay >= 1461) {
312 100 : year += 4;
313 100 : totDay -= 1461;
314 4 : } else if (totDay >= 1096) {
315 4 : year += 3;
316 4 : totDay -= 1096;
317 0 : } else if (totDay >= 731) {
318 0 : year += 2;
319 0 : totDay -= 731;
320 : } else {
321 0 : year++;
322 0 : totDay -= 366;
323 : }
324 : } else {
325 24 : year++;
326 24 : totDay -= 365;
327 : }
328 : }
329 12 : if ((totDay == 365) && (!ISLEAPYEAR (year))) {
330 0 : year++;
331 0 : totDay -= 365;
332 : }
333 : } else {
334 0 : while (totDay <= -366) {
335 0 : year--;
336 0 : if (ISLEAPYEAR (year)) {
337 0 : if (totDay <= -1461) {
338 0 : year -= 3;
339 0 : totDay += 1461;
340 0 : } else if (totDay <= -1096) {
341 0 : year -= 2;
342 0 : totDay += 1096;
343 0 : } else if (totDay <= -731) {
344 0 : year--;
345 0 : totDay += 731;
346 : } else {
347 0 : totDay += 366;
348 : }
349 : } else {
350 0 : totDay += 365;
351 : }
352 : }
353 0 : if (totDay < 0) {
354 0 : year--;
355 0 : if (ISLEAPYEAR (year)) {
356 0 : totDay += 366;
357 : } else {
358 0 : totDay += 365;
359 : }
360 : }
361 : }
362 12 : *Day = (int) totDay;
363 12 : *Yr = year;
364 12 : }
365 :
366 : /*****************************************************************************
367 : * Clock_MonthNum() --
368 : *
369 : * Arthur Taylor / MDL
370 : *
371 : * PURPOSE
372 : * Determine which numbered month it is given the day since the beginning of
373 : * the year, and the year since the beginning of the epoch.
374 : *
375 : * ARGUMENTS
376 : * day = Day since the beginning of the year. (Input)
377 : * year = Year since the beginning of the epoch. (Input)
378 : *
379 : * RETURNS: int (which month it is)
380 : *
381 : * HISTORY
382 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
383 : * 6/2004 AAT (MDL): Updated.
384 : *
385 : * NOTES
386 : *****************************************************************************
387 : */
388 12 : int Clock_MonthNum (int day, sInt4 year)
389 : {
390 12 : if (day < 31)
391 4 : return 1;
392 8 : if (ISLEAPYEAR (year))
393 8 : day -= 1;
394 8 : if (day < 59)
395 8 : return 2;
396 0 : if (day <= 89)
397 0 : return 3;
398 0 : if (day == 242)
399 0 : return 8;
400 0 : return ((day + 64) * 5) / 153 - 1;
401 : }
402 :
403 : /*****************************************************************************
404 : * Clock_NumDay() --
405 : *
406 : * Arthur Taylor / MDL
407 : *
408 : * PURPOSE
409 : * Returns either the number of days in the month or the number of days
410 : * since the begining of the year.
411 : *
412 : * ARGUMENTS
413 : * month = Month in question. (Input)
414 : * day = Day of month in question (Input)
415 : * year = years since the epoch (Input)
416 : * f_tot = 1 if we want total days from begining of year,
417 : * 0 if we want total days in the month. (Input)
418 : *
419 : * RETURNS: int
420 : * Either the number of days in the month, or
421 : * the number of days since the beginning of they year.
422 : *
423 : * HISTORY
424 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
425 : *
426 : * NOTES
427 : *****************************************************************************
428 : */
429 68 : int Clock_NumDay (int month, int day, sInt4 year, char f_tot)
430 : {
431 68 : if (f_tot == 1) {
432 40 : if (month > 2) {
433 0 : if (ISLEAPYEAR (year)) {
434 0 : return ((month + 1) * 153) / 5 - 63 + day;
435 : } else {
436 0 : return ((month + 1) * 153) / 5 - 64 + day;
437 : }
438 : } else {
439 40 : return (month - 1) * 31 + day - 1;
440 : }
441 : } else {
442 28 : if (month == 1) {
443 14 : return 31;
444 14 : } else if (month != 2) {
445 0 : if ((((month - 3) % 5) % 2) == 1) {
446 0 : return 30;
447 : } else {
448 0 : return 31;
449 : }
450 : } else {
451 14 : if (ISLEAPYEAR (year)) {
452 14 : return 29;
453 : } else {
454 0 : return 28;
455 : }
456 : }
457 : }
458 : }
459 :
460 : /*****************************************************************************
461 : * Clock_FormatParse() --
462 : *
463 : * Arthur Taylor / MDL
464 : *
465 : * PURPOSE
466 : * To format part of the output clock string.
467 : *
468 : * ARGUMENTS
469 : * buffer = The output string to write to. (Output)
470 : * sec = Seconds since beginning of day. (Input)
471 : * floatSec = Part of a second since beginning of second. (Input)
472 : * totDay = Days since the beginning of the epoch. (Input)
473 : * year = Years since the beginning of the epoch (Input)
474 : * month = Month since the beginning of the year (Input)
475 : * day = Days since the beginning of the year (Input)
476 : * format = Which part of the format string we are working on. (Input)
477 : *
478 : * RETURNS: void
479 : *
480 : * HISTORY
481 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
482 : * 6/2004 AAT (MDL): Updated.
483 : *
484 : * NOTES
485 : *****************************************************************************
486 : */
487 60 : static void Clock_FormatParse (char buffer[100], sInt4 sec, float floatSec,
488 : sInt4 totDay, sInt4 year, int month, int day,
489 : char format)
490 : {
491 : static char *MonthName[] = {
492 : "January", "February", "March", "April", "May", "June", "July",
493 : "August", "September", "October", "November", "December"
494 : };
495 : static char *DayName[] = {
496 : "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
497 : "Saturday"
498 : };
499 : int dy; /* # of days from start of year to start of month. */
500 : int i; /* Temporary variable to help with computations. */
501 : int DOM; /* Day of the Month (e.g., 1-31) */
502 : int DOW; /* Numeric day of the week (e.g., 0 = Sunday, 1 =
503 : * Monday, etc. */
504 : int monthStartDOW; /* Numeric day of the week of the 1st day of the
505 : * month */
506 : char temp[100]; /* Helps parse the %D, %T, %r, and %R options. */
507 :
508 60 : switch (format) {
509 : case 'd':
510 12 : dy = (Clock_NumDay (month, 1, year, 1) - 1);
511 12 : sprintf (buffer, "%02d", day - dy);
512 12 : return;
513 : case 'm':
514 12 : sprintf (buffer, "%02d", month);
515 12 : return;
516 : case 'E':
517 0 : sprintf (buffer, "%2d", month);
518 0 : return;
519 : case 'Y':
520 12 : sprintf (buffer, "%04d", year);
521 12 : return;
522 : case 'H':
523 12 : sprintf (buffer, "%02d", (int) ((sec % 86400L) / 3600));
524 12 : return;
525 : case 'G':
526 0 : sprintf (buffer, "%2d", (int) ((sec % 86400L) / 3600));
527 0 : return;
528 : case 'M':
529 12 : sprintf (buffer, "%02d", (int) ((sec % 3600) / 60));
530 12 : return;
531 : case 'S':
532 0 : sprintf (buffer, "%02d", (int) (sec % 60));
533 0 : return;
534 : case 'f':
535 0 : sprintf (buffer, "%05.2f", ((int) (sec % 60)) + floatSec);
536 0 : return;
537 : case 'n':
538 0 : sprintf (buffer, "\n");
539 0 : return;
540 : case '%':
541 0 : sprintf (buffer, "%%");
542 0 : return;
543 : case 't':
544 0 : sprintf (buffer, "\t");
545 0 : return;
546 : case 'y':
547 0 : sprintf (buffer, "%02d", (int) (year % 100));
548 0 : return;
549 : case 'I':
550 0 : i = ((sec % 43200L) / 3600);
551 0 : if (i == 0) {
552 0 : sprintf (buffer, "12");
553 : } else {
554 0 : sprintf (buffer, "%02d", i);
555 : }
556 0 : return;
557 : case 'p':
558 0 : if (((sec % 86400L) / 3600) >= 12) {
559 0 : sprintf (buffer, "PM");
560 : } else {
561 0 : sprintf (buffer, "AM");
562 : }
563 0 : return;
564 : case 'B':
565 0 : strcpy (buffer, MonthName[month - 1]);
566 0 : return;
567 : case 'A':
568 0 : strcpy (buffer, DayName[(4 + totDay) % 7]);
569 0 : return;
570 : case 'b':
571 : case 'h':
572 0 : strcpy (buffer, MonthName[month - 1]);
573 0 : buffer[3] = '\0';
574 0 : return;
575 : case 'a':
576 0 : strcpy (buffer, DayName[(4 + totDay) % 7]);
577 0 : buffer[3] = '\0';
578 0 : return;
579 : case 'w':
580 0 : sprintf (buffer, "%d", (int) ((4 + totDay) % 7));
581 0 : return;
582 : case 'j':
583 0 : sprintf (buffer, "%03d", day + 1);
584 0 : return;
585 : case 'e':
586 0 : dy = (Clock_NumDay (month, 1, year, 1) - 1);
587 0 : sprintf (buffer, "%d", (int) (day - dy));
588 0 : return;
589 : case 'W':
590 0 : i = (1 - ((4 + totDay - day) % 7)) % 7;
591 0 : if (day < i)
592 0 : sprintf (buffer, "00");
593 : else
594 0 : sprintf (buffer, "%02d", ((day - i) / 7) + 1);
595 0 : return;
596 : case 'U':
597 0 : i = (-((4 + totDay - day) % 7)) % 7;
598 0 : if (day < i)
599 0 : sprintf (buffer, "00");
600 : else
601 0 : sprintf (buffer, "%02d", ((day - i) / 7) + 1);
602 0 : return;
603 : case 'D':
604 0 : Clock_FormatParse (buffer, sec, floatSec, totDay, year, month,
605 : day, 'm');
606 0 : strcat (buffer, "/");
607 0 : Clock_FormatParse (temp, sec, floatSec, totDay, year, month,
608 : day, 'd');
609 0 : strcat (buffer, temp);
610 0 : strcat (buffer, "/");
611 0 : Clock_FormatParse (temp, sec, floatSec, totDay, year, month,
612 : day, 'Y');
613 0 : strcat (buffer, temp);
614 0 : return;
615 : case 'T':
616 0 : Clock_FormatParse (buffer, sec, floatSec, totDay, year, month,
617 : day, 'H');
618 0 : strcat (buffer, ":");
619 0 : Clock_FormatParse (temp, sec, floatSec, totDay, year, month,
620 : day, 'M');
621 0 : strcat (buffer, temp);
622 0 : strcat (buffer, ":");
623 0 : Clock_FormatParse (temp, sec, floatSec, totDay, year, month,
624 : day, 'S');
625 0 : strcat (buffer, temp);
626 0 : return;
627 : case 'r':
628 0 : Clock_FormatParse (buffer, sec, floatSec, totDay, year, month,
629 : day, 'I');
630 0 : strcat (buffer, ":");
631 0 : Clock_FormatParse (temp, sec, floatSec, totDay, year, month,
632 : day, 'M');
633 0 : strcat (buffer, temp);
634 0 : strcat (buffer, ":");
635 0 : Clock_FormatParse (temp, sec, floatSec, totDay, year, month,
636 : day, 'S');
637 0 : strcat (buffer, temp);
638 0 : strcat (buffer, " ");
639 0 : Clock_FormatParse (temp, sec, floatSec, totDay, year, month,
640 : day, 'p');
641 0 : strcat (buffer, temp);
642 0 : return;
643 : case 'R':
644 0 : Clock_FormatParse (buffer, sec, floatSec, totDay, year, month,
645 : day, 'H');
646 0 : strcat (buffer, ":");
647 0 : Clock_FormatParse (temp, sec, floatSec, totDay, year, month,
648 : day, 'M');
649 0 : strcat (buffer, temp);
650 0 : return;
651 :
652 : /* If the current day is a federal holiday, then return a pointer to
653 : * the appropriate holiday string (e.g., "Martin Luther King Day") */
654 : case 'v':
655 : /* Clock_FormatParse 'd' */
656 0 : dy = (Clock_NumDay (month, 1, year, 1) - 1);
657 0 : DOM = day - dy;
658 : /* Clock_FormatParse 'w' */
659 0 : DOW = (int) ((4 + totDay) % 7);
660 :
661 0 : if ((DOM % 7) != 1) {
662 0 : monthStartDOW = DOW - ((DOM % 7) - 1);
663 0 : if (monthStartDOW < 0) {
664 0 : monthStartDOW = 7 + monthStartDOW;
665 : }
666 : } else {
667 0 : monthStartDOW = DOW;
668 : }
669 :
670 0 : Clock_Holiday (month, DOM, monthStartDOW, temp);
671 0 : if (temp[0] != '\0') {
672 0 : strcpy (buffer, temp);
673 : } else {
674 0 : Clock_FormatParse (buffer, sec, floatSec, totDay, year, month,
675 : day, 'A');
676 : }
677 0 : return;
678 : default:
679 0 : sprintf (buffer, "unknown %c", format);
680 0 : return;
681 : }
682 : }
683 :
684 : /*****************************************************************************
685 : * Clock_GetTimeZone() --
686 : *
687 : * Arthur Taylor / MDL
688 : *
689 : * PURPOSE
690 : * Returns the time zone offset in hours to add to local time to get UTC.
691 : * So EST is +5 not -5.
692 : *
693 : * ARGUMENTS
694 : *
695 : * RETURNS: int
696 : *
697 : * HISTORY
698 : * 6/2004 Arthur Taylor (MDL): Created.
699 : * 3/2005 AAT: Found bug... Used to use 1/1/1970 00Z and find the local
700 : * hour. If CET, this means use 1969 date, which causes it to die.
701 : * Switched to 1/2/1970 00Z.
702 : * 3/2005 AAT: timeZone (see CET) can be < 0. don't add 24 if timeZone < 0
703 : *
704 : * NOTES
705 : *****************************************************************************
706 : */
707 0 : sChar Clock_GetTimeZone ()
708 : {
709 : struct tm time;
710 : time_t ansTime;
711 : struct tm *gmTime;
712 : static int timeZone = 9999;
713 :
714 0 : if (timeZone == 9999) {
715 : /* Cheap method of getting global time_zone variable. */
716 0 : memset (&time, 0, sizeof (struct tm));
717 0 : time.tm_year = 70;
718 0 : time.tm_mday = 2;
719 0 : ansTime = mktime (&time);
720 0 : gmTime = gmtime (&ansTime);
721 0 : timeZone = gmTime->tm_hour;
722 0 : if (gmTime->tm_mday != 2) {
723 0 : timeZone -= 24;
724 : }
725 : }
726 0 : return timeZone;
727 : }
728 :
729 : /*****************************************************************************
730 : * Clock_IsDaylightSaving() --
731 : *
732 : * Arthur Taylor / MDL
733 : *
734 : * PURPOSE
735 : * To determine if daylight savings is in effect. Daylight savings is in
736 : * effect from the first sunday in April to the last sunday in October.
737 : * At 2 AM ST (or 3 AM DT) in April -> 3 AM DT (and we return 1)
738 : * At 2 AM DT (or 1 AM ST) in October -> 1 AM ST (and we return 0)
739 : *
740 : * ARGUMENTS
741 : * clock = The time stored as a double. (Input)
742 : * TimeZone = hours to add to local time to get UTC. (Input)
743 : *
744 : * RETURNS: int
745 : * 0 if not in daylight savings time.
746 : * 1 if in daylight savings time.
747 : *
748 : * HISTORY
749 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
750 : * 6/2004 AAT (MDL): Updated.
751 : *
752 : * NOTES
753 : *****************************************************************************
754 : */
755 0 : int Clock_IsDaylightSaving2 (double clock, sChar TimeZone)
756 : {
757 : sInt4 totDay, year;
758 : int day, first;
759 : double secs;
760 :
761 0 : clock = clock - TimeZone * 3600.;
762 : /* Clock should now be in Standard Time, so comparisons later have to be
763 : * based on Standard Time. */
764 :
765 0 : totDay = (sInt4) floor (clock / SEC_DAY);
766 0 : Clock_Epoch2YearDay (totDay, &day, &year);
767 : /* Figure out number of seconds since beginning of year. */
768 0 : secs = clock - (totDay - day) * SEC_DAY;
769 :
770 : /* figure out if 1/1/year is mon/tue/.../sun */
771 0 : first = ((4 + (totDay - day)) % 7); /* -day should get 1/1 but may need
772 : * -day+1 => sun == 0, ... sat == 6 */
773 :
774 : /* figure out if year is a leap year */
775 0 : if (((year % 4) == 0) && (((year % 100) != 0) || ((year % 400) == 0))) {
776 : /* look up extents of daylight savings. for leap year. */
777 0 : switch (first) {
778 : case 0:
779 0 : if ((secs >= 7869600.0) && (secs <= 26010000.0))
780 0 : return 1;
781 : else
782 0 : return 0;
783 : case 1:
784 0 : if ((secs >= 8388000.0) && (secs <= 25923600.0))
785 0 : return 1;
786 : else
787 0 : return 0;
788 : case 2:
789 0 : if ((secs >= 8301600.0) && (secs <= 25837200.0))
790 0 : return 1;
791 : else
792 0 : return 0;
793 : case 3:
794 0 : if ((secs >= 8215200.0) && (secs <= 25750800.0))
795 0 : return 1;
796 : else
797 0 : return 0;
798 : case 4:
799 0 : if ((secs >= 8128800.0) && (secs <= 26269200.0))
800 0 : return 1;
801 : else
802 0 : return 0;
803 : case 5:
804 0 : if ((secs >= 8042400.0) && (secs <= 26182800.0))
805 0 : return 1;
806 : else
807 0 : return 0;
808 : case 6:
809 0 : if ((secs >= 7956000.0) && (secs <= 26096400.0))
810 0 : return 1;
811 : else
812 0 : return 0;
813 : }
814 : } else {
815 0 : switch (first) {
816 : case 0:
817 0 : if ((secs >= 7869600.0) && (secs <= 26010000.0))
818 0 : return 1;
819 : else
820 0 : return 0;
821 : case 1:
822 0 : if ((secs >= 7783200.0) && (secs <= 25923600.0))
823 0 : return 1;
824 : else
825 0 : return 0;
826 : case 2:
827 0 : if ((secs >= 8301600.0) && (secs <= 25837200.0))
828 0 : return 1;
829 : else
830 0 : return 0;
831 : case 3:
832 0 : if ((secs >= 8215200.0) && (secs <= 25750800.0))
833 0 : return 1;
834 : else
835 0 : return 0;
836 : case 4:
837 0 : if ((secs >= 8128800.0) && (secs <= 26664400.0))
838 0 : return 1;
839 : else
840 0 : return 0;
841 : case 5:
842 0 : if ((secs >= 8042400.0) && (secs <= 26182800.0))
843 0 : return 1;
844 : else
845 0 : return 0;
846 : case 6:
847 0 : if ((secs >= 7956000.0) && (secs <= 26096400.0))
848 0 : return 1;
849 : else
850 0 : return 0;
851 : }
852 : }
853 0 : return 0;
854 : }
855 :
856 : /*****************************************************************************
857 : * Clock_PrintDate() --
858 : *
859 : * Arthur Taylor / MDL
860 : *
861 : * PURPOSE
862 : *
863 : * ARGUMENTS
864 : * clock = The time stored as a double. (Input)
865 : * year = The year. (Output)
866 : * month = The month. (Output)
867 : * day = The day. (Output)
868 : * hour = The hour. (Output)
869 : * min = The min. (Output)
870 : * sec = The second. (Output)
871 : *
872 : * RETURNS: void
873 : *
874 : * HISTORY
875 : * 3/2005 Arthur Taylor (MDL): Commented.
876 : *
877 : * NOTES
878 : *****************************************************************************
879 : */
880 0 : void Clock_PrintDate (double clock, sInt4 *year, int *month, int *day,
881 : int *hour, int *min, double *sec)
882 : {
883 : sInt4 totDay;
884 : sInt4 intSec;
885 :
886 0 : totDay = (sInt4) floor (clock / SEC_DAY);
887 0 : Clock_Epoch2YearDay (totDay, day, year);
888 0 : *month = Clock_MonthNum (*day, *year);
889 0 : *day = *day - Clock_NumDay (*month, 1, *year, 1) + 1;
890 0 : *sec = clock - ((double) totDay) * SEC_DAY;
891 0 : intSec = (sInt4) (*sec);
892 0 : *hour = (int) ((intSec % 86400L) / 3600);
893 0 : *min = (int) ((intSec % 3600) / 60);
894 0 : *sec = (intSec % 60) + (*sec - intSec);
895 0 : }
896 :
897 : /*****************************************************************************
898 : * Clock_Print() --
899 : *
900 : * Arthur Taylor / MDL
901 : *
902 : * PURPOSE
903 : * To create formated output from a time structure that is stored as a
904 : * double.
905 : *
906 : * ARGUMENTS
907 : * buffer = Destination to write the format to. (Output)
908 : * n = The number of characters in buffer. (Input)
909 : * clock = The time stored as a double. (Input)
910 : * format = The desired output format. (Input)
911 : * f_gmt = 0 output GMT, 1 output LDT, 2 output LST. (Input)
912 : *
913 : * RETURNS: void
914 : *
915 : * HISTORY
916 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
917 : * 6/2004 AAT (MDL): Updated.
918 : *
919 : * NOTES
920 : *****************************************************************************
921 : */
922 12 : void Clock_Print (char *buffer, int n, double clock, const char *format,
923 : char f_gmt)
924 : {
925 : sInt4 totDay, year;
926 : sInt4 sec;
927 : double floatSec;
928 : int month, day;
929 : size_t i;
930 : int j;
931 : char f_perc;
932 : char locBuff[100];
933 : sChar timeZone; /* Hours to add to local time to get UTC. */
934 :
935 : /* Handle gmt problems. */
936 12 : if (f_gmt != 0) {
937 0 : timeZone = Clock_GetTimeZone ();
938 : /* clock is currently in UTC */
939 0 : clock -= timeZone * 3600;
940 : /* clock is now in local standard time Note: A 0 is passed to
941 : * DaylightSavings so it converts from local to local standard time. */
942 0 : if ((f_gmt == 1) && (Clock_IsDaylightSaving2 (clock, 0) == 1)) {
943 0 : clock = clock + 3600;
944 : }
945 : }
946 : /* Convert from seconds to days and seconds. */
947 12 : totDay = (sInt4) floor (clock / SEC_DAY);
948 12 : Clock_Epoch2YearDay (totDay, &day, &year);
949 12 : month = Clock_MonthNum (day, year);
950 12 : floatSec = clock - ((double) totDay) * SEC_DAY;
951 12 : sec = (sInt4) floatSec;
952 12 : floatSec = floatSec - sec;
953 :
954 12 : f_perc = 0;
955 12 : j = 0;
956 132 : for (i = 0; i < strlen (format); i++) {
957 120 : if (j >= n)
958 0 : return;
959 120 : if (format[i] == '%') {
960 60 : f_perc = 1;
961 : } else {
962 60 : if (f_perc == 0) {
963 0 : buffer[j] = format[i];
964 0 : j++;
965 0 : buffer[j] = '\0';
966 : } else {
967 60 : Clock_FormatParse (locBuff, sec, floatSec, totDay, year, month,
968 60 : day, format[i]);
969 60 : buffer[j] = '\0';
970 60 : strncat (buffer, locBuff, n - j);
971 60 : j += strlen (locBuff);
972 60 : f_perc = 0;
973 : }
974 : }
975 : }
976 : }
977 :
978 : /*****************************************************************************
979 : * Clock_Print2() --
980 : *
981 : * Arthur Taylor / MDL
982 : *
983 : * PURPOSE
984 : * To create formated output from a time structure that is stored as a
985 : * double. This is similar to Clock_Print, except it bases the timezone
986 : * shift on what the user supplies rather than the system timezone, and
987 : * accepts a flag that indicates whether to inquire about daylight savings.
988 : * If f_dayCheck, then it looks at the local time and see's if daylight is
989 : * in effect. This allows for points where daylight is never in effect
990 : * (f_dayCheck = 0).
991 : *
992 : * ARGUMENTS
993 : * buffer = Destination to write the format to. (Output)
994 : * n = The number of characters in buffer. (Input)
995 : * clock = The time stored as a double (asumed in UTC). (Input)
996 : * format = The desired output format. (Input)
997 : * timeZone = Hours to add to local time to get UTC. (Input)
998 : * f_dayCheck = True if we should check if daylight savings is in effect,
999 : * after converting to LST. (Input)
1000 : *
1001 : * RETURNS: void
1002 : *
1003 : * HISTORY
1004 : * 1/2006 Arthur Taylor (MDL/RSIS): Created.
1005 : *
1006 : * NOTES
1007 : *****************************************************************************
1008 : */
1009 0 : void Clock_Print2 (char *buffer, int n, double clock, char *format,
1010 : sChar timeZone, sChar f_dayCheck)
1011 : {
1012 : sInt4 totDay, year;
1013 : sInt4 sec;
1014 : double floatSec;
1015 : int month, day;
1016 : size_t i;
1017 : int j;
1018 : char f_perc;
1019 : char locBuff[100];
1020 :
1021 : /* clock is currently in UTC */
1022 0 : clock -= timeZone * 3600;
1023 : /* clock is now in local standard time */
1024 0 : if (f_dayCheck) {
1025 : /* Note: A 0 is passed to DaylightSavings so it converts from local to
1026 : * local standard time. */
1027 0 : if (Clock_IsDaylightSaving2 (clock, 0) == 1) {
1028 0 : clock += 3600;
1029 : }
1030 : }
1031 :
1032 : /* Convert from seconds to days and seconds. */
1033 0 : totDay = (sInt4) floor (clock / SEC_DAY);
1034 0 : Clock_Epoch2YearDay (totDay, &day, &year);
1035 0 : month = Clock_MonthNum (day, year);
1036 0 : floatSec = clock - ((double) totDay) * SEC_DAY;
1037 0 : sec = (sInt4) floatSec;
1038 0 : floatSec = floatSec - sec;
1039 :
1040 0 : f_perc = 0;
1041 0 : j = 0;
1042 0 : for (i = 0; i < strlen (format); i++) {
1043 0 : if (j >= n)
1044 0 : return;
1045 0 : if (format[i] == '%') {
1046 0 : f_perc = 1;
1047 : } else {
1048 0 : if (f_perc == 0) {
1049 0 : buffer[j] = format[i];
1050 0 : j++;
1051 0 : buffer[j] = '\0';
1052 : } else {
1053 0 : Clock_FormatParse (locBuff, sec, floatSec, totDay, year, month,
1054 0 : day, format[i]);
1055 0 : buffer[j] = '\0';
1056 0 : strncat (buffer, locBuff, n - j);
1057 0 : j += strlen (locBuff);
1058 0 : f_perc = 0;
1059 : }
1060 : }
1061 : }
1062 : }
1063 :
1064 : /*****************************************************************************
1065 : * Clock_Clicks() --
1066 : *
1067 : * Arthur Taylor / MDL
1068 : *
1069 : * PURPOSE
1070 : * Returns the number of clicks since the program started execution.
1071 : *
1072 : * ARGUMENTS
1073 : *
1074 : * RETURNS: double
1075 : * Number of clicks since the beginning of the program.
1076 : *
1077 : * HISTORY
1078 : * 6/2004 Arthur Taylor (MDL): Created.
1079 : *
1080 : * NOTES
1081 : *****************************************************************************
1082 : */
1083 0 : double Clock_Clicks (void)
1084 : {
1085 : double ans;
1086 :
1087 0 : ans = (double) clock ();
1088 0 : return ans;
1089 : }
1090 :
1091 : /*****************************************************************************
1092 : * Clock_Seconds() --
1093 : *
1094 : * Arthur Taylor / MDL
1095 : *
1096 : * PURPOSE
1097 : * Returns the current number of seconds since the beginning of the epoch.
1098 : * Using the local system time zone.
1099 : *
1100 : * ARGUMENTS
1101 : *
1102 : * RETURNS: double
1103 : * Number of seconds since beginning of the epoch.
1104 : *
1105 : * HISTORY
1106 : * 6/2004 Arthur Taylor (MDL): Created.
1107 : *
1108 : * NOTES
1109 : *****************************************************************************
1110 : */
1111 0 : int Clock_SetSeconds (double *time, sChar f_set)
1112 : {
1113 : static double ans = 0;
1114 : static int f_ansSet = 0;
1115 :
1116 0 : if (f_set) {
1117 0 : ans = *time;
1118 0 : f_ansSet = 1;
1119 0 : } else if (f_ansSet) {
1120 0 : *time = ans;
1121 : }
1122 0 : return f_ansSet;
1123 : }
1124 :
1125 0 : double Clock_Seconds (void)
1126 : {
1127 : double ans;
1128 :
1129 0 : if (Clock_SetSeconds (&ans, 0) == 0) {
1130 0 : ans = time (NULL);
1131 : }
1132 0 : return ans;
1133 : }
1134 :
1135 : /*****************************************************************************
1136 : * Clock_PrintZone() --
1137 : *
1138 : * Arthur Taylor / MDL
1139 : *
1140 : * PURPOSE
1141 : * Prints the time zone based on the shift from UTC and if it is daylight
1142 : * savings or not.
1143 : *
1144 : * ARGUMENTS
1145 : * ptr = The character string to scan. (Output)
1146 : * TimeZone = Hours to add to local time to get UTC. (Input)
1147 : * f_day = True if we are dealing with daylight savings. (Input)
1148 : *
1149 : * RETURNS: int
1150 : * 0 if we read TimeZone, -1 if not.
1151 : *
1152 : * HISTORY
1153 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
1154 : * 6/2004 AAT (MDL): Updated.
1155 : *
1156 : * NOTES
1157 : *****************************************************************************
1158 : */
1159 0 : int Clock_PrintZone2 (char *ptr, sChar TimeZone, char f_day)
1160 : {
1161 0 : if (TimeZone == 0) {
1162 0 : sprintf (ptr, "UTC");
1163 0 : return 0;
1164 0 : } else if (TimeZone == 5) {
1165 0 : if (f_day) {
1166 0 : sprintf (ptr, "EDT");
1167 : } else {
1168 0 : sprintf (ptr, "EST");
1169 : }
1170 0 : return 0;
1171 0 : } else if (TimeZone == 6) {
1172 0 : if (f_day) {
1173 0 : sprintf (ptr, "CDT");
1174 : } else {
1175 0 : sprintf (ptr, "CST");
1176 : }
1177 0 : return 0;
1178 0 : } else if (TimeZone == 7) {
1179 0 : if (f_day) {
1180 0 : sprintf (ptr, "MDT");
1181 : } else {
1182 0 : sprintf (ptr, "MST");
1183 : }
1184 0 : return 0;
1185 0 : } else if (TimeZone == 8) {
1186 0 : if (f_day) {
1187 0 : sprintf (ptr, "PDT");
1188 : } else {
1189 0 : sprintf (ptr, "PST");
1190 : }
1191 0 : return 0;
1192 0 : } else if (TimeZone == 9) {
1193 0 : if (f_day) {
1194 0 : sprintf (ptr, "YDT");
1195 : } else {
1196 0 : sprintf (ptr, "YST");
1197 : }
1198 0 : return 0;
1199 : }
1200 0 : ptr[0] = '\0';
1201 0 : return -1;
1202 : }
1203 :
1204 : /*****************************************************************************
1205 : * Clock_ScanZone() --
1206 : *
1207 : * Arthur Taylor / MDL
1208 : *
1209 : * PURPOSE
1210 : * Scans a character string to determine the timezone.
1211 : *
1212 : * ARGUMENTS
1213 : * ptr = The character string to scan. (Input)
1214 : * TimeZone = Hours to add to local time to get UTC. (Output)
1215 : * f_day = True if we are dealing with daylight savings. (Output)
1216 : *
1217 : * RETURNS: int
1218 : * 0 if we read TimeZone, -1 if not.
1219 : *
1220 : * HISTORY
1221 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
1222 : * 6/2004 AAT (MDL): Updated.
1223 : *
1224 : * NOTES
1225 : *****************************************************************************
1226 : */
1227 0 : int Clock_ScanZone2 (char *ptr, sChar *TimeZone, char *f_day)
1228 : {
1229 0 : switch (ptr[0]) {
1230 : case 'G':
1231 0 : if (strcmp (ptr, "GMT") == 0) {
1232 0 : *f_day = 0;
1233 0 : *TimeZone = 0;
1234 0 : return 0;
1235 : }
1236 0 : return -1;
1237 : case 'U':
1238 0 : if (strcmp (ptr, "UTC") == 0) {
1239 0 : *f_day = 0;
1240 0 : *TimeZone = 0;
1241 0 : return 0;
1242 : }
1243 0 : return -1;
1244 : case 'E':
1245 0 : if (strcmp (ptr, "EDT") == 0) {
1246 0 : *f_day = 1;
1247 0 : *TimeZone = 5;
1248 0 : return 0;
1249 0 : } else if (strcmp (ptr, "EST") == 0) {
1250 0 : *f_day = 0;
1251 0 : *TimeZone = 5;
1252 0 : return 0;
1253 : }
1254 0 : return -1;
1255 : case 'C':
1256 0 : if (strcmp (ptr, "CDT") == 0) {
1257 0 : *f_day = 1;
1258 0 : *TimeZone = 6;
1259 0 : return 0;
1260 0 : } else if (strcmp (ptr, "CST") == 0) {
1261 0 : *f_day = 0;
1262 0 : *TimeZone = 6;
1263 0 : return 0;
1264 : }
1265 0 : return -1;
1266 : case 'M':
1267 0 : if (strcmp (ptr, "MDT") == 0) {
1268 0 : *f_day = 1;
1269 0 : *TimeZone = 7;
1270 0 : return 0;
1271 0 : } else if (strcmp (ptr, "MST") == 0) {
1272 0 : *f_day = 0;
1273 0 : *TimeZone = 7;
1274 0 : return 0;
1275 : }
1276 0 : return -1;
1277 : case 'P':
1278 0 : if (strcmp (ptr, "PDT") == 0) {
1279 0 : *f_day = 1;
1280 0 : *TimeZone = 8;
1281 0 : return 0;
1282 0 : } else if (strcmp (ptr, "PST") == 0) {
1283 0 : *f_day = 0;
1284 0 : *TimeZone = 8;
1285 0 : return 0;
1286 : }
1287 0 : return -1;
1288 : case 'Y':
1289 0 : if (strcmp (ptr, "YDT") == 0) {
1290 0 : *f_day = 1;
1291 0 : *TimeZone = 9;
1292 0 : return 0;
1293 0 : } else if (strcmp (ptr, "YST") == 0) {
1294 0 : *f_day = 0;
1295 0 : *TimeZone = 9;
1296 0 : return 0;
1297 : }
1298 0 : return -1;
1299 : case 'Z':
1300 0 : if (strcmp (ptr, "Z") == 0) {
1301 0 : *f_day = 0;
1302 0 : *TimeZone = 0;
1303 0 : return 0;
1304 : }
1305 0 : return -1;
1306 : }
1307 0 : return -1;
1308 : }
1309 :
1310 : /*****************************************************************************
1311 : * Clock_ScanMonth() --
1312 : *
1313 : * Arthur Taylor / MDL
1314 : *
1315 : * PURPOSE
1316 : * Scans a string looking for a month word. Assumes string is all caps.
1317 : *
1318 : * ARGUMENTS
1319 : * ptr = The character string to scan. (Input)
1320 : *
1321 : * RETURNS: int
1322 : * Returns the month number read, or -1 if no month word seen.
1323 : *
1324 : * HISTORY
1325 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
1326 : * 6/2004 AAT (MDL): Updated.
1327 : *
1328 : * NOTES
1329 : *****************************************************************************
1330 : */
1331 0 : int Clock_ScanMonth (char *ptr)
1332 : {
1333 0 : switch (*ptr) {
1334 : case 'A':
1335 0 : if ((strcmp (ptr, "APR") == 0) || (strcmp (ptr, "APRIL") == 0))
1336 0 : return 4;
1337 0 : else if ((strcmp (ptr, "AUG") == 0) || (strcmp (ptr, "AUGUST") == 0))
1338 0 : return 8;
1339 0 : return -1;
1340 : case 'D':
1341 0 : if ((strcmp (ptr, "DEC") == 0) || (strcmp (ptr, "DECEMBER") == 0))
1342 0 : return 12;
1343 0 : return -1;
1344 : case 'F':
1345 0 : if ((strcmp (ptr, "FEB") == 0) || (strcmp (ptr, "FEBRUARY") == 0))
1346 0 : return 2;
1347 0 : return -1;
1348 : case 'J':
1349 0 : if ((strcmp (ptr, "JAN") == 0) || (strcmp (ptr, "JANUARY") == 0))
1350 0 : return 1;
1351 0 : else if ((strcmp (ptr, "JUN") == 0) || (strcmp (ptr, "JUNE") == 0))
1352 0 : return 6;
1353 0 : else if ((strcmp (ptr, "JUL") == 0) || (strcmp (ptr, "JULY") == 0))
1354 0 : return 7;
1355 0 : return -1;
1356 : case 'M':
1357 0 : if ((strcmp (ptr, "MAR") == 0) || (strcmp (ptr, "MARCH") == 0))
1358 0 : return 3;
1359 0 : else if (strcmp (ptr, "MAY") == 0)
1360 0 : return 5;
1361 0 : return -1;
1362 : case 'N':
1363 0 : if ((strcmp (ptr, "NOV") == 0) || (strcmp (ptr, "NOVEMBER") == 0))
1364 0 : return 11;
1365 0 : return -1;
1366 : case 'O':
1367 0 : if ((strcmp (ptr, "OCT") == 0) || (strcmp (ptr, "OCTOBER") == 0))
1368 0 : return 10;
1369 0 : return -1;
1370 : case 'S':
1371 0 : if ((strcmp (ptr, "SEP") == 0) || (strcmp (ptr, "SEPTEMBER") == 0))
1372 0 : return 9;
1373 0 : return -1;
1374 : }
1375 0 : return -1;
1376 : }
1377 :
1378 : /*****************************************************************************
1379 : * Clock_PrintMonth3() --
1380 : *
1381 : * Arthur Taylor / MDL
1382 : *
1383 : * PURPOSE
1384 : *
1385 : * ARGUMENTS
1386 : *
1387 : * RETURNS: void
1388 : *
1389 : * HISTORY
1390 : * 3/2005 Arthur Taylor (MDL/RSIS): Commented.
1391 : *
1392 : * NOTES
1393 : *****************************************************************************
1394 : */
1395 0 : void Clock_PrintMonth3 (int mon, char *buffer, int buffLen)
1396 : {
1397 : static char *MonthName[] = {
1398 : "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT",
1399 : "NOV", "DEC"
1400 : };
1401 : myAssert ((mon > 0) && (mon < 13));
1402 : myAssert (buffLen > 3);
1403 0 : strcpy (buffer, MonthName[mon - 1]);
1404 0 : }
1405 :
1406 : /*****************************************************************************
1407 : * Clock_PrintMonth() --
1408 : *
1409 : * Arthur Taylor / MDL
1410 : *
1411 : * PURPOSE
1412 : *
1413 : * ARGUMENTS
1414 : *
1415 : * RETURNS: void
1416 : *
1417 : * HISTORY
1418 : * 3/2005 Arthur Taylor (MDL/RSIS): Commented.
1419 : *
1420 : * NOTES
1421 : *****************************************************************************
1422 : */
1423 0 : void Clock_PrintMonth (int mon, char *buffer, int buffLen)
1424 : {
1425 : static char *MonthName[] = {
1426 : "January", "February", "March", "April", "May", "June", "July",
1427 : "August", "September", "October", "November", "December"
1428 : };
1429 : myAssert ((mon > 0) && (mon < 13));
1430 : myAssert (buffLen > 9);
1431 0 : strcpy (buffer, MonthName[mon - 1]);
1432 0 : }
1433 :
1434 : /*****************************************************************************
1435 : * Clock_ScanWeekday() --
1436 : *
1437 : * Arthur Taylor / MDL
1438 : *
1439 : * PURPOSE
1440 : * Scans a string looking for a day word. Assumes string is all caps.
1441 : *
1442 : * ARGUMENTS
1443 : * ptr = The character string to scan. (Input)
1444 : *
1445 : * RETURNS: int
1446 : * Returns the day number read, or -1 if no day word seen.
1447 : *
1448 : * HISTORY
1449 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
1450 : * 6/2004 AAT (MDL): Updated.
1451 : *
1452 : * NOTES
1453 : *****************************************************************************
1454 : */
1455 0 : static int Clock_ScanWeekday (char *ptr)
1456 : {
1457 0 : switch (*ptr) {
1458 : case 'S':
1459 0 : if ((strcmp (ptr, "SUN") == 0) || (strcmp (ptr, "SUNDAY") == 0))
1460 0 : return 0;
1461 0 : else if ((strcmp (ptr, "SAT") == 0) ||
1462 0 : (strcmp (ptr, "SATURDAY") == 0))
1463 0 : return 6;
1464 0 : return -1;
1465 : case 'M':
1466 0 : if ((strcmp (ptr, "MON") == 0) || (strcmp (ptr, "MONDAY") == 0))
1467 0 : return 1;
1468 0 : return -1;
1469 : case 'T':
1470 0 : if ((strcmp (ptr, "TUE") == 0) || (strcmp (ptr, "TUESDAY") == 0))
1471 0 : return 2;
1472 0 : else if ((strcmp (ptr, "THU") == 0) ||
1473 0 : (strcmp (ptr, "THURSDAY") == 0))
1474 0 : return 4;
1475 0 : return -1;
1476 : case 'W':
1477 0 : if ((strcmp (ptr, "WED") == 0) || (strcmp (ptr, "WEDNESDAY") == 0))
1478 0 : return 3;
1479 0 : return -1;
1480 : case 'F':
1481 0 : if ((strcmp (ptr, "FRI") == 0) || (strcmp (ptr, "FRIDAY") == 0))
1482 0 : return 5;
1483 0 : return -1;
1484 : }
1485 0 : return -1;
1486 : }
1487 :
1488 : /*****************************************************************************
1489 : * Clock_ScanColon() --
1490 : *
1491 : * Arthur Taylor / MDL
1492 : *
1493 : * PURPOSE
1494 : * Parses a word assuming it is : separated and is dealing with
1495 : * hours:minutes:seconds or hours:minutes. Returns the resulting time as
1496 : * a double.
1497 : *
1498 : * ARGUMENTS
1499 : * ptr = The character string to scan. (Input)
1500 : *
1501 : * RETURNS: double
1502 : * The time after converting the : separated string.
1503 : *
1504 : * HISTORY
1505 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
1506 : * 6/2004 AAT (MDL): Updated.
1507 : *
1508 : * NOTES
1509 : *****************************************************************************
1510 : */
1511 0 : static double Clock_ScanColon (char *ptr)
1512 : {
1513 : sInt4 hour, min;
1514 : double sec;
1515 : char *ptr3;
1516 :
1517 0 : ptr3 = strchr (ptr, ':');
1518 0 : *ptr3 = '\0';
1519 0 : hour = atoi (ptr);
1520 0 : *ptr3 = ':';
1521 0 : ptr = ptr3 + 1;
1522 : /* Check for second :, other wise it is hh:mm */
1523 0 : if ((ptr3 = strchr (ptr, ':')) == NULL) {
1524 0 : min = atoi (ptr);
1525 0 : sec = 0;
1526 : } else {
1527 0 : *ptr3 = '\0';
1528 0 : min = atoi (ptr);
1529 0 : *ptr3 = ':';
1530 0 : ptr = ptr3 + 1;
1531 0 : sec = atof (ptr);
1532 : }
1533 0 : return (sec + 60 * min + 3600 * hour);
1534 : }
1535 :
1536 : /*****************************************************************************
1537 : * Clock_ScanSlash() --
1538 : *
1539 : * Arthur Taylor / MDL
1540 : *
1541 : * PURPOSE
1542 : * Parses a word assuming it is / separated and is dealing with
1543 : * months/days/years or months/days.
1544 : *
1545 : * ARGUMENTS
1546 : * word = The character string to scan. (Input)
1547 : * mon = The month that was seen. (Output)
1548 : * day = The day that was seen. (Output)
1549 : * year = The year that was seen. (Output)
1550 : * f_year = True if the year is valid. (Output)
1551 : *
1552 : * RETURNS: int
1553 : * -1 if mon or day is out of range.
1554 : * 0 if no problems.
1555 : *
1556 : * HISTORY
1557 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
1558 : * 6/2004 AAT (MDL): Updated.
1559 : *
1560 : * NOTES
1561 : *****************************************************************************
1562 : */
1563 0 : static int Clock_ScanSlash (char *word, int *mon, int *day, sInt4 *year,
1564 : char *f_year)
1565 : {
1566 : char *ptr3;
1567 0 : char *ptr = word;
1568 :
1569 0 : ptr3 = strchr (ptr, '/');
1570 0 : *ptr3 = '\0';
1571 0 : *mon = atoi (ptr);
1572 0 : *ptr3 = '/';
1573 0 : ptr = ptr3 + 1;
1574 : /* Check for second /, other wise it is mm/dd */
1575 0 : if ((ptr3 = strchr (ptr, '/')) == NULL) {
1576 0 : *day = atoi (ptr);
1577 0 : *year = 1970;
1578 0 : *f_year = 0;
1579 : } else {
1580 0 : *ptr3 = '\0';
1581 0 : *day = atoi (ptr);
1582 0 : *ptr3 = '/';
1583 0 : ptr = ptr3 + 1;
1584 0 : *year = atoi (ptr);
1585 0 : *f_year = 1;
1586 : }
1587 0 : if ((*mon < 1) || (*mon > 12) || (*day < 1) || (*day > 31)) {
1588 0 : printf ("Errors parsing %s\n", word);
1589 0 : return -1;
1590 : }
1591 0 : return 0;
1592 : }
1593 :
1594 : /* http://www.w3.org/TR/NOTE-datetime
1595 : Year and month:
1596 : YYYY-MM (eg 1997-07)
1597 : Complete date:
1598 : YYYY-MM-DD (eg 1997-07-16)
1599 : Complete date plus hours and minutes:
1600 : YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
1601 : Complete date plus hours, minutes and seconds:
1602 : YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
1603 : Complete date plus hours, minutes, seconds and a decimal fraction of a
1604 : second
1605 : YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
1606 :
1607 : Example:
1608 : 1994-11-05T08:15:30-05:00 corresponds to November 5, 1994, 8:15:30 am,
1609 : US Eastern Standard Time.
1610 : 1994-11-05T13:15:30Z corresponds to the same instant.
1611 : */
1612 0 : static int Clock_ScanDash (char *word, int *mon, int *day, sInt4 *year,
1613 : double *time, char *f_time)
1614 : {
1615 : char *ptr3;
1616 0 : char *ptr = word;
1617 : sInt4 hour, min;
1618 : double sec;
1619 : char temp;
1620 : sInt4 offset;
1621 :
1622 0 : ptr3 = strchr (ptr, '-');
1623 0 : *ptr3 = '\0';
1624 0 : *year = atoi (ptr);
1625 0 : *ptr3 = '-';
1626 0 : ptr = ptr3 + 1;
1627 : /* Check for second -, other wise it is yyyy-mm */
1628 0 : if ((ptr3 = strchr (ptr, '-')) == NULL) {
1629 : /* Don't touch time or f_time */
1630 0 : *mon = atoi (ptr);
1631 0 : *day = 1;
1632 0 : if ((*mon < 1) || (*mon > 12)) {
1633 0 : printf ("Errors parsing %s\n", word);
1634 0 : return -1;
1635 : }
1636 0 : return 0;
1637 : }
1638 0 : *ptr3 = '\0';
1639 0 : *mon = atoi (ptr);
1640 0 : *ptr3 = '-';
1641 0 : ptr = ptr3 + 1;
1642 0 : if ((ptr3 = strchr (ptr, 'T')) == NULL) {
1643 : /* Don't touch time or f_time */
1644 0 : *day = atoi (ptr);
1645 0 : if ((*mon < 1) || (*mon > 12) || (*day < 1) || (*day > 31)) {
1646 0 : printf ("Errors parsing %s\n", word);
1647 0 : return -1;
1648 : }
1649 0 : return 0;
1650 : }
1651 0 : *ptr3 = '\0';
1652 0 : *day = atoi (ptr);
1653 0 : *ptr3 = 'T';
1654 0 : ptr = ptr3 + 1;
1655 : /* hh:mmTZD */
1656 : /* hh:mm:ssTZD */
1657 : /* hh:mm:ss.sTZD */
1658 0 : if (strlen (ptr) < 5) {
1659 0 : printf ("Errors parsing %s\n", word);
1660 0 : return -1;
1661 : }
1662 0 : ptr[2] = '\0';
1663 0 : hour = atoi (ptr);
1664 0 : ptr[2] = ':';
1665 0 : ptr += 3;
1666 0 : offset = 0;
1667 0 : sec = 0;
1668 0 : if (strlen (ptr) == 2) {
1669 0 : min = atoi (ptr);
1670 : } else {
1671 0 : temp = ptr[2];
1672 0 : ptr[2] = '\0';
1673 0 : min = atoi (ptr);
1674 0 : ptr[2] = temp;
1675 0 : if (temp == ':') {
1676 0 : ptr += 3;
1677 0 : if ((ptr3 = strchr (ptr, '+')) == NULL) {
1678 0 : if ((ptr3 = strchr (ptr, '-')) == NULL) {
1679 0 : ptr3 = strchr (ptr, 'Z');
1680 : }
1681 : }
1682 0 : if (ptr3 == NULL) {
1683 0 : sec = atof (ptr);
1684 : } else {
1685 0 : temp = *ptr3;
1686 0 : *ptr3 = '\0';
1687 0 : sec = atof (ptr);
1688 0 : *ptr3 = temp;
1689 0 : if (temp != 'Z') {
1690 0 : ptr = ptr3;
1691 0 : ptr[3] = '\0';
1692 0 : offset = atoi (ptr) * 3600;
1693 0 : ptr[3] = ':';
1694 0 : ptr += 4;
1695 0 : offset += atoi (ptr) * 60;
1696 : }
1697 : }
1698 0 : } else if (temp != 'Z') {
1699 0 : ptr += 2;
1700 0 : ptr[3] = '\0';
1701 0 : offset = atoi (ptr) * 3600;
1702 0 : ptr[3] = ':';
1703 0 : ptr += 4;
1704 0 : offset += atoi (ptr) * 60;
1705 : }
1706 : }
1707 0 : *f_time = 1;
1708 0 : *time = sec + min * 60 + hour * 3600 - offset;
1709 0 : return 0;
1710 : }
1711 :
1712 : /*****************************************************************************
1713 : * Clock_ScanDate() --
1714 : *
1715 : * Arthur Taylor / MDL
1716 : *
1717 : * PURPOSE
1718 : *
1719 : * ARGUMENTS
1720 : *
1721 : * RETURNS: void
1722 : *
1723 : * HISTORY
1724 : * 3/2005 Arthur Taylor (MDL/RSIS): Commented.
1725 : *
1726 : * NOTES
1727 : *****************************************************************************
1728 : */
1729 : /* prj::slosh prj::stm2trk and prj::degrib use this with clock zero'ed
1730 : out, so I have now made sure clock is zero'ed. */
1731 28 : void Clock_ScanDate (double *clock, sInt4 year, int mon, int day)
1732 : {
1733 : int i;
1734 : sInt4 delt, temp, totDay;
1735 :
1736 : myAssert ((mon >= 1) && (mon <= 12));
1737 :
1738 : /* Makes sure clock is zero'ed out. */
1739 28 : *clock = 0;
1740 :
1741 28 : if ((mon < 1) || (mon > 12) || (day < 0) || (day > 31))
1742 0 : return;
1743 28 : totDay = Clock_NumDay (mon, day, year, 0);
1744 28 : if (day > totDay)
1745 0 : return;
1746 28 : totDay = Clock_NumDay (mon, day, year, 1);
1747 28 : temp = 1970;
1748 28 : delt = year - temp;
1749 28 : if ((delt >= 400) || (delt <= -400)) {
1750 0 : i = (delt / 400);
1751 0 : temp += 400 * i;
1752 0 : totDay += 146097L * i;
1753 : }
1754 28 : if (temp < year) {
1755 386 : while (temp < year) {
1756 850 : if (((temp % 4) == 0) &&
1757 274 : (((temp % 100) != 0) || ((temp % 400) == 0))) {
1758 246 : if ((temp + 4) < year) {
1759 218 : totDay += 1461;
1760 218 : temp += 4;
1761 28 : } else if ((temp + 3) < year) {
1762 14 : totDay += 1096;
1763 14 : temp += 3;
1764 14 : } else if ((temp + 2) < year) {
1765 14 : totDay += 731;
1766 14 : temp += 2;
1767 : } else {
1768 0 : totDay += 366;
1769 0 : temp++;
1770 : }
1771 : } else {
1772 84 : totDay += 365;
1773 84 : temp++;
1774 : }
1775 : }
1776 0 : } else if (temp > year) {
1777 0 : while (temp > year) {
1778 0 : temp--;
1779 0 : if (((temp % 4) == 0) &&
1780 0 : (((temp % 100) != 0) || ((temp % 400) == 0))) {
1781 0 : if (year < temp - 3) {
1782 0 : totDay -= 1461;
1783 0 : temp -= 3;
1784 0 : } else if (year < (temp - 2)) {
1785 0 : totDay -= 1096;
1786 0 : temp -= 2;
1787 0 : } else if (year < (temp - 1)) {
1788 0 : totDay -= 731;
1789 0 : temp--;
1790 : } else {
1791 0 : totDay -= 366;
1792 : }
1793 : } else {
1794 0 : totDay -= 365;
1795 : }
1796 : }
1797 : }
1798 28 : *clock = *clock + ((double) (totDay)) * 24 * 3600;
1799 : }
1800 :
1801 0 : int Clock_ScanDateNumber (double *clock, char *buffer)
1802 : {
1803 0 : int buffLen = strlen (buffer);
1804 : sInt4 year;
1805 0 : int mon = 1;
1806 0 : int day = 1;
1807 0 : int hour = 0;
1808 0 : int min = 0;
1809 0 : int sec = 0;
1810 : char c_temp;
1811 :
1812 0 : *clock = 0;
1813 0 : if ((buffLen != 4) && (buffLen != 6) && (buffLen != 8) &&
1814 : (buffLen != 10) && (buffLen != 12) && (buffLen != 14)) {
1815 0 : return 1;
1816 : }
1817 0 : c_temp = buffer[4];
1818 0 : buffer[4] = '\0';
1819 0 : year = atoi (buffer);
1820 0 : buffer[4] = c_temp;
1821 0 : if (buffLen > 4) {
1822 0 : c_temp = buffer[6];
1823 0 : buffer[6] = '\0';
1824 0 : mon = atoi (buffer + 4);
1825 0 : buffer[6] = c_temp;
1826 : }
1827 0 : if (buffLen > 6) {
1828 0 : c_temp = buffer[8];
1829 0 : buffer[8] = '\0';
1830 0 : day = atoi (buffer + 6);
1831 0 : buffer[8] = c_temp;
1832 : }
1833 0 : if (buffLen > 8) {
1834 0 : c_temp = buffer[10];
1835 0 : buffer[10] = '\0';
1836 0 : hour = atoi (buffer + 8);
1837 0 : buffer[10] = c_temp;
1838 : }
1839 0 : if (buffLen > 10) {
1840 0 : c_temp = buffer[12];
1841 0 : buffer[12] = '\0';
1842 0 : min = atoi (buffer + 10);
1843 0 : buffer[12] = c_temp;
1844 : }
1845 0 : if (buffLen > 12) {
1846 0 : c_temp = buffer[14];
1847 0 : buffer[14] = '\0';
1848 0 : sec = atoi (buffer + 12);
1849 0 : buffer[14] = c_temp;
1850 : }
1851 0 : Clock_ScanDate (clock, year, mon, day);
1852 0 : *clock = *clock + sec + min * 60 + hour * 3600;
1853 0 : return 0;
1854 : }
1855 :
1856 0 : void Clock_PrintDateNumber (double clock, char buffer[15])
1857 : {
1858 : sInt4 year;
1859 : int month, day, hour, min, sec;
1860 : double d_sec;
1861 :
1862 0 : Clock_PrintDate (clock, &year, &month, &day, &hour, &min, &d_sec);
1863 0 : sec = (int) d_sec;
1864 0 : sprintf (buffer, "%04d%02d%02d%02d%02d%02d", year, month, day, hour, min,
1865 : sec);
1866 0 : }
1867 :
1868 : /* Word_types: none, ':' word, '/' word, '-' word, integer word, 'AM'/'PM'
1869 : * word, timeZone word, month word, weekDay word, Preceeder to a relativeDate
1870 : * word, Postceeder to a relativeDate word, relativeDate word unit, Adjust Day
1871 : * word
1872 : */
1873 : enum {
1874 : WT_NONE, WT_COLON, WT_SLASH, WT_DASH, WT_INTEGER, WT_AMPM, WT_TIMEZONE,
1875 : WT_MONTH, WT_DAY, WT_PRE_RELATIVE, WT_POST_RELATIVE, WT_RELATIVE_UNIT,
1876 : WT_ADJDAY
1877 : };
1878 :
1879 : /*****************************************************************************
1880 : * Clock_GetWord() --
1881 : *
1882 : * Arthur Taylor / MDL
1883 : *
1884 : * PURPOSE
1885 : *
1886 : * ARGUMENTS
1887 : *
1888 : * RETURNS: void
1889 : *
1890 : * HISTORY
1891 : * 3/2005 Arthur Taylor (MDL/RSIS): Commented.
1892 : *
1893 : * NOTES
1894 : *****************************************************************************
1895 : */
1896 : /* Start at *Start. Advance Start until it is at first non-space,
1897 : * non-',' non-'.' character. Move End to first space, ',' or '.' after
1898 : * new Start location. Copy upto 30 characters (in caps) into word. */
1899 : /* return -1 if no next word, 0 otherwise */
1900 0 : static int Clock_GetWord (char **Start, char **End, char word[30],
1901 : int *wordType)
1902 : {
1903 : char *ptr;
1904 : int cnt;
1905 : int f_integer;
1906 :
1907 0 : *wordType = WT_NONE;
1908 0 : if (*Start == NULL) {
1909 0 : return -1;
1910 : }
1911 0 : ptr = *Start;
1912 : /* Find start of next word (first non-space non-',' non-'.' char.) */
1913 0 : while ((*ptr == ' ') || (*ptr == ',') || (*ptr == '.')) {
1914 0 : ptr++;
1915 : }
1916 : /* There is no next word. */
1917 0 : if (*ptr == '\0') {
1918 0 : return -1;
1919 : }
1920 0 : *Start = ptr;
1921 : /* Find end of next word. */
1922 0 : cnt = 0;
1923 0 : f_integer = 1;
1924 0 : while ((*ptr != ' ') && (*ptr != ',') && (*ptr != '\0')) {
1925 0 : if (cnt < 29) {
1926 0 : word[cnt] = (char) toupper (*ptr);
1927 0 : cnt++;
1928 : }
1929 0 : if (*ptr == ':') {
1930 0 : if (*wordType == WT_NONE)
1931 0 : *wordType = WT_COLON;
1932 0 : f_integer = 0;
1933 0 : } else if (*ptr == '/') {
1934 0 : if (*wordType == WT_NONE)
1935 0 : *wordType = WT_SLASH;
1936 0 : f_integer = 0;
1937 0 : } else if (*ptr == '-') {
1938 0 : if (ptr != *Start) {
1939 0 : if (*wordType == WT_NONE)
1940 0 : *wordType = WT_DASH;
1941 0 : f_integer = 0;
1942 : }
1943 0 : } else if (*ptr == '.') {
1944 0 : if (!isdigit (*(ptr + 1))) {
1945 0 : break;
1946 : } else {
1947 0 : f_integer = 0;
1948 : }
1949 0 : } else if (!isdigit (*ptr)) {
1950 0 : f_integer = 0;
1951 : }
1952 0 : ptr++;
1953 : }
1954 0 : word[cnt] = '\0';
1955 0 : *End = ptr;
1956 0 : if (f_integer) {
1957 0 : *wordType = WT_INTEGER;
1958 : }
1959 0 : return 0;
1960 : }
1961 :
1962 : typedef struct {
1963 : sInt4 val;
1964 : int len; /* read from len char string? */
1965 : } stackType;
1966 :
1967 : typedef struct {
1968 : int relUnit;
1969 : int f_negate;
1970 : int amount;
1971 : } relType;
1972 :
1973 : /*****************************************************************************
1974 : * Clock_Scan() --
1975 : *
1976 : * Arthur Taylor / MDL
1977 : *
1978 : * PURPOSE
1979 : *
1980 : * ARGUMENTS
1981 : *
1982 : * RETURNS: void
1983 : *
1984 : * HISTORY
1985 : *
1986 : * NOTES
1987 : * * f_gmt == 0 no adjust, 1 adjust as LDT, 2 adjust as LST *
1988 : * Adjusted from:
1989 : * if ((f_gmt == 2) && (Clock_IsDaylightSaving2 (*clock, 0) == 1)) {
1990 : * to:
1991 : * if ((f_gmt == 1) && (Clock_IsDaylightSaving2 (*clock, 0) == 1)) {
1992 :
1993 : *****************************************************************************
1994 : */
1995 0 : int Clock_Scan (double *clock, char *buffer, char f_gmt)
1996 : {
1997 : char *ptr, *ptr2;
1998 : char *ptr3;
1999 : char word[30];
2000 : int wordType;
2001 : int lastWordType;
2002 0 : sChar TimeZone = Clock_GetTimeZone ();
2003 : /* hours to add to local time to get UTC. */
2004 0 : char f_dayLight = 0;
2005 : int month;
2006 : int day;
2007 : sInt4 year;
2008 0 : char f_year = 0;
2009 : int index;
2010 : int ans;
2011 0 : stackType *Stack = NULL;
2012 0 : relType *Rel = NULL;
2013 0 : int lenRel = 0;
2014 0 : int lenStack = 0;
2015 : static char *PreRel[] = { "LAST", "THIS", "NEXT", NULL };
2016 : static char *RelUnit[] = {
2017 : "YEAR", "YEARS", "MONTH", "MONTHS", "FORTNIGHT", "FORTNIGHTS", "WEEK",
2018 : "WEEKS", "DAY", "DAYS", "HOUR", "HOURS", "MIN", "MINS", "MINUTE",
2019 : "MINUTES", "SEC", "SECS", "SECOND", "SECONDS", NULL
2020 : };
2021 : static char *AdjDay[] = { "YESTERDAY", "TODAY", "TOMORROW", NULL };
2022 0 : sChar f_ampm = -1;
2023 0 : char f_timeZone = 0;
2024 0 : char f_time = 0;
2025 0 : char f_date = 0;
2026 0 : char f_slashWord = 0;
2027 0 : char f_dateWord = 0;
2028 0 : char f_monthWord = 0;
2029 0 : char f_dayWord = 0;
2030 : double curTime;
2031 : sInt4 sec;
2032 : int i;
2033 : int monthAdj;
2034 : int yearAdj;
2035 :
2036 : /* Check that they gave us a string */
2037 0 : ptr = buffer;
2038 0 : if (*ptr == '\0')
2039 0 : return 0;
2040 :
2041 0 : f_time = 0;
2042 0 : f_date = 0;
2043 0 : lastWordType = WT_NONE;
2044 0 : curTime = 0;
2045 0 : while (Clock_GetWord (&ptr, &ptr2, word, &wordType) == 0) {
2046 0 : if (wordType == WT_COLON) {
2047 0 : if (f_time) {
2048 0 : printf ("Detected multiple time pieces\n");
2049 0 : goto errorReturn;
2050 : }
2051 0 : curTime = Clock_ScanColon (word);
2052 0 : f_time = 1;
2053 0 : } else if (wordType == WT_SLASH) {
2054 0 : if ((f_slashWord) || (f_dateWord)) {
2055 0 : printf ("Detected multiple date pieces\n");
2056 0 : goto errorReturn;
2057 : }
2058 0 : Clock_ScanSlash (word, &month, &day, &year, &f_year);
2059 0 : f_slashWord = 1;
2060 0 : } else if (wordType == WT_DASH) {
2061 0 : if ((f_slashWord) || (f_dateWord)) {
2062 0 : printf ("Detected multiple date pieces\n");
2063 0 : goto errorReturn;
2064 : }
2065 0 : Clock_ScanDash (word, &month, &day, &year, &curTime, &f_time);
2066 0 : f_year = 1;
2067 0 : f_slashWord = 1;
2068 0 : TimeZone = 0;
2069 0 : } else if (wordType == WT_INTEGER) {
2070 0 : lenStack++;
2071 0 : Stack = (stackType *) realloc ((void *) Stack,
2072 : lenStack * sizeof (stackType));
2073 0 : Stack[lenStack - 1].val = atoi (word);
2074 0 : Stack[lenStack - 1].len = strlen (word);
2075 0 : } else if (strcmp (word, "AM") == 0) {
2076 0 : if (f_ampm != -1) {
2077 0 : printf ("Detected multiple am/pm\n");
2078 0 : goto errorReturn;
2079 : }
2080 0 : f_ampm = 1;
2081 0 : wordType = WT_AMPM;
2082 0 : } else if (strcmp (word, "PM") == 0) {
2083 0 : if (f_ampm != -1) {
2084 0 : printf ("Detected multiple am/pm\n");
2085 0 : goto errorReturn;
2086 : }
2087 0 : f_ampm = 2;
2088 0 : wordType = WT_AMPM;
2089 0 : } else if (Clock_ScanZone2 (word, &TimeZone, &f_dayLight) == 0) {
2090 0 : if (f_timeZone) {
2091 0 : printf ("Detected multiple time zones.\n");
2092 0 : goto errorReturn;
2093 : }
2094 0 : if (f_dayLight == 0) {
2095 0 : f_gmt = 2;
2096 : } else {
2097 0 : f_gmt = 1;
2098 : }
2099 0 : f_timeZone = 1;
2100 0 : wordType = WT_TIMEZONE;
2101 0 : } else if ((index = Clock_ScanMonth (word)) != -1) {
2102 0 : if ((f_slashWord) || (f_monthWord)) {
2103 0 : printf ("Detected multiple months or already defined month.\n");
2104 0 : goto errorReturn;
2105 : }
2106 0 : month = index;
2107 : /* Get the next word? First preserve the pointer */
2108 0 : ptr3 = ptr2;
2109 0 : ptr = ptr2;
2110 0 : ans = Clock_GetWord (&ptr, &ptr2, word, &wordType);
2111 0 : if ((ans != 0) || (wordType != WT_INTEGER)) {
2112 : /* Next word not integer, so previous word is integral day. */
2113 0 : if (lastWordType != WT_INTEGER) {
2114 0 : printf ("Problems with month word and finding the day.\n");
2115 0 : goto errorReturn;
2116 : }
2117 0 : lenStack--;
2118 0 : day = Stack[lenStack].val;
2119 : /* Put the next word back under consideration. */
2120 0 : wordType = WT_MONTH;
2121 0 : ptr2 = ptr3;
2122 : } else {
2123 : /* If word is trailed by comma, then it is day, and the next one
2124 : * is the year, otherwise it is a year, and the number before the
2125 : * month is the day. */
2126 0 : if (*ptr2 == ',') {
2127 0 : day = atoi (word);
2128 0 : ptr = ptr2;
2129 0 : ans = Clock_GetWord (&ptr, &ptr2, word, &wordType);
2130 0 : if ((ans != 0) || (wordType != WT_INTEGER)) {
2131 0 : printf ("Couldn't find the year after the day.\n");
2132 0 : goto errorReturn;
2133 : }
2134 0 : year = atoi (word);
2135 0 : f_year = 1;
2136 : } else {
2137 0 : year = atoi (word);
2138 0 : f_year = 1;
2139 0 : if (lastWordType != WT_INTEGER) {
2140 0 : printf ("Problems with month word and finding the day.\n");
2141 0 : goto errorReturn;
2142 : }
2143 0 : lenStack--;
2144 0 : day = Stack[lenStack].val;
2145 : }
2146 : }
2147 0 : f_monthWord = 1;
2148 0 : f_dateWord = 1;
2149 :
2150 : /* Ignore the day of the week info? */
2151 0 : } else if ((index = Clock_ScanWeekday (word)) != -1) {
2152 0 : if ((f_slashWord) || (f_dayWord)) {
2153 0 : printf ("Detected multiple day of week or already defined "
2154 : "day.\n");
2155 0 : goto errorReturn;
2156 : }
2157 0 : wordType = WT_DAY;
2158 0 : f_dayWord = 1;
2159 0 : f_dateWord = 1;
2160 0 : } else if (GetIndexFromStr (word, PreRel, &index) != -1) {
2161 0 : wordType = WT_PRE_RELATIVE;
2162 : /* Next word must be a unit word. */
2163 0 : ptr = ptr2;
2164 0 : if (Clock_GetWord (&ptr, &ptr2, word, &wordType) != 0) {
2165 0 : printf ("Couldn't get the next word after Pre-Relative time "
2166 : "word\n");
2167 0 : goto errorReturn;
2168 : }
2169 0 : if (GetIndexFromStr (word, RelUnit, &ans) == -1) {
2170 0 : printf ("Couldn't get the Relative unit\n");
2171 0 : goto errorReturn;
2172 : }
2173 0 : if (index != 1) {
2174 0 : lenRel++;
2175 0 : Rel = (relType *) realloc ((void *) Rel,
2176 : lenRel * sizeof (relType));
2177 0 : Rel[lenRel - 1].relUnit = ans;
2178 0 : Rel[lenRel - 1].amount = 1;
2179 0 : if (index == 0) {
2180 0 : Rel[lenRel - 1].f_negate = 1;
2181 : } else {
2182 0 : Rel[lenRel - 1].f_negate = 0;
2183 : }
2184 : }
2185 0 : printf ("Pre Relative Word: %s %d\n", word, index);
2186 :
2187 0 : } else if (strcmp (word, "AGO") == 0) {
2188 0 : if ((lastWordType != WT_PRE_RELATIVE) ||
2189 : (lastWordType != WT_RELATIVE_UNIT)) {
2190 0 : printf ("Ago did not follow relative words\n");
2191 0 : goto errorReturn;
2192 : }
2193 0 : Rel[lenRel - 1].f_negate = 1;
2194 0 : wordType = WT_POST_RELATIVE;
2195 0 : } else if (GetIndexFromStr (word, RelUnit, &index) != -1) {
2196 0 : lenRel++;
2197 0 : Rel = (relType *) realloc ((void *) Rel, lenRel * sizeof (relType));
2198 0 : Rel[lenRel - 1].relUnit = index;
2199 0 : Rel[lenRel - 1].amount = 1;
2200 0 : Rel[lenRel - 1].f_negate = 0;
2201 0 : if (lastWordType == WT_INTEGER) {
2202 0 : lenStack--;
2203 0 : Rel[lenRel - 1].amount = Stack[lenStack].val;
2204 : }
2205 0 : wordType = WT_RELATIVE_UNIT;
2206 0 : } else if (GetIndexFromStr (word, AdjDay, &index) != -1) {
2207 0 : if (index != 1) {
2208 0 : lenRel++;
2209 0 : Rel = (relType *) realloc ((void *) Rel,
2210 : lenRel * sizeof (relType));
2211 0 : Rel[lenRel - 1].relUnit = 13; /* DAY in RelUnit list */
2212 0 : Rel[lenRel - 1].amount = 1;
2213 0 : if (index == 0) {
2214 0 : Rel[lenRel - 1].f_negate = 1;
2215 : } else {
2216 0 : Rel[lenRel - 1].f_negate = 0;
2217 : }
2218 : }
2219 0 : wordType = WT_ADJDAY;
2220 : } else {
2221 0 : printf ("unknown: %s\n", word);
2222 0 : goto errorReturn;
2223 : }
2224 0 : ptr = ptr2;
2225 0 : lastWordType = wordType;
2226 : }
2227 :
2228 : /* Deal with time left on the integer stack. */
2229 0 : if (lenStack > 1) {
2230 0 : printf ("Too many integers on the stack?\n");
2231 0 : goto errorReturn;
2232 : }
2233 0 : if (lenStack == 1) {
2234 0 : if (Stack[0].val < 0) {
2235 0 : printf ("Unable to deduce a negative time?\n");
2236 0 : goto errorReturn;
2237 : }
2238 0 : if (f_time) {
2239 0 : if (f_dateWord || f_slashWord) {
2240 0 : printf ("Already have date and time...\n");
2241 0 : goto errorReturn;
2242 : }
2243 0 : if ((Stack[0].len == 6) || (Stack[0].len == 8)) {
2244 0 : year = Stack[0].val / 10000;
2245 0 : f_year = 1;
2246 0 : month = (Stack[0].val % 10000) / 100;
2247 0 : day = Stack[0].val % 100;
2248 0 : f_slashWord = 1;
2249 0 : if ((month < 1) || (month > 12) || (day < 1) || (day > 31)) {
2250 0 : printf ("Unable to deduce the integer value\n");
2251 0 : return -1;
2252 : }
2253 : } else {
2254 0 : printf ("Unable to deduce the integer value\n");
2255 0 : goto errorReturn;
2256 : }
2257 : } else {
2258 0 : if (Stack[0].len < 3) {
2259 0 : curTime = Stack[0].val * 3600;
2260 0 : f_time = 1;
2261 0 : } else if (Stack[0].len < 5) {
2262 0 : curTime = ((Stack[0].val / 100) * 3600. +
2263 0 : (Stack[0].val % 100) * 60.);
2264 0 : f_time = 1;
2265 0 : } else if ((Stack[0].len == 6) || (Stack[0].len == 8)) {
2266 0 : year = Stack[0].val / 10000;
2267 0 : f_year = 1;
2268 0 : month = (Stack[0].val % 10000) / 100;
2269 0 : day = Stack[0].val % 100;
2270 0 : f_slashWord = 1;
2271 0 : if ((month < 1) || (month > 12) || (day < 1) || (day > 31)) {
2272 0 : printf ("Unable to deduce the integer value\n");
2273 0 : return -1;
2274 : }
2275 : } else {
2276 0 : printf ("Unable to deduce the time\n");
2277 0 : goto errorReturn;
2278 : }
2279 : }
2280 0 : lenStack = 0;
2281 : }
2282 0 : if (!f_time) {
2283 0 : if (f_ampm != -1) {
2284 0 : printf ("Problems setting the time to 0\n");
2285 0 : goto errorReturn;
2286 : }
2287 0 : curTime = 0;
2288 : }
2289 0 : if (f_ampm == 1) {
2290 : /* Adjust for 12 am */
2291 0 : sec = (sInt4) (curTime - (floor (curTime / SEC_DAY)) * SEC_DAY);
2292 0 : if (((sec % 43200L) / 3600) == 0) {
2293 0 : curTime -= 43200L;
2294 : }
2295 0 : } else if (f_ampm == 2) {
2296 : /* Adjust for 12 pm */
2297 0 : curTime += 43200L;
2298 0 : sec = (sInt4) (curTime - (floor (curTime / SEC_DAY)) * SEC_DAY);
2299 0 : if (((sec % 43200L) / 3600) == 0) {
2300 0 : curTime -= 43200L;
2301 : }
2302 : }
2303 0 : for (i = 0; i < lenRel; i++) {
2304 0 : if (Rel[i].f_negate) {
2305 0 : Rel[i].amount = -1 * Rel[i].amount;
2306 : }
2307 : }
2308 : /* Deal with adjustments by year or month. */
2309 0 : if (f_dateWord || f_slashWord) {
2310 : /* Check if we don't have the year. */
2311 0 : if (!f_year) {
2312 0 : *clock = Clock_Seconds ();
2313 0 : Clock_Epoch2YearDay ((sInt4) (floor (*clock / SEC_DAY)), &i, &year);
2314 : }
2315 : /* Deal with relative adjust by year and month. */
2316 0 : for (i = 0; i < lenRel; i++) {
2317 0 : if ((Rel[i].relUnit == 0) || (Rel[i].relUnit == 1)) {
2318 0 : year += Rel[i].amount;
2319 0 : } else if ((Rel[i].relUnit == 2) || (Rel[i].relUnit == 3)) {
2320 0 : month += Rel[i].amount;
2321 : }
2322 : }
2323 0 : while (month < 1) {
2324 0 : year--;
2325 0 : month += 12;
2326 : }
2327 0 : while (month > 12) {
2328 0 : year++;
2329 0 : month -= 12;
2330 : }
2331 0 : *clock = 0;
2332 0 : Clock_ScanDate (clock, year, month, day);
2333 :
2334 : } else {
2335 : /* Pure Time words. */
2336 0 : *clock = Clock_Seconds ();
2337 : /* round off to start of day */
2338 0 : *clock = (floor (*clock / SEC_DAY)) * SEC_DAY;
2339 : /* Deal with relative adjust by year and month. */
2340 0 : monthAdj = 0;
2341 0 : yearAdj = 0;
2342 0 : for (i = 0; i < lenRel; i++) {
2343 0 : if ((Rel[i].relUnit == 0) || (Rel[i].relUnit == 1)) {
2344 0 : if (Rel[i].f_negate) {
2345 0 : yearAdj -= Rel[i].amount;
2346 : } else {
2347 0 : yearAdj += Rel[i].amount;
2348 : }
2349 0 : } else if ((Rel[i].relUnit == 2) || (Rel[i].relUnit == 3)) {
2350 0 : if (Rel[i].f_negate) {
2351 0 : monthAdj -= Rel[i].amount;
2352 : } else {
2353 0 : monthAdj += Rel[i].amount;
2354 : }
2355 : }
2356 : }
2357 0 : if ((monthAdj != 0) || (yearAdj != 0)) {
2358 : /* Break clock into mon/day/year */
2359 0 : Clock_Epoch2YearDay ((sInt4) (floor (*clock / SEC_DAY)),
2360 : &day, &year);
2361 0 : month = Clock_MonthNum (day, year);
2362 0 : day -= (Clock_NumDay (month, 1, year, 1) - 1);
2363 0 : month += monthAdj;
2364 0 : year += yearAdj;
2365 0 : while (month < 1) {
2366 0 : year--;
2367 0 : month += 12;
2368 : }
2369 0 : while (month > 12) {
2370 0 : year++;
2371 0 : month -= 12;
2372 : }
2373 0 : *clock = 0;
2374 0 : Clock_ScanDate (clock, year, month, day);
2375 : }
2376 : }
2377 :
2378 : /* Join the date and the time. */
2379 0 : *clock += curTime;
2380 :
2381 : /* Finish the relative adjustments. */
2382 0 : for (i = 0; i < lenRel; i++) {
2383 0 : switch (Rel[i].relUnit) {
2384 : case 3: /* Fortnight. */
2385 : case 4:
2386 0 : *clock += (Rel[i].amount * 14 * 24 * 3600.);
2387 0 : break;
2388 : case 5: /* Week. */
2389 : case 6:
2390 0 : *clock += (Rel[i].amount * 7 * 24 * 3600.);
2391 0 : break;
2392 : case 7: /* Day. */
2393 : case 8:
2394 0 : *clock += (Rel[i].amount * 24 * 3600.);
2395 0 : break;
2396 : case 9: /* Hour. */
2397 : case 10:
2398 0 : *clock += (Rel[i].amount * 3600.);
2399 0 : break;
2400 : case 11: /* Minute. */
2401 : case 12:
2402 : case 13:
2403 : case 14:
2404 0 : *clock += (Rel[i].amount * 60.);
2405 0 : break;
2406 : case 15: /* Second. */
2407 : case 16:
2408 : case 17:
2409 : case 18:
2410 0 : *clock += Rel[i].amount;
2411 : break;
2412 : }
2413 : }
2414 :
2415 0 : if (f_gmt != 0) {
2416 : /* IsDaylightSaving takes clock in GMT, and Timezone. */
2417 : /* Note: A 0 is passed to DaylightSavings so it converts from LST to
2418 : * LST. */
2419 0 : if ((f_gmt == 1) && (Clock_IsDaylightSaving2 (*clock, 0) == 1)) {
2420 0 : *clock = *clock - 3600;
2421 : }
2422 : /* Handle gmt problems. We are going from Local time to GMT so we add
2423 : * the TimeZone here. */
2424 0 : *clock = *clock + TimeZone * 3600;
2425 : }
2426 :
2427 0 : free (Stack);
2428 0 : free (Rel);
2429 0 : return 0;
2430 :
2431 : errorReturn:
2432 0 : free (Stack);
2433 0 : free (Rel);
2434 0 : return -1;
2435 : }
2436 :
2437 : #ifdef CLOCK_PROGRAM
2438 : /* See clockstart.c */
2439 : #endif
|