48 #define MJD_0000J -678943
53 #define MJD_0000G -678941
56 #define MJD_0001J -678577
57 #define MJD_0001G -678575
59 #define MJD_1970 40587
62 static const int MonthStartDOY[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
63 static const int MonthStartDOY_L[] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
71 int setFromUT(
int year,
int month,
int day,
int hour,
int min,
double sec,
MJDtime *MJD,
int forceJulian )
83 int leaps, year4, year100, year400;
84 double dbase_day, non_leaps = 365.;
86 double time_sec, dextraDays;
89 if ( month < 0 || month > 11 )
91 fprintf( stderr,
"setfromUT: invalid month value\n" );
103 year100 = year - 100;
104 year400 = year - 400;
129 leaps = year4 / 4 - year100 / 100 + year400 / 400;
138 if ( ( year % 4 == 0 && year % 100 != 0 ) || ( year % 4 == 0 && year % 400 == 0 ) )
144 time_sec = sec + ( (double) min + (
double) hour * 60. ) * 60.;
148 dextraDays = ( time_sec /
SecInDay );
150 if ( fabs( dextraDays ) > 2.e9 )
154 extraDays = (int) ( dextraDays );
155 dbase_day += extraDays;
159 if ( fabs( dbase_day ) > 2.e9 )
175 void getYAD(
int *year,
int *ifleapyear,
int *doy,
const MJDtime *MJD,
int forceJulian )
179 int j, ifcorrect, year4, year100, year400;
194 *year = (int) ( (
double) ( j ) / 365.25 );
199 *year = (int) ( (
double) ( j - 365 ) / 365.25 );
203 *doy = j - *year * 365 - year4 / 4;
205 *ifleapyear = *year % 4 == 0;
218 *year = (int) ( (
double) ( j ) / 365.2425 );
225 *year = (int) ( (
double) ( j - 365 ) / 365.2425 );
227 year100 = *year - 100;
228 year400 = *year - 400;
231 *doy = j - *year * 365 - year4 / 4 + year100 / 100 - year400 / 400;
232 *ifleapyear = ( *year % 4 == 0 && *year % 100 != 0 ) || ( *year % 4 == 0 && *year % 400 == 0 );
240 else if ( *doy > 365 && ( !*ifleapyear || *doy > 366 ) )
260 year100 = *year - 100;
261 year400 = *year - 400;
264 *doy = j - *year * 365 - year4 / 4 + year100 / 100 - year400 / 400;
265 *ifleapyear = ( *year % 4 == 0 && *year % 100 != 0 ) || ( *year % 4 == 0 && *year % 400 == 0 );
289 void breakDownMJD(
int *year,
int *month,
int *day,
int *hour,
int *
min,
double *sec,
const MJDtime *MJD,
int forceJulian )
295 MJDtime nMJD_value, *nMJD = &nMJD_value;
302 *hour = (int) ( *sec / 3600. );
303 *sec -= (double) *hour * 3600.;
304 *min = (int) ( *sec / 60. );
305 *sec -= (double) *min * 60.;
307 getYAD( year, &ifleapyear, &doy, nMJD, forceJulian );
336 static const char *dow = {
"Wed\0Thu\0Fri\0Sat\0Sun\0Mon\0Tue" };
340 return &( dow[d * 4] );
345 static const char *dow = {
"Wednesday\0Thursday\0\0Friday\0\0\0\0Saturday\0\0Sunday\0\0\0\0Monday\0\0\0\0Tuesday" };
349 return &( dow[d * 10] );
354 static const char *months = {
"Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec" };
355 return &( months[( m ) * 4] );
360 static const char *months = {
"January\0\0\0February\0\0March\0\0\0\0\0April\0\0\0\0\0May\0\0\0\0\0\0\0June\0\0\0\0\0\0July\0\0\0\0\0\0August\0\0\0\0September\0October\0\0\0November\0\0December" };
361 return &( months[( m ) * 10] );
365 size_t strfMJD(
char *
buf,
size_t len,
const char *format,
const MJDtime *MJD,
int forceJulian,
int inleap )
377 int year, month, day, hour,
min, ysign, second, d, y;
379 int i, secsSince1970;
380 int nplaces, fmtlen, slen;
384 double sec, sec_fraction;
385 int w, doy, days_in_wk1;
387 const char *monthText;
390 size_t last = len - 1;
391 MJDtime nMJD_value, *nMJD = &nMJD_value;
392 char dynamic_format[10];
396 fmtlen = (int) strlen( format );
400 char next = format[i];
406 if ( isdigit( next ) != 0 )
408 nplaces = (int) strtol( &( format[i] ), NULL, 10 );
409 if ( nplaces > resolution )
410 resolution = nplaces;
412 else if ( next ==
'.' )
421 shiftPlaces = pow( 10, (
double) resolution );
423 nMJD->
time_sec += 0.5 / shiftPlaces;
431 breakDownMJD( &year, &month, &day, &hour, &min, &sec, nMJD, forceJulian );
444 sec = floor( sec * shiftPlaces ) / shiftPlaces;
451 char next = format[i];
465 else if ( next ==
'a' )
469 strncat( &( buf[posn] ), dayText, last - posn );
470 posn = strlen( buf );
474 else if ( next ==
'A' )
478 strncat( &( buf[posn] ), dayText, last - posn );
479 posn = strlen( buf );
483 else if ( next ==
'b' || next ==
'h' )
487 strncat( &( buf[posn] ), monthText, last - posn );
488 posn = strlen( buf );
492 else if ( next ==
'B' )
496 strncat( &( buf[posn] ), monthText, last - posn );
497 posn = strlen( buf );
501 else if ( next ==
'c' )
507 sprintf( DateTime,
"%s %s %02d %02d:%02d:%02d %04d", dayText, monthText, day, hour, min, second, year );
509 sprintf( DateTime,
"%s %s %02d %02d:%02d:%02d -%04d", dayText, monthText, day, hour, min, second, year );
511 strncat( &( buf[posn] ), DateTime, last - posn );
512 posn = strlen( buf );
516 else if ( next ==
'C' )
519 int century = year / 100;
521 sprintf( DateTime,
"%02d", century );
523 sprintf( DateTime,
"-%02d", century + 1 );
525 strncat( &( buf[posn] ), DateTime, last - posn );
526 posn = strlen( buf );
530 else if ( next ==
'd' )
533 sprintf( DateTime,
"%02d", day );
535 strncat( &( buf[posn] ), DateTime, last - posn );
536 posn = strlen( buf );
540 else if ( next ==
'D' )
545 sprintf( DateTime,
"%02d/%02d/%02d", month + 1, day, y );
547 sprintf( DateTime,
"%02d/%02d/-%02d", month + 1, day, y );
549 strncat( &( buf[posn] ), DateTime, last - posn );
550 posn = strlen( buf );
554 else if ( next ==
'e' )
558 sprintf( DateTime,
" %01d", day );
560 sprintf( DateTime,
"%02d", day );
562 strncat( &( buf[posn] ), DateTime, last - posn );
563 posn = strlen( buf );
567 else if ( next ==
'F' )
571 sprintf( DateTime,
"%04d-%02d-%02d", year, month + 1, day );
573 sprintf( DateTime,
"-%04d-%02d-%02d", year, month + 1, day );
575 strncat( &( buf[posn] ), DateTime, last - posn );
576 posn = strlen( buf );
580 else if ( next ==
'H' )
583 sprintf( DateTime,
"%02d", hour );
585 strncat( &( buf[posn] ), DateTime, last - posn );
586 posn = strlen( buf );
590 else if ( next ==
'I' )
594 sprintf( DateTime,
"%02d", hour + 12 );
595 else if ( hour > 12 )
596 sprintf( DateTime,
"%02d", hour - 12 );
598 sprintf( DateTime,
"%02d", hour );
600 strncat( &( buf[posn] ), DateTime, last - posn );
601 posn = strlen( buf );
605 else if ( next ==
'j' )
608 getYAD( &y1, &ifleapyear, &doy, nMJD, forceJulian );
609 sprintf( DateTime,
"%03d", doy );
611 strncat( &( buf[posn] ), DateTime, last - posn );
612 posn = strlen( buf );
616 else if ( next ==
'k' )
620 sprintf( DateTime,
" %01d", hour );
622 sprintf( DateTime,
"%02d", hour );
624 strncat( &( buf[posn] ), DateTime, last - posn );
625 posn = strlen( buf );
629 else if ( next ==
'l' )
633 sprintf( DateTime,
"%02d", hour + 12 );
634 else if ( hour < 10 )
635 sprintf( DateTime,
" %01d", hour );
636 else if ( hour <= 12 )
637 sprintf( DateTime,
"%02d", hour );
638 else if ( hour < 22 )
639 sprintf( DateTime,
" %01d", hour - 12 );
641 sprintf( DateTime,
"%02d", hour - 12 );
643 strncat( &( buf[posn] ), DateTime, last - posn );
644 posn = strlen( buf );
648 else if ( next ==
'm' )
651 sprintf( DateTime,
"%02d", month + 1 );
653 strncat( &( buf[posn] ), DateTime, last - posn );
654 posn = strlen( buf );
658 else if ( next ==
'M' )
661 sprintf( DateTime,
"%02d", min );
663 strncat( &( buf[posn] ), DateTime, last - posn );
664 posn = strlen( buf );
668 else if ( next ==
'n' )
676 else if ( next ==
'p' )
680 sprintf( DateTime,
"AM" );
682 sprintf( DateTime,
"PM" );
684 strncat( &( buf[posn] ), DateTime, last - posn );
685 posn = strlen( buf );
689 else if ( next ==
'r' )
693 sprintf( DateTime,
"%02d:%02d:%02d AM", hour + 12, min, second );
694 else if ( hour > 12 )
695 sprintf( DateTime,
"%02d:%02d:%02d PM", hour - 12, min, second );
696 else if ( hour == 12 )
697 sprintf( DateTime,
"%02d:%02d:%02d PM", hour, min, second );
699 sprintf( DateTime,
"%02d:%02d:%02d AM", hour, min, second );
701 strncat( &( buf[posn] ), DateTime, last - posn );
702 posn = strlen( buf );
706 else if ( next ==
'R' )
709 sprintf( DateTime,
"%02d:%02d", hour, min );
711 strncat( &( buf[posn] ), DateTime, last - posn );
712 posn = strlen( buf );
716 else if ( next ==
'S' )
719 if ( i + 2 < fmtlen && format[i + 1] ==
'%' && ( format[i + 2] ==
'.' || isdigit( format[i + 2] ) != 0 ) )
722 if ( format[i + 2] ==
'.' )
726 nplaces = (int) strtol( &( format[i + 2] ), NULL, 10 );
736 sprintf( DateTime,
"%02d", (
int) ( sec + 0.5 ) );
740 sprintf( dynamic_format,
"%%0%d.%df", nplaces + 3, nplaces );
741 sprintf( DateTime, dynamic_format, sec );
742 if ( format[i] ==
'.' )
744 slen = (int) strlen( DateTime ) - 1;
745 while ( DateTime[slen] ==
'0' && DateTime[slen - 1] !=
'.' )
747 DateTime[slen] =
'\0';
753 strncat( &( buf[posn] ), DateTime, last - posn );
754 posn = strlen( buf );
758 else if ( next ==
's' )
762 sprintf( DateTime,
"%d", secsSince1970 );
764 strncat( &( buf[posn] ), DateTime, last - posn );
765 posn = strlen( buf );
769 else if ( next ==
't' )
777 else if ( next ==
'T' )
780 sprintf( DateTime,
"%02d:%02d:%02d", hour, min, second );
782 strncat( &( buf[posn] ), DateTime, last - posn );
783 posn = strlen( buf );
787 else if ( next ==
'U' )
790 getYAD( &y1, &ifleapyear, &doy, nMJD, forceJulian );
791 days_in_wk1 = ( nMJD->
base_day - doy - 4 ) % 7;
793 w = ( doy + 6 - days_in_wk1 ) / 7;
795 sprintf( DateTime,
"%02d", w );
797 strncat( &( buf[posn] ), DateTime, last - posn );
798 posn = strlen( buf );
802 else if ( next ==
'u' )
807 sprintf( DateTime,
"%01d", d );
809 strncat( &( buf[posn] ), DateTime, last - posn );
810 posn = strlen( buf );
814 else if ( next ==
'v' )
823 sprintf( DateTime,
" %01d-%s-%04d", day, monthText, year );
825 sprintf( DateTime,
"%02d-%s-%04d", day, monthText, year );
830 sprintf( DateTime,
" %01d-%s-(-)%04d", day, monthText, year );
832 sprintf( DateTime,
"%02d-%s-(-)%04d", day, monthText, year );
835 strncat( &( buf[posn] ), DateTime, last - posn );
836 posn = strlen( buf );
840 else if ( next ==
'V' )
843 getYAD( &y1, &ifleapyear, &doy, nMJD, forceJulian );
844 days_in_wk1 = ( nMJD->
base_day - doy - 3 ) % 7;
846 if ( days_in_wk1 <= 3 )
847 w = ( doy + 6 - days_in_wk1 ) / 7;
849 w = 1 + ( doy + 6 - days_in_wk1 ) / 7;
853 sprintf( DateTime,
"%02d", w );
855 strncat( &( buf[posn] ), DateTime, last - posn );
856 posn = strlen( buf );
860 else if ( next ==
'w' )
865 sprintf( DateTime,
"%01d", d );
867 strncat( &( buf[posn] ), DateTime, last - posn );
868 posn = strlen( buf );
872 else if ( next ==
'W' )
875 getYAD( &y1, &ifleapyear, &doy, nMJD, forceJulian );
876 days_in_wk1 = ( nMJD->
base_day - doy - 3 ) % 7;
878 w = ( doy + 6 - days_in_wk1 ) / 7;
880 sprintf( DateTime,
"%02d", w );
882 strncat( &( buf[posn] ), DateTime, last - posn );
883 posn = strlen( buf );
887 else if ( next ==
'x' )
893 sprintf( DateTime,
"%s %s %02d, %04d", dayText, monthText, day, year );
895 sprintf( DateTime,
"%s %s %02d, -%04d", dayText, monthText, day, year );
897 strncat( &( buf[posn] ), DateTime, last - posn );
898 posn = strlen( buf );
902 else if ( next ==
'X' )
905 sprintf( DateTime,
"%02d:%02d:%02d", hour, min, second );
907 strncat( &( buf[posn] ), DateTime, last - posn );
908 posn = strlen( buf );
912 else if ( next ==
'y' )
918 sprintf( DateTime,
"%02d", y );
920 sprintf( DateTime,
"-%02d", y );
922 strncat( &( buf[posn] ), DateTime, last - posn );
923 posn = strlen( buf );
927 else if ( next ==
'Y' )
931 sprintf( DateTime,
"%04d", year );
933 sprintf( DateTime,
"-%04d", year );
935 strncat( &( buf[posn] ), DateTime, last - posn );
936 posn = strlen( buf );
940 else if ( next ==
'Z' )
944 strncat( &( buf[posn] ),
"UTC Julian", last - posn );
946 strncat( &( buf[posn] ),
"UTC Gregorian", last - posn );
948 posn = strlen( buf );
952 else if ( next ==
'z' )
955 strncat( &( buf[posn] ),
"+0000", last - posn );
956 posn = strlen( buf );
960 else if ( next ==
'+' )
966 sprintf( DateTime,
"%s %s %02d %02d:%02d:%02d UTC %04d", dayText, monthText, day, hour, min, second, year );
968 sprintf( DateTime,
"%s %s %02d %02d:%02d:%02d UTC -%04d", dayText, monthText, day, hour, min, second, year );
970 strncat( &( buf[posn] ), DateTime, last - posn );
971 posn = strlen( buf );
975 else if ( next ==
'.' || isdigit( next ) != 0 )
982 nplaces = (int) strtol( &( format[i] ), NULL, 10 );
985 sec_fraction = sec - (int) sec;
986 sprintf( dynamic_format,
"%%-%d.%df", nplaces + 2, nplaces );
988 sprintf( DateTime, dynamic_format, sec_fraction );
989 while ( ( ptr = strrchr( &( DateTime[0] ),
' ' ) ) != NULL )
994 slen = (int) strlen( DateTime ) - 1;
995 while ( DateTime[slen] ==
'0' && DateTime[slen - 1] !=
'.' )
997 DateTime[slen] =
'\0';
1002 ptr = strchr( DateTime,
'.' );
1006 strncat( &( buf[posn] ), ptr, last - posn );
1007 posn = strlen( buf );
1068 MJDtime MJD_value, *MJD = &MJD_value;
1077 fprintf( stderr,
"*index = %d\n", *index );
1084 fprintf( stderr,
"libqsastime (leap_second_TAI) logic ERROR: bad condition for *index = %d\n", *index );
1085 exit( EXIT_FAILURE );
1102 fprintf( stderr,
"libqsastime (leap_second_TAI) logic ERROR: bad condition for *index = %d\n", *index );
1103 exit( EXIT_FAILURE );
1119 fprintf( stderr,
"libqsastime (leap_second_TAI) logic ERROR: bad condition for *index = %d\n", *index );
1120 exit( EXIT_FAILURE );
1137 fprintf( stderr,
"libqsastime (leap_second_TAI) logic ERROR: bad *index = %d\n", *index );
1138 exit( EXIT_FAILURE );
1142 void configqsas(
double scale,
double offset1,
double offset2,
int ccontrol,
int ifbtime_offset,
int year,
int month,
int day,
int hour,
int min,
double sec,
QSASConfig **qsasconfig )
1146 int forceJulian, ret;
1147 MJDtime MJD_value, *MJD = &MJD_value;
1151 if ( *qsasconfig == NULL )
1154 if ( *qsasconfig == NULL )
1156 fprintf( stderr,
"configqsas: out of memory\n" );
1157 exit( EXIT_FAILURE );
1163 ( *qsasconfig )->index = -40;
1167 if ( ifbtime_offset )
1169 if ( ccontrol & 0x1 )
1173 ret =
setFromUT( year, month, day, hour, min, sec, MJD, forceJulian );
1176 fprintf( stderr,
"configqsas: some problem with broken-down arguments\n" );
1177 exit( EXIT_FAILURE );
1182 ( *qsasconfig )->scale = scale;
1183 ( *qsasconfig )->offset1 = offset1;
1184 ( *qsasconfig )->offset2 = offset2;
1185 ( *qsasconfig )->ccontrol = ccontrol;
1193 ( *qsasconfig )->scale = 1. / (double)
SecInDay;
1194 ( *qsasconfig )->offset1 = (double)
MJD_1970;
1195 ( *qsasconfig )->offset2 = 0.;
1196 ( *qsasconfig )->ccontrol = 0x0;
1203 if ( *qsasconfig != NULL )
1205 free( (
void *) *qsasconfig );
1212 MJDtime MJD_value, *MJD = &MJD_value;
1213 int forceJulian, ret;
1215 if ( qsasconfig == NULL )
1217 fprintf( stderr,
"libqsastime (ctimeqsas) ERROR: configqsas must be called first.\n" );
1218 exit( EXIT_FAILURE );
1226 ret =
setFromUT( year, month, day, hour, min, sec, MJD, forceJulian );
1235 MJDtime MJD_value, *MJD = &MJD_value;
1237 double integral_offset1, integral_offset2, integral_scaled_ctime;
1240 if ( qsasconfig == NULL )
1242 fprintf( stderr,
"libqsastime (btimeqsas) ERROR: configqsas must be called first.\n" );
1243 exit( EXIT_FAILURE );
1246 MJD->
time_sec =
SecInDay * ( modf( qsasconfig->
offset1, &integral_offset1 ) + modf( qsasconfig->
offset2, &integral_offset2 ) + modf( ctime * qsasconfig->
scale, &integral_scaled_ctime ) );
1247 MJD->
base_day = (int) ( integral_offset1 + integral_offset2 + integral_scaled_ctime );
1266 breakDownMJD( year, month, day, hour, min, sec, MJD, forceJulian );
1273 MJDtime MJD_value, *MJD = &MJD_value;
1275 double integral_offset1, integral_offset2, integral_scaled_ctime;
1278 if ( qsasconfig == NULL )
1280 fprintf( stderr,
"libqsastime (strfqsas) ERROR: configqsas must be called first.\n" );
1281 exit( EXIT_FAILURE );
1283 MJD->
time_sec =
SecInDay * ( modf( qsasconfig->
offset1, &integral_offset1 ) + modf( qsasconfig->
offset2, &integral_offset2 ) + modf( ctime * qsasconfig->
scale, &integral_scaled_ctime ) );
1284 MJD->
base_day = (int) ( integral_offset1 + integral_offset2 + integral_scaled_ctime );
1296 return strfMJD( buf, len, format, MJD, forceJulian, inleap );
1312 void bhunt_search(
const void *key,
const void *base,
int n,
size_t size,
int *low,
int ( *ge )(
const void *keyval,
const void *datum ) )
1314 const void *indexbase;
1315 int mid, high, hunt_inc = 1;
1322 if ( *low < 0 || *low >= n )
1330 indexbase = (
const void *) ( ( (
const char *) base ) + ( size * (size_t) ( *low ) ) );
1331 if ( ( *ge )( key, indexbase ) )
1333 high = ( *low ) + hunt_inc;
1334 indexbase = (
const void *) ( ( (
const char *) base ) + ( size * (
size_t) high ) );
1336 while ( ( high < n ) && ( ( *ge )( key, indexbase ) ) )
1339 hunt_inc += hunt_inc;
1340 high = high + hunt_inc;
1341 indexbase = (
const void *) ( ( (
const char *) base ) + ( size * (
size_t) high ) );
1351 *low = high - hunt_inc;
1352 indexbase = (
const void *) ( ( (
const char *) base ) + ( size * (
size_t) ( *low ) ) );
1354 while ( ( ( *low ) >= 0 ) && !( ( *ge )( key, indexbase ) ) )
1357 hunt_inc += hunt_inc;
1358 *low = ( *low ) - hunt_inc;
1359 indexbase = (
const void *) ( ( (
const char *) base ) + ( size * (
size_t) ( *low ) ) );
1370 while ( high - *low > 1 )
1372 mid = *low + ( high - *low ) / 2;
1373 indexbase = (
const void *) ( ( (
const char *) base ) + ( size * (
size_t) mid ) );
1374 if ( ( *ge )( key, indexbase ) )
const char * getMonth(int m)
size_t strfMJD(char *buf, size_t len, const char *format, const MJDtime *MJD, int forceJulian, int inleap)
int setFromUT(int year, int month, int day, int hour, int min, double sec, MJDtime *MJD, int forceJulian)
struct QSASConfigStruct QSASConfig
int ctimeqsas(int year, int month, int day, int hour, int min, double sec, double *ctime, QSASConfig *qsasconfig)
static int geMJDtime_UTC(const MJDtime *number1, const TAI_UTC *number2)
size_t strfqsas(char *buf, size_t len, const char *format, double ctime, QSASConfig *qsasconfig)
void getYAD(int *year, int *ifleapyear, int *doy, const MJDtime *MJD, int forceJulian)
void configqsas(double scale, double offset1, double offset2, int ccontrol, int ifbtime_offset, int year, int month, int day, int hour, int min, double sec, QSASConfig **qsasconfig)
static const double SecInDay
void bhunt_search(const void *key, const void *base, int n, size_t size, int *low, int(*ge)(const void *keyval, const void *datum))
const int number_of_entries_in_tai_utc_table
static int geMJDtime_TAI(const MJDtime *number1, const TAI_UTC *number2)
static const int MonthStartDOY_L[]
static const int MonthStartDOY[]
const char * getLongDayOfWeek(const MJDtime *MJD)
const TAI_UTC TAI_UTC_lookup_table[38]
static double leap_second_TAI(const MJDtime *MJD_TAI, int *inleap, int *index)
const char * getDayOfWeek(const MJDtime *MJD)
void normalize_MJD(MJDtime *MJD)
void closeqsas(QSASConfig **qsasconfig)
void breakDownMJD(int *year, int *month, int *day, int *hour, int *min, double *sec, const MJDtime *MJD, int forceJulian)
const char * getLongMonth(int m)
void btimeqsas(int *year, int *month, int *day, int *hour, int *min, double *sec, double ctime, QSASConfig *qsasconfig)