1 /*----------------------------------------------------------------------------
2 --
3 --  Module:           TimDate
4 --
5 --  Project:          Tools - General C objects.
6 --  System:           Tim - Time and date manipulation.
7 --    Subsystem:      <>
8 --    Function block: <>
9 --
10 --  Description:
11 --    Manage time and date.
12 --
13 --    Date format:
14 --      Order:            YMD, DMY or MDY
15 --      Separator:        One character, 0 is no separator
16 --      Day leading 0:    0 is no, 1 is yes
17 --      Month leading 0:  0 is no, 1 is yes
18 --      Century:          0 is no, 1 is yes
19 --      1st weekday:      0 is Sunday, 1 is Monday
20 --
21 --    Time format:
22 --      12 or 24 hour:    12 or 24
23 --      12 hour suffix:   Two characters, two blanks is no suffix
24 --      24 hour suffix:   Two characters, two blanks is no suffix
25 --      Separator:        One character, 0 is no separator
26 --      Hour leading 0:   0 is no, 1 is yes
27 --
28 --  Filename:         TimDate.c
29 --
30 --  Authors:          Roger Larsson, Ulrika Bornetun
31 --  Creation date:    1990-11-30
32 --
33 --
34 --  (C) Copyright Ulrika Bornetun, Roger Larsson (1995)
35 --      All rights reserved
36 --
37 --  Permission to use, copy, modify, and distribute this software and its
38 --  documentation for any purpose and without fee is hereby granted,
39 --  provided that the above copyright notice appear in all copies. Ulrika
40 --  Bornetun and Roger Larsson make no representations about the usability
41 --  of this software for any purpose. It is provided "as is" without express
42 --  or implied warranty.
43 ----------------------------------------------------------------------------*/
44 
45 /* SCCS module identifier. */
46 static char SCCSID[] = "@(#) Module: TimDate.c, Version: 1.1, Date: 95/02/18 14:32:31";
47 
48 
49 /*----------------------------------------------------------------------------
50 --  Include files
51 ----------------------------------------------------------------------------*/
52 
53 #include <memory.h>
54 #include <stdio.h>
55 #include <string.h>
56 #include <time.h>
57 #include <sys/types.h>
58 #include <stdlib.h>
59 #include <ctype.h>
60 
61 #include "System.h"
62 #include "TimDate.h"
63 
64 
65 /*----------------------------------------------------------------------------
66 --  Macro definitions
67 ----------------------------------------------------------------------------*/
68 
69 
70 /*----------------------------------------------------------------------------
71 --  Type declarations
72 ----------------------------------------------------------------------------*/
73 
74 /* Order to use for year, month and day. */
75 typedef enum {
76   DATE_MMDDYY, DATE_DDMMYY, DATE_YYMMDD
77 } DATE_ORDER;
78 
79 /* Format used for dates. */
80 typedef struct {
81   DATE_ORDER  order;
82   char        separator[ 2 ];
83   Boolean     day_leading_zero;
84   Boolean     month_leading_zero;
85   Boolean     include_century;
86   char        ymd_format[ 50 ];
87   char        md_format[ 50 ];
88   char        d_format[ 50 ];
89   int         week_1st_day;
90 } DATE_FORMAT;
91 
92 /* Format used for times. */
93 typedef struct {
94   Boolean  hour_12;
95   char     hour_12_suffix[ 5 ];
96   char     hour_12_suffix_separator[ 2 ];
97   char     hour_24_suffix[ 5 ];
98   char     hour_24_suffix_separator[ 2 ];
99   char     separator[ 2 ];
100   Boolean  hour_leading_zero;
101   char     hm_format[ 50 ];
102   char     m_format[ 50 ];
103 } TIME_FORMAT;
104 
105 
106 /*----------------------------------------------------------------------------
107 --  Global definitions
108 ----------------------------------------------------------------------------*/
109 
110 /* Date and time format. */
111 static char  date_format_string[ 50 ] = {
112   'Y', 'M', 'D', '-', '1', '1', '1', '1', '\0' };
113 static char  time_format_string[ 50 ] = {
114   '2', '4', ' ', ' ', ' ', ' ', ':', '0', '\0' };
115 
116 static DATE_FORMAT  user_date_format = {
117   DATE_YYMMDD, { '-', '\0' }, True, True, True,
118   { '%','d','%','*','[','^','0','-','9',']','%','d','%','*','[','^','0','-',
119     '9',']','%','d','\0' },
120   { '%','d','%','*','[','^','0','-','9',']','%','d','\0' },
121   { '%','d','\0' },
122   1
123 };
124 
125 static DATE_FORMAT  iso_date_format = {
126   DATE_YYMMDD, { '-', '\0' }, True, True, True,
127   { '%','d','%','*','[','^','0','-','9',']','%','d','%','*','[','^','0','-',
128     '9',']','%','d','\0' },
129   { '%','d','%','*','[','^','0','-','9',']','%','d','\0' },
130   { '%','d','\0' },
131   1
132 };
133 
134 static TIME_FORMAT  user_time_format = {
135   False,
136   { '\0' }, { ' ', '\0' },
137   { '\0' }, { ' ', '\0' },
138   { ':', '\0' }, False,
139   { '%','d','%','*','[','^','0','-','9',']','%','d', '\0' },
140   { '%','d','\0' }
141 };
142 
143 static TIME_FORMAT  iso_time_format = {
144   False,
145   { '\0' }, { ' ', '\0' },
146   { '\0' }, { ' ', '\0' },
147   { ':', '\0' }, False,
148   { '%','d','%','*','[','^','0','-','9',']','%','d', '\0' },
149   { '%','d','\0' }
150 };
151 
152 /* Number of days in the month. */
153 static int days_in_month_leap_year[] = {
154   31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
155 
156 static int days_in_month[] = {
157   31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
158 
159 /* Offset of the days within the year (0 - 365). */
160 static int day_offset[] = {
161   0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
162 
163 static int day_offset_leap_year[] = {
164   0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
165 
166 /* Week number offsets 1970-2070 (not nice but it works). */
167 static UINT8 mon_week_offsets[] = {
168    0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1,
169    0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
170    1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0,
171    0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0,
172    0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
173    1,
174 };
175 
176 static UINT8 sun_week_offsets[] = {
177    1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0,
178    0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1,
179    1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0,
180    0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0,
181    0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1,
182    1,
183 };
184 
185 /* Use the standard UNIX week numbers. */
186 static  unix_week_no = False;
187 
188 
189 /*----------------------------------------------------------------------------
190 --  Function prototypes
191 ----------------------------------------------------------------------------*/
192 
193 static struct tm
194   *convertToLocalStruct( TIM_TIME_REF  time,
195                          struct tm     *container );
196 
197 static struct tm
198   *convertToStruct( TIM_TIME_REF  time,
199                     struct tm     *container );
200 
201 static int
202   dayNumberInYear( int year,
203                    int month,
204                    int day );
205 
206 static int
207   daysInYear( int  year );
208 
209 static void
210   formatDate( DATE_FORMAT   *date_format,
211               TIM_TIME_REF  time,
212               char          *buffer,
213               int           buffer_size );
214 
215 static void
216   formatFullDate( DATE_FORMAT   *date_format,
217                   TIM_TIME_REF  time,
218                   char          *buffer,
219                   int           buffer_size );
220 
221 static void
222   formatTime( TIME_FORMAT   *time_format,
223               TIM_TIME_REF  time,
224               char          *buffer,
225               int           buffer_size );
226 
227 static TIM_STATUS_TYPE
228   isTimeOk( int  year,
229             int  month,
230             int  day,
231             int  hour,
232             int  minute,
233             int  second );
234 
235 static TIM_STATUS_TYPE
236   makeDateFromString( DATE_FORMAT   *date_format,
237                       TIM_TIME_REF  *time,
238                       char          *string );
239 
240 static TIM_STATUS_TYPE
241   makeTimeFromString( TIME_FORMAT   *time_format,
242                       TIM_TIME_REF  *time,
243                       char          *string );
244 
245 static int
246   noCaseStrcmp( char  *buffer1,
247                 char  *buffer2 );
248 
249 static time_t
250   secondsSince1970( struct tm *time_ref );
251 
252 
253 /*----------------------------------------------------------------------------
254 --  Functions
255 ----------------------------------------------------------------------------*/
256 
257 void
TimAddDays(TIM_TIME_REF * time,int days)258   TimAddDays( TIM_TIME_REF *time, int days )
259 {
260 
261   /* Code. */
262 
263   *time = *time + (days * 24 * 60 * 60);
264 
265 } /* TimAddDays */
266 
267 
268 /*----------------------------------------------------------------------*/
269 
270 void
TimAddHours(TIM_TIME_REF * time,int hours)271   TimAddHours( TIM_TIME_REF *time, int hours )
272 {
273 
274   /* Code. */
275 
276   *time = *time + (hours * 60 * 60);
277 
278 
279   return;
280 
281 } /* TimAddHours */
282 
283 
284 /*----------------------------------------------------------------------*/
285 
286 void
TimAddMinutes(TIM_TIME_REF * time,int minutes)287   TimAddMinutes( TIM_TIME_REF *time, int minutes )
288 {
289 
290   /* Code. */
291 
292   *time = *time + (minutes * 60);
293 
294 
295   return;
296 
297 } /* TimAddMinutes */
298 
299 
300 /*----------------------------------------------------------------------*/
301 
302 void
TimAddMonths(TIM_TIME_REF * time,int months)303   TimAddMonths( TIM_TIME_REF *time, int months )
304 {
305 
306   /* Variables. */
307   int        add_months;
308   int        add_year;
309   time_t     new_time;
310   struct tm  *time_struct;
311   struct tm  time_struct_obj;
312 
313 
314   /* Code. */
315 
316   time_struct = convertToStruct( *time, &time_struct_obj );
317 
318   add_year   = abs( months ) / 12;
319   add_months = abs( months ) % 12;
320 
321   if( months < 0 ) {
322     time_struct -> tm_year = time_struct -> tm_year - add_year;
323     time_struct -> tm_mon  = time_struct -> tm_mon  - add_months;
324   } else {
325     time_struct -> tm_year = time_struct -> tm_year + add_year;
326     time_struct -> tm_mon  = time_struct -> tm_mon  + add_months;
327   }
328 
329   if( time_struct -> tm_mon > 11 ) {
330     time_struct -> tm_year = time_struct -> tm_year + 1;
331     time_struct -> tm_mon  = time_struct -> tm_mon  - 12;
332   }
333 
334   if( time_struct -> tm_mon < 0 ) {
335     time_struct -> tm_year = time_struct -> tm_year - 1;
336     time_struct -> tm_mon  = time_struct -> tm_mon  + 12;
337   }
338 
339   time_struct -> tm_yday  = dayNumberInYear(
340                               time_struct -> tm_year,
341                               time_struct -> tm_mon + 1,
342                               time_struct -> tm_mday ) - 1;
343 
344   new_time = (TIM_TIME_REF) secondsSince1970( time_struct );
345 
346   *time = new_time;
347 
348 
349   return;
350 
351 } /* TimAddMonths */
352 
353 
354 /*----------------------------------------------------------------------*/
355 
356 void
TimAddSeconds(TIM_TIME_REF * time,int seconds)357   TimAddSeconds( TIM_TIME_REF *time, int seconds )
358 {
359 
360   /* Code. */
361 
362   *time = *time + seconds;
363 
364 
365   return;
366 
367 } /* TimAddSeconds */
368 
369 
370 /*----------------------------------------------------------------------*/
371 
372 TIM_TIME_REF
TimAddTime(TIM_TIME_REF time,TIM_TIME_REF to_time)373   TimAddTime( TIM_TIME_REF  time,
374               TIM_TIME_REF  to_time )
375 {
376 
377   /* Code. */
378 
379   return( time + to_time );
380 
381 } /* TimAdd */
382 
383 
384 /*----------------------------------------------------------------------*/
385 
386 void
TimAddYears(TIM_TIME_REF * time,int years)387   TimAddYears( TIM_TIME_REF *time, int years )
388 {
389 
390   /* Variables. */
391   time_t     new_time;
392   struct tm  *time_struct;
393   struct tm  time_struct_obj;
394 
395 
396   /* Code. */
397 
398   time_struct = convertToStruct( *time, &time_struct_obj );
399 
400   time_struct -> tm_year = time_struct -> tm_year + years;
401   time_struct -> tm_yday  = dayNumberInYear(
402                               time_struct -> tm_year,
403                               time_struct -> tm_mon + 1,
404                               time_struct -> tm_mday ) - 1;
405 
406   new_time = (TIM_TIME_REF) secondsSince1970( time_struct );
407 
408   if( new_time >= 0 )
409     *time = new_time;
410 
411 
412   return;
413 
414 } /* TimAddYears */
415 
416 
417 /*----------------------------------------------------------------------*/
418 
419 int
TimDaysInMonth(TIM_TIME_REF time)420   TimDaysInMonth( TIM_TIME_REF  time )
421 {
422 
423   /* Variables. */
424   struct tm  *time_struct;
425   struct tm  time_struct_obj;
426 
427 
428   /* Code. */
429 
430   time_struct = convertToStruct( time, &time_struct_obj );
431 
432   if( TimIsLeapYear( time ) == TIM_YES )
433     return( days_in_month_leap_year[ time_struct -> tm_mon ] );
434 
435 
436   return( days_in_month[ time_struct -> tm_mon ] );
437 
438 } /* TimDaysInMonth */
439 
440 
441 /*----------------------------------------------------------------------*/
442 
443 int
TimDaysInYear(TIM_TIME_REF time)444   TimDaysInYear( TIM_TIME_REF  time )
445 {
446 
447   /* Code. */
448 
449   if( TimIsLeapYear( time ) == TIM_YES )
450     return( 366 );
451 
452 
453   return( 365 );
454 
455 } /* TimDaysInYear */
456 
457 
458 /*----------------------------------------------------------------------*/
459 
460 TIM_STATUS_TYPE
TimDelta(TIM_TIME_REF time1,TIM_TIME_REF time2,TIM_DELTA_TYPE * delta)461   TimDelta( TIM_TIME_REF    time1,
462             TIM_TIME_REF    time2,
463             TIM_DELTA_TYPE  *delta )
464 {
465 
466   /* Variables. */
467   TIM_TIME_REF  temp_time;
468 
469 
470   /* Code. */
471 
472   if( time1 > time2 ) {
473     temp_time = time1;
474     time1     = time2;
475     time2     = temp_time;
476   }
477 
478   delta -> seconds = ((int) time2) - ((int) time1);
479   delta -> minutes = delta -> seconds / 60;
480   delta -> hours   = delta -> seconds / (60 * 60);
481   delta -> days    = delta -> seconds / (60 * 60 * 24);
482   delta -> weeks   = delta -> seconds / (60 * 60 * 24 * 7);
483 
484 
485   return( TIM_OK );
486 
487 } /* TimDelta */
488 
489 
490 /*----------------------------------------------------------------------*/
491 
492 void
TimFormatDate(TIM_TIME_REF time,char * buffer,int buffer_size)493   TimFormatDate( TIM_TIME_REF  time,
494                  char          *buffer,
495                  int           buffer_size )
496 {
497 
498   /* Code. */
499 
500   formatDate( &user_date_format, time, buffer, buffer_size );
501 
502 
503   return;
504 
505 } /* TimFormatDate */
506 
507 
508 /*----------------------------------------------------------------------*/
509 
510 void
TimFormatIsoDate(TIM_TIME_REF time,char * buffer,int buffer_size)511   TimFormatIsoDate( TIM_TIME_REF  time,
512                     char          *buffer,
513                     int           buffer_size )
514 {
515 
516   /* Code. */
517 
518   formatDate( &iso_date_format, time, buffer, buffer_size );
519 
520 
521   return;
522 
523 } /* TimFormatIsoDate */
524 
525 
526 /*----------------------------------------------------------------------*/
527 
528 void
TimFormatFullDate(TIM_TIME_REF time,char * buffer,int buffer_size)529   TimFormatFullDate( TIM_TIME_REF  time,
530                      char          *buffer,
531                      int           buffer_size )
532 {
533 
534   /* Code. */
535 
536   formatFullDate( &user_date_format, time, buffer, buffer_size );
537 
538 
539   return;
540 
541 } /* TimFormatFullDate */
542 
543 
544 /*----------------------------------------------------------------------*/
545 
546 void
TimFormatFullIsoDate(TIM_TIME_REF time,char * buffer,int buffer_size)547   TimFormatFullIsoDate( TIM_TIME_REF  time,
548                         char          *buffer,
549                         int           buffer_size )
550 {
551 
552   /* Code. */
553 
554   formatFullDate( &iso_date_format, time, buffer, buffer_size );
555 
556 
557   return;
558 
559 } /* TimFormatFullIsoDate */
560 
561 
562 /*----------------------------------------------------------------------*/
563 
564 void
TimFormatStrTime(TIM_TIME_REF time,char * format,char * buffer,int buffer_size)565   TimFormatStrTime( TIM_TIME_REF  time,
566                     char          *format,
567                     char          *buffer,
568                     int           buffer_size )
569 {
570 
571   /* Variables. */
572   int        size;
573   struct tm  *time_struct;
574   struct tm  time_struct_obj;
575 
576 
577   /* Code. */
578 
579   time_struct = convertToStruct( time, &time_struct_obj );
580 
581   size = strftime( buffer, buffer_size, format, time_struct );
582 
583   if( size == 0 )
584     *buffer = '\0';
585 
586 
587   return;
588 
589 } /* TimFormatStrTime */
590 
591 
592 /*----------------------------------------------------------------------*/
593 
594 void
TimFormatTime(TIM_TIME_REF time,char * buffer,int buffer_size)595   TimFormatTime( TIM_TIME_REF  time,
596                  char          *buffer,
597                  int           buffer_size )
598 {
599 
600   /* Code. */
601 
602   formatTime( &user_time_format, time, buffer, buffer_size );
603 
604 
605   return;
606 
607 } /* TimFormatTime */
608 
609 
610 /*----------------------------------------------------------------------*/
611 
612 void
TimFormatIsoTime(TIM_TIME_REF time,char * buffer,int buffer_size)613   TimFormatIsoTime( TIM_TIME_REF  time,
614                     char          *buffer,
615                     int           buffer_size )
616 {
617 
618   /* Code. */
619 
620   formatTime( &iso_time_format, time, buffer, buffer_size );
621 
622 
623   return;
624 
625 } /* TimFormatIsoTime */
626 
627 
628 /*----------------------------------------------------------------------*/
629 
630 int
TimHour(TIM_TIME_REF time)631   TimHour( TIM_TIME_REF  time )
632 {
633 
634   /* Variables. */
635   struct tm *time_struct;
636   struct tm  time_struct_obj;
637 
638 
639   /* Code. */
640 
641   time_struct = convertToStruct( time, &time_struct_obj );
642 
643 
644   return( time_struct -> tm_hour );
645 
646 } /* TimHour */
647 
648 
649 /*----------------------------------------------------------------------*/
650 
651 int
TimIndexOfDay(TIM_TIME_REF time)652   TimIndexOfDay( TIM_TIME_REF  time )
653 {
654 
655   /* Variables. */
656   struct tm  *time_struct;
657   struct tm  time_struct_obj;
658 
659 
660   /* Code. */
661 
662   time_struct = convertToStruct( time, &time_struct_obj );
663 
664 
665   return( time_struct -> tm_mday );
666 
667 } /* TimIndexOfDay */
668 
669 
670 /*----------------------------------------------------------------------*/
671 
672 int
TimIndexOfDayInIsoWeek(TIM_TIME_REF time)673   TimIndexOfDayInIsoWeek( TIM_TIME_REF  time )
674 {
675 
676   /* Variables. */
677   struct tm  *time_struct;
678   struct tm  time_struct_obj;
679 
680 
681   /* Code. */
682 
683   time_struct = convertToStruct( time, &time_struct_obj );
684 
685   if( time_struct -> tm_wday == 0 )
686     return( time_struct -> tm_wday + 7 );
687 
688 
689   return( time_struct -> tm_wday );
690 
691 } /* TimIndexOfDayInIsoWeek */
692 
693 
694 /*----------------------------------------------------------------------*/
695 
696 int
TimIndexOfDayInWeek(TIM_TIME_REF time)697   TimIndexOfDayInWeek( TIM_TIME_REF  time )
698 {
699 
700   /* Variables. */
701   struct tm  *time_struct;
702   struct tm  time_struct_obj;
703 
704 
705   /* Code. */
706 
707   time_struct = convertToStruct( time, &time_struct_obj );
708 
709   switch( user_date_format.week_1st_day ) {
710 
711     case 0:
712       return( time_struct -> tm_wday + 1 );
713 
714     case 1:
715     default:
716       if( time_struct -> tm_wday == 0 )
717         return( time_struct -> tm_wday + 7 );
718       else
719         return( time_struct -> tm_wday );
720 
721     } /* switch */
722 
723 } /* TimIndexOfDayInWeek */
724 
725 
726 /*----------------------------------------------------------------------*/
727 
728 int
TimIndexOfFirstDayInWeek()729   TimIndexOfFirstDayInWeek()
730 {
731 
732   /* Code. */
733 
734 
735   return( user_date_format.week_1st_day );
736 
737 } /* TimIndexOfFirstDayInWeek */
738 
739 
740 /*----------------------------------------------------------------------*/
741 
742 int
TimIndexOfDayInYear(TIM_TIME_REF time)743   TimIndexOfDayInYear( TIM_TIME_REF time )
744 {
745 
746   /* Variables. */
747   struct tm  *time_struct;
748   struct tm  time_struct_obj;
749 
750 
751   /* Code. */
752 
753   time_struct = convertToStruct( time, &time_struct_obj );
754 
755 
756   return( time_struct -> tm_yday + 1 );
757 
758 } /* TimIndexOfDayInYear */
759 
760 
761 /*----------------------------------------------------------------------*/
762 
763 int
TimIndexOfMonth(TIM_TIME_REF time)764   TimIndexOfMonth( TIM_TIME_REF  time )
765 {
766 
767   /* Variables. */
768   struct tm  *time_struct;
769   struct tm  time_struct_obj;
770 
771 
772   /* Code. */
773 
774   time_struct = convertToStruct( time, &time_struct_obj );
775 
776 
777   return( time_struct -> tm_mon + 1 );
778 
779 } /* TimIndexOfMonth */
780 
781 
782 /*----------------------------------------------------------------------*/
783 
784 int
TimIndexOfIsoWeek(TIM_TIME_REF time)785   TimIndexOfIsoWeek( TIM_TIME_REF  time )
786 {
787 
788   /* Variables. */
789   int        week_no;
790   int        year;
791   char       buffer[ 10 ];
792   struct tm  *time_struct;
793   struct tm  time_struct_obj;
794 
795 
796   /* Code. */
797 
798   time_struct = convertToStruct( time, &time_struct_obj );
799 
800   strftime( buffer, sizeof( buffer ), "%W", time_struct );
801 
802   week_no = atoi( buffer ) + 1;
803   year    = time_struct -> tm_year + 1900;
804 
805   if( week_no > 1 && year >= 1970 && year <= 2070 && ! unix_week_no )
806     week_no = week_no - (int) mon_week_offsets[ year - 1970 ];
807 
808 
809   return( week_no );
810 
811 } /* TimIndexOfIsoWeek */
812 
813 
814 /*----------------------------------------------------------------------*/
815 
816 int
TimIndexOfWeek(TIM_TIME_REF time)817   TimIndexOfWeek( TIM_TIME_REF  time )
818 {
819 
820   /* Variables. */
821   int        week_no;
822   int        year;
823   char       buffer[ 10 ];
824   struct tm  *time_struct;
825   struct tm  time_struct_obj;
826 
827 
828   /* Code. */
829 
830   time_struct = convertToStruct( time, &time_struct_obj );
831 
832   switch( user_date_format.week_1st_day ) {
833     case 0:
834       strftime( buffer, sizeof( buffer ), "%U", time_struct );
835       break;
836 
837     case 1:
838     default:
839       strftime( buffer, sizeof( buffer ), "%W", time_struct );
840       break;
841     }
842 
843   week_no = atoi( buffer ) + 1;
844   year    = time_struct -> tm_year + 1900;
845 
846   switch( user_date_format.week_1st_day ) {
847     case 0:
848       if( week_no > 1 && year >= 1970 && year <= 2070 && ! unix_week_no )
849         week_no = week_no - (int) sun_week_offsets[ year - 1970 ];
850       break;
851 
852     case 1:
853     default:
854       if( week_no > 1 && year >= 1970 && year <= 2070 && ! unix_week_no )
855         week_no = week_no - (int) mon_week_offsets[ year - 1970 ];
856       break;
857   }
858 
859 
860   return( week_no );
861 
862 } /* TimIndexOfWeek */
863 
864 
865 /*----------------------------------------------------------------------*/
866 
867 int
TimIndexOfYear(TIM_TIME_REF time)868   TimIndexOfYear( TIM_TIME_REF  time )
869 {
870 
871   /* Variables. */
872   struct tm  *time_struct;
873   struct tm  time_struct_obj;
874 
875 
876   /* Code. */
877 
878   time_struct = convertToStruct( time, &time_struct_obj );
879 
880 
881   return( time_struct -> tm_year + 1900 );
882 
883 } /* TimIndexOfYear */
884 
885 
886 /*----------------------------------------------------------------------*/
887 
888 TIM_STATUS_TYPE
TimInitializeFormat(char * date_format_str,char * time_format_str)889   TimInitializeFormat( char  *date_format_str,
890                        char  *time_format_str )
891 {
892 
893   /* Variables. */
894   char         day_format[ 50 ];
895   char         hour_format[ 50 ];
896   char         minute_format[ 50 ];
897   char         month_format[ 50 ];
898   char         sep_format[ 50 ];
899   char         suffix_format[ 50 ];
900   char         year_format[ 50 ];
901   DATE_FORMAT  new_date_format;
902   TIME_FORMAT  new_time_format;
903 
904 
905   /* Code. */
906 
907   /* Correct length of the format strings? */
908   if( strlen( date_format_str ) != 8 )
909     return( TIM_ERROR );
910 
911   if( strlen( time_format_str ) != 8 )
912     return( TIM_ERROR );
913 
914 
915   /* Date format. */
916 
917   /* Date order. */
918   if( strncmp( &date_format_str[ 0 ], "MDY", 3 ) == 0 )
919     new_date_format.order = DATE_MMDDYY;
920   else if( strncmp( &date_format_str[ 0 ], "DMY", 3 ) == 0 )
921     new_date_format.order = DATE_DDMMYY;
922   else if( strncmp( &date_format_str[ 0 ], "YMD", 3 ) == 0 )
923     new_date_format.order = DATE_YYMMDD;
924   else
925     return( TIM_ERROR );
926 
927   /* Separator. */
928   if( date_format_str[ 3 ] == '0' )
929     strcpy( new_date_format.separator, "" );
930   else if( ! isdigit( date_format_str[ 3 ] ) ) {
931     new_date_format.separator[ 0 ] = date_format_str[ 3 ];
932     new_date_format.separator[ 1 ] = '\0';
933   } else
934     return( TIM_ERROR );
935 
936   /* Day leading zero. */
937   if( date_format_str[ 4 ] == '1' )
938     new_date_format.day_leading_zero = True;
939   else
940     new_date_format.day_leading_zero = False;
941 
942   /* Month leading zero. */
943   if( date_format_str[ 5 ] == '1' )
944     new_date_format.month_leading_zero = True;
945   else
946     new_date_format.month_leading_zero = False;
947 
948   /* Include century. */
949   if( date_format_str[ 6 ] == '1' )
950     new_date_format.include_century = True;
951   else
952     new_date_format.include_century = False;
953 
954   /* First day in week. */
955   if( date_format_str[ 7 ] == '0' )
956     new_date_format.week_1st_day = 0;
957   else
958     new_date_format.week_1st_day = 1;
959 
960 
961   /* Time format. */
962 
963   /* 12/24 hour time. */
964   if( strncmp( &time_format_str[ 0 ], "12", 2 ) == 0 )
965     new_time_format.hour_12 = True;
966   else if( strncmp( &time_format_str[ 0 ], "24", 2 ) == 0 )
967     new_time_format.hour_12 = False;
968   else
969     return( TIM_ERROR );
970 
971   /* 12 hour suffix. */
972   if( strncmp( &time_format_str[ 2 ], "  ", 2 ) == 0 ) {
973     if( new_time_format.hour_12 ) {
974       strncpy( new_time_format.hour_12_suffix, "am", 2 );
975       new_time_format.hour_12_suffix[ 2 ] = '\0';
976       strcpy( new_time_format.hour_12_suffix_separator, " " );
977     } else {
978       new_time_format.hour_12_suffix[ 0 ] = '\0';
979       strcpy( new_time_format.hour_12_suffix_separator, "" );
980     }
981   } else {
982     strncpy( new_time_format.hour_12_suffix, &time_format_str[ 2 ], 2 );
983     new_time_format.hour_12_suffix[ 2 ] = '\0';
984     strcpy( new_time_format.hour_12_suffix_separator, " " );
985   }
986 
987   /* 24 hour suffix. */
988   if( strncmp( &time_format_str[ 4 ], "  ", 2 ) == 0 ) {
989     if( new_time_format.hour_12 ) {
990       strncpy( new_time_format.hour_24_suffix, "pm", 2 );
991       new_time_format.hour_24_suffix[ 2 ] = '\0';
992       strcpy( new_time_format.hour_24_suffix_separator, " " );
993     } else {
994       new_time_format.hour_24_suffix[ 0 ] = '\0';
995       strcpy( new_time_format.hour_24_suffix_separator, "" );
996     }
997   } else {
998     strncpy( new_time_format.hour_24_suffix, &time_format_str[ 4 ], 2 );
999     new_time_format.hour_24_suffix[ 2 ] = '\0';
1000     strcpy( new_time_format.hour_24_suffix_separator, " " );
1001   }
1002 
1003   /* Separator. */
1004   if( time_format_str[ 6 ] == '0' ) {
1005     strcpy( new_time_format.separator, "" );
1006   } else if( ! isdigit( time_format_str[ 6 ] ) ) {
1007     new_time_format.separator[ 0 ] = time_format_str[ 6 ];
1008     new_time_format.separator[ 1 ] = '\0';
1009   } else
1010     return( TIM_ERROR );
1011 
1012   /* Hour leading zero. */
1013   if( time_format_str[ 7 ] == '1' )
1014     new_time_format.hour_leading_zero = True;
1015   else
1016     new_time_format.hour_leading_zero = False;
1017 
1018 
1019   /* Store the result. */
1020   memcpy( (void *) &user_date_format, (void *) &new_date_format,
1021            sizeof( DATE_FORMAT ) );
1022 
1023   memcpy( (void *) &user_time_format, (void *) &new_time_format,
1024            sizeof( TIME_FORMAT ) );
1025 
1026 
1027   /* Read dates. */
1028 
1029   /* Year format? */
1030   if( user_date_format.separator[ 0 ] == '\0' ) {
1031     if( user_date_format.include_century )
1032       strcpy( year_format, "%4d" );
1033     else
1034       strcpy( year_format, "%2d" );
1035   } else
1036     strcpy( year_format, "%d" );
1037 
1038   /* Month format? */
1039   if( user_date_format.separator[ 0 ] == '\0' ) {
1040     if( user_date_format.month_leading_zero )
1041       strcpy( month_format, "%2d" );
1042     else
1043       strcpy( month_format, "%1d" );
1044   } else
1045     strcpy( month_format, "%d" );
1046 
1047   /* Day format? */
1048   if( user_date_format.separator[ 0 ] == '\0' ) {
1049     if( user_date_format.day_leading_zero )
1050       strcpy( day_format, "%2d" );
1051     else
1052       strcpy( day_format, "%1d" );
1053   } else
1054     strcpy( day_format, "%d" );
1055 
1056   /* Separator format? */
1057   if( user_date_format.separator[ 0 ] != '\0' )
1058     strcpy( sep_format, "%*[^0-9]" );
1059   else
1060     sep_format[ 0 ] = '\0';
1061 
1062   /* MMDDYY format? */
1063   if( user_date_format.order == DATE_MMDDYY ) {
1064     sprintf( user_date_format.ymd_format, "%s%s%s%s%s",
1065              month_format, sep_format, day_format, sep_format, year_format );
1066     sprintf( user_date_format.md_format, "%s%s%s",
1067              month_format, sep_format, day_format );
1068     sprintf( user_date_format.d_format, "%s",
1069              day_format );
1070   }
1071 
1072   /* DDMMYY format? */
1073   if( user_date_format.order == DATE_DDMMYY ) {
1074     sprintf( user_date_format.ymd_format, "%s%s%s%s%s",
1075              day_format, sep_format, month_format, sep_format, year_format );
1076     sprintf( user_date_format.md_format,  "%s%s%s",
1077              day_format, sep_format, month_format );
1078     sprintf( user_date_format.d_format,   "%s",
1079              day_format );
1080   }
1081 
1082   /* YYMMDD format? */
1083   if( user_date_format.order == DATE_YYMMDD ) {
1084     sprintf( user_date_format.ymd_format, "%s%s%s%s%s",
1085              year_format, sep_format, month_format, sep_format, day_format );
1086     sprintf( user_date_format.md_format, "%s%s%s",
1087              month_format, sep_format, day_format );
1088     sprintf( user_date_format.d_format, "%s",
1089              day_format );
1090   }
1091 
1092 
1093   /* Read times. */
1094 
1095   /* Hour format? */
1096   if( user_time_format.separator[ 0 ] == '\0' ) {
1097     if( user_time_format.hour_leading_zero )
1098       strcpy( hour_format, "%2d" );
1099     else
1100       strcpy( hour_format, "%1d" );
1101   } else
1102     strcpy( hour_format, "%d" );
1103 
1104   /* Minute format? */
1105   strcpy( minute_format, "%2d" );
1106 
1107   /* Separator format? */
1108   if( user_time_format.separator[ 0 ] != '\0' )
1109     strcpy( sep_format, "%*[^0-9]" );
1110   else
1111     sep_format[ 0 ] = '\0';
1112 
1113   /* Suffix format. */
1114   if( user_time_format.hour_12 )
1115     strcpy( suffix_format, "%s" );
1116   else
1117     suffix_format[ 0 ] = '\0';
1118 
1119   /* Time formats. */
1120   sprintf( user_time_format.hm_format, "%s%s%s%s",
1121            hour_format, sep_format, minute_format, suffix_format );
1122   sprintf( user_time_format.m_format, "%s%s",
1123            minute_format, suffix_format );
1124 
1125 
1126   /* Save the date and time formats. */
1127   strcpy( date_format_string, date_format_str );
1128   strcpy( time_format_string, time_format_str );
1129 
1130 
1131   return( TIM_OK );
1132 
1133 } /* TimInitializeFormat */
1134 
1135 
1136 /*----------------------------------------------------------------------*/
1137 
1138 TIM_STATUS_TYPE
TimIsLeapYear(TIM_TIME_REF time)1139   TimIsLeapYear( TIM_TIME_REF time )
1140 {
1141 
1142   /* Variables. */
1143   struct tm  *time_struct;
1144   struct tm  time_struct_obj;
1145 
1146 
1147   /* Code. */
1148 
1149   time_struct = convertToStruct( time, &time_struct_obj );
1150 
1151   if( daysInYear( time_struct -> tm_year ) == 366 )
1152     return( TIM_YES );
1153 
1154 
1155   return( TIM_NO );
1156 
1157 } /* TimIsLeapYear */
1158 
1159 
1160 /*----------------------------------------------------------------------*/
1161 
1162 TIM_STATUS_TYPE
TimIsSameDate(TIM_TIME_REF time1,TIM_TIME_REF time2)1163   TimIsSameDate( TIM_TIME_REF time1,
1164                  TIM_TIME_REF time2 )
1165 {
1166 
1167   /* Code. */
1168 
1169   if( TimIndexOfYear(  time1 ) == TimIndexOfYear(  time2 ) &&
1170       TimIndexOfMonth( time1 ) == TimIndexOfMonth( time2 ) &&
1171       TimIndexOfDay(   time1 ) == TimIndexOfDay(   time2 ) )
1172     return( TIM_YES );
1173 
1174 
1175   return( TIM_NO );
1176 
1177 } /* TimIsSameDate */
1178 
1179 
1180 /*----------------------------------------------------------------------*/
1181 
1182 TIM_TIME_REF
TimLocalTime(TIM_TIME_REF time)1183   TimLocalTime( TIM_TIME_REF  time )
1184 {
1185 
1186   /* Variables. */
1187   time_t     new_time;
1188   struct tm  *time_struct;
1189   struct tm  time_struct_obj;
1190 
1191 
1192   /* Code. */
1193 
1194   time_struct = convertToLocalStruct( time, &time_struct_obj );
1195 
1196   new_time = secondsSince1970( time_struct );
1197 
1198 
1199   return( (TIM_TIME_REF) new_time );
1200 
1201 } /* TimLocalTime */
1202 
1203 
1204 /*----------------------------------------------------------------------*/
1205 
1206 TIM_TIME_REF
TimMakeTime(int year,int month,int day,int hour,int minute,int second)1207   TimMakeTime( int  year,
1208                int  month,
1209                int  day,
1210                int  hour,
1211                int  minute,
1212                int  second )
1213 {
1214 
1215   /* Variables. */
1216   time_t     new_time;
1217   time_t     now;
1218   struct tm  *time_struct;
1219   struct tm  time_struct_obj;
1220 
1221 
1222   /* Code. */
1223 
1224   now = time( NULL );
1225 
1226   time_struct = convertToStruct( now, &time_struct_obj );
1227 
1228   if( year != TIM_NOW )
1229     time_struct -> tm_year = year - 1900;
1230 
1231   if( month != TIM_NOW )
1232     time_struct -> tm_mon = month - 1;
1233 
1234   if( day != TIM_NOW )
1235     time_struct -> tm_mday = day;
1236 
1237   if( hour != TIM_NOW )
1238     time_struct -> tm_hour = hour;
1239 
1240   if( minute != TIM_NOW )
1241     time_struct -> tm_min = minute;
1242 
1243   if( second != TIM_NOW )
1244     time_struct -> tm_sec = second;
1245 
1246   time_struct -> tm_yday  = dayNumberInYear(
1247                               time_struct -> tm_year,
1248                               time_struct -> tm_mon + 1,
1249                               time_struct -> tm_mday ) - 1;
1250 
1251   new_time = (TIM_TIME_REF) secondsSince1970( time_struct );
1252 
1253 
1254   return( new_time );
1255 
1256 } /* TimMakeTime */
1257 
1258 
1259 /*----------------------------------------------------------------------*/
1260 
1261 TIM_STATUS_TYPE
TimMakeDateFromString(TIM_TIME_REF * time,char * string)1262   TimMakeDateFromString( TIM_TIME_REF  *time,
1263                          char          *string )
1264 {
1265 
1266   /* Variables. */
1267   TIM_STATUS_TYPE  status;
1268 
1269 
1270   /* Code. */
1271 
1272   status = makeDateFromString( &user_date_format, time, string );
1273 
1274 
1275   return( status );
1276 
1277 } /* TimMakeDateFromString */
1278 
1279 
1280 /*----------------------------------------------------------------------*/
1281 
1282 TIM_STATUS_TYPE
TimMakeDateFromIsoString(TIM_TIME_REF * time,char * string)1283   TimMakeDateFromIsoString( TIM_TIME_REF  *time,
1284                             char          *string )
1285 {
1286 
1287   /* Variables. */
1288   TIM_STATUS_TYPE  status;
1289 
1290 
1291   /* Code. */
1292 
1293   status = makeDateFromString( &iso_date_format, time, string );
1294 
1295 
1296   return( status );
1297 
1298 } /* TimMakeDateFromIsoString */
1299 
1300 
1301 /*----------------------------------------------------------------------*/
1302 
1303 TIM_STATUS_TYPE
TimMakeTimeFromString(TIM_TIME_REF * time,char * string)1304   TimMakeTimeFromString( TIM_TIME_REF  *time,
1305                          char          *string )
1306 {
1307 
1308   /* Variables. */
1309   TIM_STATUS_TYPE  status;
1310 
1311 
1312   /* Code. */
1313 
1314   status = makeTimeFromString( &user_time_format, time, string );
1315 
1316 
1317   return( status );
1318 
1319 } /* TimMakeTimeFromString */
1320 
1321 
1322 /*----------------------------------------------------------------------*/
1323 
1324 TIM_STATUS_TYPE
TimMakeTimeFromIsoString(TIM_TIME_REF * time,char * string)1325   TimMakeTimeFromIsoString( TIM_TIME_REF  *time,
1326                             char          *string )
1327 {
1328 
1329   /* Variables. */
1330   TIM_STATUS_TYPE  status;
1331 
1332 
1333   /* Code. */
1334 
1335   status = makeTimeFromString( &iso_time_format, time, string );
1336 
1337 
1338   return( status );
1339 
1340 } /* TimMakeTimeFromIsoString */
1341 
1342 
1343 /*----------------------------------------------------------------------*/
1344 
1345 TIM_TIME_REF
TimMakeTimeNow()1346   TimMakeTimeNow()
1347 {
1348 
1349   /* Code. */
1350 
1351   return( (TIM_TIME_REF) time( NULL ) );
1352 
1353 } /* TimMakeTimeNow */
1354 
1355 
1356 /*----------------------------------------------------------------------*/
1357 
1358 TIM_STATUS_TYPE
TimMakeTimeFromWeek(int year,int week_number,TIM_TIME_REF * time)1359   TimMakeTimeFromWeek( int           year,
1360                        int           week_number,
1361                        TIM_TIME_REF  *time )
1362 {
1363 
1364   /* Variables. */
1365   TIM_TIME_REF  new_time;
1366 
1367 
1368   /* Code. */
1369 
1370   new_time = TimMakeTime( year, 1, 1, 0, 0, 0 );
1371 
1372   TimAddDays( &new_time, (week_number - 2) * 7 );
1373 
1374   while( TimIndexOfWeek( new_time ) != week_number )
1375     TimAddDays( &new_time, 1 );
1376 
1377   *time = new_time;
1378 
1379 
1380   return( TIM_OK );
1381 
1382 } /* TimMakeTimeFromWeek */
1383 
1384 
1385 /*----------------------------------------------------------------------*/
1386 
1387 int
TimMinute(TIM_TIME_REF time)1388   TimMinute( TIM_TIME_REF  time )
1389 {
1390 
1391   /* Variables. */
1392   struct tm  *time_struct;
1393   struct tm  time_struct_obj;
1394 
1395 
1396   /* Code. */
1397 
1398   time_struct = convertToStruct( time, &time_struct_obj );
1399 
1400 
1401   return( time_struct -> tm_min );
1402 
1403 } /* TimMinute */
1404 
1405 
1406 /*----------------------------------------------------------------------*/
1407 
1408 void
TimNextDay(TIM_TIME_REF * time,TIM_DAY_TYPE time_of_day)1409   TimNextDay( TIM_TIME_REF  *time,
1410               TIM_DAY_TYPE  time_of_day )
1411 {
1412 
1413   /* Variables. */
1414   struct tm  *time_struct;
1415   struct tm  time_struct_obj;
1416 
1417 
1418   /* Code. */
1419 
1420   TimAddDays( time, 1 );
1421 
1422   time_struct = convertToStruct( *time, &time_struct_obj );
1423 
1424   /* Set to a specific time of the day. */
1425   switch( time_of_day ) {
1426     case TIM_NOON:
1427       time_struct -> tm_hour = 12;
1428       time_struct -> tm_min  = 0;
1429       time_struct -> tm_sec  = 0;
1430 
1431       *time = (TIM_TIME_REF) secondsSince1970( time_struct );
1432       break;
1433 
1434     case TIM_MIDNIGHT:
1435       time_struct -> tm_hour = 0;
1436       time_struct -> tm_min  = 0;
1437       time_struct -> tm_sec  = 0;
1438 
1439       *time = (TIM_TIME_REF) secondsSince1970( time_struct );
1440       break;
1441 
1442     default:
1443       break;
1444 
1445   } /* switch */
1446 
1447 
1448   return;
1449 
1450 } /* TimNextDay */
1451 
1452 
1453 /*----------------------------------------------------------------------*/
1454 
1455 void
TimNextMonth(TIM_TIME_REF * time,TIM_MONTH_TYPE day_in_month)1456   TimNextMonth( TIM_TIME_REF    *time,
1457                 TIM_MONTH_TYPE  day_in_month )
1458 {
1459 
1460   /* Variables. */
1461   TIM_TIME_REF  new_time;
1462 
1463 
1464   /* Code. */
1465 
1466   /* The end of this month. */
1467   new_time = TimMakeTime( TimIndexOfYear(  *time ),
1468                           TimIndexOfMonth( *time ),
1469                           TimDaysInMonth(  *time ),
1470                           0, 0, 0 );
1471 
1472   /* Add days so that we move to the next month. */
1473   TimAddDays( &new_time, 1 );
1474 
1475   /* Which part of the month? */
1476   switch( day_in_month ) {
1477 
1478     case TIM_START_MONTH:
1479       break;
1480 
1481     case TIM_END_MONTH:
1482       new_time = TimMakeTime( TimIndexOfYear(  new_time ),
1483                               TimIndexOfMonth( new_time ),
1484                               TimDaysInMonth(  new_time ),
1485                               0, 0, 0 );
1486       break;
1487 
1488   } /* switch */
1489 
1490   *time = new_time;
1491 
1492 
1493   return;
1494 
1495 } /* TimNextMonth */
1496 
1497 
1498 /*----------------------------------------------------------------------*/
1499 
1500 void
TimPreviousDay(TIM_TIME_REF * time,TIM_DAY_TYPE time_of_day)1501   TimPreviousDay( TIM_TIME_REF  *time,
1502                   TIM_DAY_TYPE  time_of_day )
1503 {
1504 
1505   /* Variables. */
1506   struct tm  *time_struct;
1507   struct tm  time_struct_obj;
1508 
1509 
1510   /* Code. */
1511 
1512   TimAddDays( time, -1 );
1513 
1514   time_struct = convertToStruct( *time, &time_struct_obj );
1515 
1516   /* Set to a specific time of the day. */
1517   switch( time_of_day ) {
1518     case TIM_NOON:
1519       time_struct -> tm_hour = 12;
1520       time_struct -> tm_min  = 0;
1521       time_struct -> tm_sec  = 0;
1522 
1523       *time = (TIM_TIME_REF) secondsSince1970( time_struct );
1524       break;
1525 
1526     case TIM_MIDNIGHT:
1527       time_struct -> tm_hour = 0;
1528       time_struct -> tm_min  = 0;
1529       time_struct -> tm_sec  = 0;
1530 
1531       *time = (TIM_TIME_REF) secondsSince1970( time_struct );
1532       break;
1533 
1534     default:
1535       break;
1536 
1537   } /* switch */
1538 
1539 
1540   return;
1541 
1542 } /* TimPreviousDay */
1543 
1544 
1545 /*----------------------------------------------------------------------*/
1546 
1547 void
TimPreviousMonth(TIM_TIME_REF * time,TIM_MONTH_TYPE day_in_month)1548   TimPreviousMonth( TIM_TIME_REF    *time,
1549                     TIM_MONTH_TYPE  day_in_month )
1550 {
1551 
1552   /* Variables. */
1553   TIM_TIME_REF  new_time;
1554 
1555 
1556   /* Code. */
1557 
1558   /* The first in this month. */
1559   new_time = TimMakeTime( TimIndexOfYear(  *time ),
1560                           TimIndexOfMonth( *time ),
1561                           1, 0, 0, 0 );
1562 
1563   /* Add days so that we move to the end of next month. */
1564   TimAddDays( &new_time, -1 );
1565 
1566   /* Which part of the month? */
1567   switch( day_in_month ) {
1568 
1569     case TIM_START_MONTH:
1570       new_time = TimMakeTime( TimIndexOfYear(  new_time ),
1571                               TimIndexOfMonth( new_time ),
1572                               1, 0, 0, 0 );
1573       break;
1574 
1575     case TIM_END_MONTH:
1576       break;
1577 
1578   } /* switch */
1579 
1580   *time = new_time;
1581 
1582 
1583   return;
1584 
1585 } /* TimPreviousMonth */
1586 
1587 
1588 /*----------------------------------------------------------------------*/
1589 
1590 int
TimSecond(TIM_TIME_REF time)1591   TimSecond( TIM_TIME_REF  time )
1592 {
1593 
1594   /* Variables. */
1595   struct tm  *time_struct;
1596   struct tm  time_struct_obj;
1597 
1598 
1599   /* Code. */
1600 
1601   time_struct = convertToStruct( time, &time_struct_obj );
1602 
1603 
1604   return( time_struct -> tm_sec );
1605 
1606 } /* TimSecond */
1607 
1608 
1609 /*----------------------------------------------------------------------*/
1610 
1611 void
TimSetUnixWeekNo(Boolean use_unix_week_no)1612   TimSetUnixWeekNo( Boolean  use_unix_week_no )
1613 {
1614 
1615   /* Code. */
1616 
1617   unix_week_no = use_unix_week_no;
1618 
1619 
1620   return;
1621 
1622 } /* TimSetUnixWeekNo */
1623 
1624 
1625 /*----------------------------------------------------------------------*/
1626 
1627 TIM_STATUS_TYPE
TimTimeInSecondsRange(TIM_TIME_REF master,TIM_TIME_REF check,int seconds_range)1628   TimTimeInSecondsRange( TIM_TIME_REF  master,
1629                          TIM_TIME_REF  check,
1630                          int           seconds_range )
1631 {
1632 
1633   /* Code. */
1634   if( abs( master - check ) <= (seconds_range / 2) )
1635     return( TIM_YES );
1636 
1637 
1638   return( TIM_NO );
1639 
1640 } /* TimTimeInSecondsRange */
1641 
1642 
1643 /*----------------------------------------------------------------------*/
1644 
1645 char
TimWhatDateFormat()1646   *TimWhatDateFormat()
1647 {
1648 
1649   /* Code. */
1650 
1651   return( date_format_string );
1652 
1653 } /* TimWhatDateFormat */
1654 
1655 
1656 /*----------------------------------------------------------------------*/
1657 
1658 char
TimWhatTimeFormat()1659   *TimWhatTimeFormat()
1660 {
1661 
1662   /* Code. */
1663 
1664   return( time_format_string );
1665 
1666 } /* TimWhatTimeFormat */
1667 
1668 
1669 /*----------------------------------------------------------------------*/
1670 
1671 static struct tm
convertToLocalStruct(TIM_TIME_REF time,struct tm * container)1672   *convertToLocalStruct( TIM_TIME_REF  time,
1673                          struct tm     *container )
1674 {
1675 
1676   /* Variables. */
1677   struct tm  *ref;
1678 
1679 
1680   /* Code. */
1681 
1682   ref = localtime( (time_t *) &time );
1683 
1684   memcpy( container, ref, sizeof( struct tm ) );
1685 
1686 
1687   return( container );
1688 
1689 } /* convertToLocalStruct */
1690 
1691 
1692 /*----------------------------------------------------------------------*/
1693 
1694 static struct tm
convertToStruct(TIM_TIME_REF time,struct tm * container)1695   *convertToStruct( TIM_TIME_REF  time,
1696                     struct tm     *container )
1697 {
1698 
1699   /* Variables. */
1700   struct tm  *ref;
1701 
1702 
1703   /* Code. */
1704 
1705   ref = gmtime( (time_t *) &time );
1706 
1707   memcpy( container, ref, sizeof( struct tm ) );
1708 
1709 
1710   return( container );
1711 
1712 } /* convertToStruct */
1713 
1714 
1715 /*----------------------------------------------------------------------*/
1716 
1717 static int
dayNumberInYear(int year,int month,int day)1718   dayNumberInYear( int year,
1719                    int month,
1720                    int day )
1721 {
1722 
1723   /* Code. */
1724 
1725   if( daysInYear( year ) == 366 )
1726     return( day_offset_leap_year[ month - 1 ] + day );
1727 
1728 
1729   return( day_offset[ month - 1 ] + day );
1730 
1731 } /* dayNumberInYear */
1732 
1733 
1734 /*----------------------------------------------------------------------*/
1735 
1736 static int
daysInYear(int year)1737   daysInYear( int  year )
1738 {
1739 
1740   /* Code. */
1741 
1742   if( year % 4 == 0 )
1743     return( 366 );
1744 
1745 
1746   return( 365 );
1747 
1748 } /* daysInYear */
1749 
1750 
1751 /*----------------------------------------------------------------------*/
1752 
1753 static void
formatDate(DATE_FORMAT * date_format,TIM_TIME_REF time,char * buffer,int buffer_size)1754   formatDate( DATE_FORMAT   *date_format,
1755               TIM_TIME_REF  time,
1756               char          *buffer,
1757               int           buffer_size )
1758 {
1759 
1760   /* Variables. */
1761   char       day[ 10 ];
1762   char       month[ 10 ];
1763   char       year[ 10 ];
1764   struct tm  *time_struct;
1765   struct tm  time_struct_obj;
1766 
1767 
1768   /* Code. */
1769 
1770   if( buffer_size < 11 ) {
1771     *buffer = '\0';
1772     return;
1773   }
1774 
1775   time_struct = convertToStruct( time, &time_struct_obj );
1776 
1777   /* Year. */
1778   if( date_format -> include_century )
1779     (void) strftime( year, sizeof( year ), "%Y", time_struct );
1780   else
1781     (void) strftime( year, sizeof( year ), "%y", time_struct );
1782 
1783   /* Month. */
1784   (void) strftime( month, sizeof( month ), "%m", time_struct );
1785   if( ! date_format -> month_leading_zero && month[ 0 ] == '0' ) {
1786     month[ 0 ] = month[ 1 ];
1787     month[ 1 ] = '\0';
1788   }
1789 
1790   /* Day. */
1791   (void) strftime( day, sizeof( day ), "%d", time_struct );
1792   if( ! date_format -> day_leading_zero && day[ 0 ] == '0' ) {
1793     day[ 0 ] = day[ 1 ];
1794     day[ 1 ] = '\0';
1795   }
1796 
1797   /* Build the date. */
1798   if( date_format -> order == DATE_MMDDYY )
1799     sprintf( buffer, "%s%s%s%s%s",
1800              month, date_format -> separator,
1801              day, date_format -> separator,
1802              year );
1803   else if( date_format -> order == DATE_DDMMYY )
1804     sprintf( buffer, "%s%s%s%s%s",
1805              day, date_format -> separator,
1806              month, date_format -> separator,
1807              year );
1808   else
1809     sprintf( buffer, "%s%s%s%s%s",
1810              year, date_format -> separator,
1811              month, date_format -> separator,
1812              day );
1813 
1814 
1815   return;
1816 
1817 } /* formatDate */
1818 
1819 
1820 /*----------------------------------------------------------------------*/
1821 
1822 static void
formatFullDate(DATE_FORMAT * date_format,TIM_TIME_REF time,char * buffer,int buffer_size)1823   formatFullDate( DATE_FORMAT   *date_format,
1824                   TIM_TIME_REF  time,
1825                   char          *buffer,
1826                   int           buffer_size )
1827 {
1828 
1829   /* Variables. */
1830   char       day[ 10 ];
1831   char       month[ 10 ];
1832   char       year[ 10 ];
1833   struct tm  *time_struct;
1834   struct tm  time_struct_obj;
1835 
1836 
1837   /* Code. */
1838 
1839   if( buffer_size < 30 ) {
1840     *buffer = '\0';
1841     return;
1842   }
1843 
1844   time_struct = convertToStruct( time, &time_struct_obj );
1845 
1846   /* Year. */
1847   (void) strftime( year, sizeof( year ), "%Y", time_struct );
1848 
1849   /* Month. */
1850   (void) strftime( month, sizeof( month ), "%B", time_struct );
1851 
1852   /* Day. */
1853   (void) strftime( day, sizeof( day ), "%d", time_struct );
1854   if( day[ 0 ] == '0' ) {
1855     day[ 0 ] = day[ 1 ];
1856     day[ 1 ] = '\0';
1857   }
1858 
1859   /* Build the date. */
1860   if( date_format -> order == DATE_MMDDYY )
1861     sprintf( buffer, "%s %s, %s", month, day, year );
1862   else if( date_format -> order == DATE_DDMMYY )
1863     sprintf( buffer, "%s. %s %s", day, month, year );
1864   else
1865     sprintf( buffer, "%s. %s %s", day, month, year );
1866 
1867 
1868   return;
1869 
1870 } /* formatFullDate */
1871 
1872 
1873 /*----------------------------------------------------------------------*/
1874 
1875 static void
formatTime(TIME_FORMAT * time_format,TIM_TIME_REF time,char * buffer,int buffer_size)1876   formatTime( TIME_FORMAT   *time_format,
1877               TIM_TIME_REF  time,
1878               char          *buffer,
1879               int           buffer_size )
1880 {
1881 
1882   /* Variables. */
1883   char       hour[ 10 ];
1884   char       minute[ 10 ];
1885   struct tm  *time_struct;
1886   struct tm  time_struct_obj;
1887 
1888 
1889   /* Code. */
1890 
1891   if( buffer_size < 9 ) {
1892     *buffer = '\0';
1893     return;
1894   }
1895 
1896   time_struct = convertToStruct( time, &time_struct_obj );
1897 
1898   /* Hour. */
1899   if( time_format -> hour_12 )
1900     (void) strftime( hour, sizeof( hour ), "%I", time_struct );
1901   else
1902     (void) strftime( hour, sizeof( hour ), "%H", time_struct );
1903 
1904   if( ! time_format -> hour_leading_zero && hour[ 0 ] == '0' ) {
1905     hour[ 0 ] = hour[ 1 ];
1906     hour[ 1 ] = '\0';
1907   }
1908 
1909   /* Minute. */
1910   (void) strftime( minute, sizeof( minute ), "%M", time_struct );
1911 
1912   /* Build the time. */
1913   if( TimHour( time ) > 11 )
1914     sprintf( buffer, "%s%s%s%s%s",
1915              hour, time_format -> separator,
1916              minute, time_format -> hour_24_suffix_separator,
1917              time_format -> hour_24_suffix );
1918   else
1919     sprintf( buffer, "%s%s%s%s%s",
1920              hour, time_format -> separator,
1921              minute, time_format -> hour_12_suffix_separator,
1922              time_format -> hour_12_suffix );
1923 
1924 
1925   return;
1926 
1927 } /* formatTime */
1928 
1929 
1930 /*----------------------------------------------------------------------*/
1931 
1932 static TIM_STATUS_TYPE
isTimeOk(int year,int month,int day,int hour,int minute,int second)1933   isTimeOk( int  year,
1934             int  month,
1935             int  day,
1936             int  hour,
1937             int  minute,
1938             int  second )
1939 {
1940 
1941   /* Variables. */
1942   TIM_TIME_REF  time;
1943 
1944 
1945   /* Code. */
1946 
1947   /* The easy check. */
1948 #ifdef NO_RXTN
1949   if( year < 1900 )
1950     year = year + 1900;
1951 #else
1952   if ( year < 1970 ) {
1953     if ( year >= 70 && year < 100 )
1954       year += 1900;
1955     else
1956       if ( year <= 30 )
1957 	year += 2000;
1958       else
1959 	return TIM_ERROR;
1960     }
1961   else
1962     if ( year > 2030 )
1963       return TIM_ERROR;
1964 #endif
1965 
1966   if( year   < 1970 || year   > 2100 ||
1967       month  < 1    || month  > 12 ||
1968       day    < 1    || day    > 31 ||
1969       hour   < 0    || hour   > 23 ||
1970       minute < 0    || minute > 59 ||
1971       second < 0    || second > 59 )
1972     return( TIM_ERROR );
1973 
1974   time = TimMakeTime( year, month, 1, 0, 0, 0 );
1975 
1976   if( day > TimDaysInMonth( time ) )
1977     return( TIM_ERROR );
1978 
1979 
1980   return( TIM_OK );
1981 
1982 } /* isTimeOk */
1983 
1984 
1985 /*----------------------------------------------------------------------*/
1986 
1987 static TIM_STATUS_TYPE
makeDateFromString(DATE_FORMAT * date_format,TIM_TIME_REF * time,char * string)1988   makeDateFromString( DATE_FORMAT   *date_format,
1989                       TIM_TIME_REF  *time,
1990                       char          *string )
1991 {
1992 
1993   /* Variables. */
1994   Boolean  has_match = False;
1995   int      day = 1;
1996   int      matches;
1997   int      month = 1;
1998   int      par1;
1999   int      par2;
2000   int      par3;
2001   int      year = 1970;
2002 
2003   struct tm  *time_struct;
2004   struct tm  time_struct_obj;
2005 
2006 
2007   /* Code. */
2008 
2009   *time = TimLocalTime( TimMakeTimeNow() );
2010 
2011   time_struct = convertToStruct( *time, &time_struct_obj );
2012 
2013   time_struct -> tm_hour = 0;
2014   time_struct -> tm_min  = 0;
2015   time_struct -> tm_sec  = 0;
2016 
2017 
2018   /* Three parameters? */
2019   if( ! has_match ) {
2020     matches = sscanf( string, date_format -> ymd_format,
2021                       &par1, &par2, &par3 );
2022     if( matches == 3 )
2023       has_match = True;
2024   }
2025 
2026   /* Two parameters? */
2027   if( ! has_match ) {
2028     matches = sscanf( string, date_format -> md_format,
2029                       &par1, &par2 );
2030     if( matches == 2 )
2031       has_match = True;
2032   }
2033 
2034   /* One parameters? */
2035   if( ! has_match ) {
2036     matches = sscanf( string, date_format -> d_format,
2037                       &par1 );
2038     if( matches == 1 )
2039       has_match = True;
2040   }
2041 
2042   /* Any matches? */
2043   if( ! has_match )
2044     return( TIM_ERROR );
2045 
2046   /* MMDDYY format. */
2047   if( date_format -> order == DATE_MMDDYY ) {
2048     if( matches == 3 ) {
2049       year  = par3;
2050       month = par1;
2051       day   = par2;
2052     } else if( matches == 2 ) {
2053       year  = time_struct -> tm_year;
2054       month = par1;
2055       day   = par2;
2056     } else {
2057       year  = time_struct -> tm_year;
2058       month = time_struct -> tm_mon + 1;
2059       day   = par1;
2060     }
2061   }
2062 
2063   /* DDMMYY format. */
2064   if( date_format -> order == DATE_DDMMYY ) {
2065     if( matches == 3 ) {
2066       year  = par3;
2067       month = par2;
2068       day   = par1;
2069     } else if( matches == 2 ) {
2070       year  = time_struct -> tm_year;
2071       month = par2;
2072       day   = par1;
2073     } else {
2074       year  = time_struct -> tm_year;
2075       month = time_struct -> tm_mon + 1;
2076       day   = par1;
2077     }
2078   }
2079 
2080   /* YYMMDD format. */
2081   if( date_format -> order == DATE_YYMMDD ) {
2082     if( matches == 3 ) {
2083       year  = par1;
2084       month = par2;
2085       day   = par3;
2086     } else if( matches == 2 ) {
2087       year  = time_struct -> tm_year;
2088       month = par1;
2089       day   = par2;
2090     } else {
2091       year  = time_struct -> tm_year;
2092       month = time_struct -> tm_mon + 1;
2093       day   = par1;
2094     }
2095   }
2096 
2097 
2098   /* Check the time. */
2099   if( isTimeOk( year, month, day, 0, 0, 0 ) != TIM_OK )
2100     return( TIM_ERROR );
2101 
2102   /* Build the time. */
2103   if( year < 1000 )
2104     time_struct -> tm_year  = year;
2105   else
2106     time_struct -> tm_year  = year - 1900;
2107 
2108   time_struct -> tm_mon  = month - 1;
2109   time_struct -> tm_mday = day;
2110   time_struct -> tm_yday = dayNumberInYear( year, month, day ) - 1;
2111 
2112   time_struct -> tm_hour = 0;
2113   time_struct -> tm_min  = 0;
2114   time_struct -> tm_sec  = 0;
2115 
2116   *time = secondsSince1970( time_struct );
2117 
2118 
2119   return( TIM_OK );
2120 
2121 } /* makeDateFromString */
2122 
2123 
2124 /*----------------------------------------------------------------------*/
2125 
2126 static TIM_STATUS_TYPE
makeTimeFromString(TIME_FORMAT * time_format,TIM_TIME_REF * time,char * string)2127   makeTimeFromString( TIME_FORMAT   *time_format,
2128                       TIM_TIME_REF  *time,
2129                       char          *string )
2130 {
2131 
2132   /* Variables. */
2133   Boolean  before_12 = False;
2134   Boolean  has_match = False;
2135   int      hour;
2136   int      matches;
2137   int      minute;
2138   int      par1;
2139   int      par2;
2140   char     suffix[ 50 ];
2141 
2142   struct tm  *time_struct;
2143   struct tm  time_struct_obj;
2144 
2145 
2146   /* Code. */
2147 
2148   *time = TimLocalTime( TimMakeTimeNow() );
2149 
2150   time_struct = convertToStruct( *time, &time_struct_obj );
2151 
2152   hour   = time_struct -> tm_hour;
2153   minute = time_struct -> tm_min;
2154 
2155 
2156   /* Two parameters? */
2157   if( ! has_match ) {
2158     if( time_format -> hour_12 ) {
2159       matches = sscanf( string, time_format -> hm_format,
2160                         &par1, &par2, suffix );
2161       if( matches == 3 )
2162         has_match = True;
2163     } else {
2164       matches = sscanf( string, time_format -> hm_format,
2165                         &par1, &par2 );
2166       if( matches == 2 )
2167         has_match = True;
2168     }
2169   }
2170 
2171   /* One parameter? */
2172   if( ! has_match ) {
2173     if( time_format -> hour_12 ) {
2174       matches = sscanf( string, time_format -> hm_format,
2175                         &par1, suffix );
2176       if( matches == 2 )
2177         has_match = True;
2178     } else {
2179       matches = sscanf( string, time_format -> hm_format,
2180                         &par1 );
2181       if( matches == 1 )
2182         has_match = True;
2183     }
2184   }
2185 
2186   /* Any matches? */
2187   if( ! has_match )
2188     return( TIM_ERROR );
2189 
2190   /* 12-hour suffix? */
2191   if( time_format -> hour_12 && matches == 3 ) {
2192     if( noCaseStrcmp( suffix, time_format -> hour_12_suffix ) == 0 )
2193       before_12 = True;
2194     else if( noCaseStrcmp( suffix, time_format -> hour_24_suffix ) == 0 )
2195       before_12 = False;
2196     else
2197       return( TIM_ERROR );
2198   }
2199 
2200 
2201   /* Build the time. */
2202   if( time_format -> hour_12 ) {
2203     if( matches == 3 ) {
2204       hour   = par1;
2205       minute = par2;
2206 
2207       /* 12 AM = 0:00, 12 PM = 12:00. */
2208       if( ! before_12 && hour != 12 )
2209         hour = hour + 12;
2210       else if( before_12 && hour == 12 )
2211         hour = 0;
2212 
2213     } else {
2214       minute = par1;
2215     }
2216   }
2217 
2218   if( ! time_format -> hour_12 ) {
2219     if( matches == 2 ) {
2220       hour   = par1;
2221       minute = par2;
2222     } else {
2223       minute = par1;
2224     }
2225   }
2226 
2227 
2228   /* Check the time. */
2229   if( isTimeOk( 1970, 1, 1, hour, minute, 0 ) != TIM_OK )
2230     return( TIM_ERROR );
2231 
2232   time_struct -> tm_year = 70;
2233   time_struct -> tm_mon  = 0;
2234   time_struct -> tm_mday = 1;
2235   time_struct -> tm_yday = 0;
2236 
2237   time_struct -> tm_hour = hour;
2238   time_struct -> tm_min  = minute;
2239   time_struct -> tm_sec  = 0;
2240 
2241   *time = secondsSince1970( time_struct );
2242 
2243 
2244   return( TIM_OK );
2245 
2246 } /* makeTimeFromString */
2247 
2248 
2249 /*----------------------------------------------------------------------*/
2250 
2251 static int
noCaseStrcmp(char * buffer1,char * buffer2)2252   noCaseStrcmp( char  *buffer1,
2253                 char  *buffer2 )
2254 {
2255 
2256   /* Variables. */
2257   char  *char_ref1;
2258   char  *char_ref2;
2259 
2260 
2261   /* Code. */
2262 
2263   if( strlen( buffer1 ) != strlen( buffer2 ) )
2264     return( strcmp( buffer1, buffer2 ) );
2265 
2266   char_ref1 = buffer1;
2267   char_ref2 = buffer2;
2268 
2269   while( *char_ref1 != '\0' ) {
2270     if( tolower( *char_ref1 ) < tolower( *char_ref2 ) )
2271       return( -1 );
2272     else if( tolower( *char_ref1 ) > tolower( *char_ref2 ) )
2273       return( 1 );
2274 
2275     char_ref1++;
2276     char_ref2++;
2277   }
2278 
2279 
2280   return( 0 );
2281 
2282 } /* noCaseStrcmp */
2283 
2284 
2285 /*----------------------------------------------------------------------*/
2286 
2287 static time_t
secondsSince1970(struct tm * time_ref)2288   secondsSince1970( struct tm *time_ref )
2289 {
2290 
2291   /* Variables. */
2292   int     index;
2293   time_t  seconds = 0;
2294 
2295 
2296   /* Code. */
2297 
2298   if( time_ref -> tm_year < 70 )
2299     return( 0 );
2300 
2301   for( index = 70 + 1900; index < time_ref -> tm_year + 1900; index++ )
2302     seconds = seconds + (daysInYear( index ) * 86400);
2303 
2304   seconds = seconds + time_ref -> tm_yday * 86400;
2305   seconds = seconds + time_ref -> tm_hour * 3600;
2306   seconds = seconds + time_ref -> tm_min  * 60;
2307   seconds = seconds + time_ref -> tm_sec;
2308 
2309 
2310   return( seconds );
2311 
2312 } /* secondsSince1970 */
2313