00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include <sys/timeb.h>
00047 #include <time.h>
00048 #include <math.h>
00049 #include "time_conversion.h"
00050 #include "constants.h"
00051
00052 #ifndef WIN32
00053 #define _CRT_SECURE_NO_DEPRECATE
00054 #endif
00055
00056
00057 #define TIMECONV_JULIAN_DATE_START_OF_GPS_TIME (2444244.5) // [days]
00058 #define TIMECONV_JULIAN_DATE_START_OF_PC_TIME (2440587.5) // [days]
00059 #define TIMECONV_DAYS_IN_JAN 31
00060 #define TIMECONV_DAYS_IN_MAR 31
00061 #define TIMECONV_DAYS_IN_APR 30
00062 #define TIMECONV_DAYS_IN_MAY 31
00063 #define TIMECONV_DAYS_IN_JUN 30
00064 #define TIMECONV_DAYS_IN_JUL 31
00065 #define TIMECONV_DAYS_IN_AUG 31
00066 #define TIMECONV_DAYS_IN_SEP 30
00067 #define TIMECONV_DAYS_IN_OCT 31
00068 #define TIMECONV_DAYS_IN_NOV 30
00069 #define TIMECONV_DAYS_IN_DEC 31
00070
00071
00072
00073
00074 static BOOL TIMECONV_IsUTCTimeValid(
00075 const unsigned short utc_year,
00076 const unsigned char utc_month,
00077 const unsigned char utc_day,
00078 const unsigned char utc_hour,
00079 const unsigned char utc_minute,
00080 const float utc_seconds
00081 );
00082
00083
00084 BOOL TIMECONV_IsUTCTimeValid(
00085 const unsigned short utc_year,
00086 const unsigned char utc_month,
00087 const unsigned char utc_day,
00088 const unsigned char utc_hour,
00089 const unsigned char utc_minute,
00090 const float utc_seconds
00091 )
00092 {
00093 unsigned char daysInMonth;
00094 BOOL result;
00095 if( utc_month == 0 || utc_month > 12 )
00096 return FALSE;
00097 result = TIMECONV_GetNumberOfDaysInMonth( utc_year, utc_month, &daysInMonth );
00098 if( result == FALSE )
00099 return FALSE;
00100 if( utc_day == 0 || utc_day > daysInMonth )
00101 return FALSE;
00102 if( utc_hour > 23 )
00103 return FALSE;
00104 if( utc_minute > 59 )
00105 return FALSE;
00106 if( utc_seconds > 60 )
00107 return FALSE;
00108
00109 return TRUE;
00110 }
00111
00112
00113 BOOL TIMECONV_GetSystemTime(
00114 unsigned short* utc_year,
00115 unsigned char* utc_month,
00116 unsigned char* utc_day,
00117 unsigned char* utc_hour,
00118 unsigned char* utc_minute,
00119 float* utc_seconds,
00120 unsigned char* utc_offset,
00121 double* julian_date,
00122 unsigned short* gps_week,
00123 double* gps_tow
00124 )
00125 {
00126 BOOL result;
00127
00128 #ifdef WIN32
00129 struct _timeb timebuffer;
00130 #else
00131 struct timeb timebuffer;
00132 #endif
00133 double timebuffer_time_in_days;
00134 double timebuffer_time_in_seconds;
00135
00136
00137 #ifndef _CRT_SECURE_NO_DEPRECATE
00138 if( _ftime_s( &timebuffer ) != 0 )
00139 return FALSE;
00140 #else
00141
00142 #ifdef WIN32
00143 _ftime( &timebuffer );
00144 #else
00145 ftime( &timebuffer );
00146 #endif
00147
00148 #endif
00149
00150
00151
00152 timebuffer_time_in_seconds = timebuffer.time + timebuffer.millitm / 1000.0;
00153
00154
00155
00156
00157
00158 timebuffer_time_in_days = timebuffer_time_in_seconds/SECONDS_IN_DAY;
00159
00160
00161 *julian_date = TIMECONV_JULIAN_DATE_START_OF_PC_TIME + timebuffer_time_in_days;
00162
00163 result = TIMECONV_DetermineUTCOffset( *julian_date, utc_offset );
00164 if( result == FALSE )
00165 return FALSE;
00166
00167 result = TIMECONV_GetGPSTimeFromJulianDate(
00168 *julian_date,
00169 *utc_offset,
00170 gps_week,
00171 gps_tow );
00172 if( result == FALSE )
00173 return FALSE;
00174
00175 result = TIMECONV_GetUTCTimeFromJulianDate(
00176 *julian_date,
00177 utc_year,
00178 utc_month,
00179 utc_day,
00180 utc_hour,
00181 utc_minute,
00182 utc_seconds );
00183 if( result == FALSE )
00184 return FALSE;
00185
00186 return TRUE;
00187 }
00188
00189
00190 BOOL TIMECONV_GetJulianDateFromGPSTime(
00191 const unsigned short gps_week,
00192 const double gps_tow,
00193 const unsigned char utc_offset,
00194 double* julian_date
00195 )
00196 {
00197 if( gps_tow < 0.0 || gps_tow > 604800.0 )
00198 return FALSE;
00199
00200
00201 *julian_date = (gps_week + (gps_tow-utc_offset)/604800.0)*7.0 + TIMECONV_JULIAN_DATE_START_OF_GPS_TIME;
00202 return TRUE;
00203 }
00204
00205
00206 BOOL TIMECONV_GetJulianDateFromUTCTime(
00207 const unsigned short utc_year,
00208 const unsigned char utc_month,
00209 const unsigned char utc_day,
00210 const unsigned char utc_hour,
00211 const unsigned char utc_minute,
00212 const float utc_seconds,
00213 double* julian_date
00214 )
00215 {
00216 double y;
00217 double m;
00218 BOOL result;
00219
00220
00221 result = TIMECONV_IsUTCTimeValid( utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds );
00222 if( result == FALSE )
00223 return FALSE;
00224
00225 if( utc_month <= 2 )
00226 {
00227 y = utc_year - 1;
00228 m = utc_month + 12;
00229 }
00230 else
00231 {
00232 y = utc_year;
00233 m = utc_month;
00234 }
00235
00236 *julian_date = (int)(365.25*y) + (int)(30.6001*(m+1.0)) + utc_day + utc_hour/24.0 + utc_minute/1440.0 + utc_seconds/86400.0 + 1720981.5;
00237 return TRUE;
00238 }
00239
00240
00241
00242 BOOL TIMECONV_GetGPSTimeFromJulianDate(
00243 const double julian_date,
00244 const unsigned char utc_offset,
00245 unsigned short* gps_week,
00246 double* gps_tow
00247 )
00248 {
00249
00250 if( julian_date < 0.0 )
00251 return FALSE;
00252
00253 *gps_week = (unsigned short)((julian_date - TIMECONV_JULIAN_DATE_START_OF_GPS_TIME)/7.0);
00254
00255 *gps_tow = (julian_date - TIMECONV_JULIAN_DATE_START_OF_GPS_TIME)*SECONDS_IN_DAY;
00256 *gps_tow -= (*gps_week)*SECONDS_IN_WEEK;
00257
00258
00259 *gps_tow += utc_offset;
00260 if( *gps_tow > SECONDS_IN_WEEK )
00261 {
00262 *gps_tow -= SECONDS_IN_WEEK;
00263 *gps_week += 1;
00264 }
00265 return TRUE;
00266 }
00267
00268
00269 BOOL TIMECONV_GetUTCTimeFromJulianDate(
00270 const double julian_date,
00271 unsigned short* utc_year,
00272 unsigned char* utc_month,
00273 unsigned char* utc_day,
00274 unsigned char* utc_hour,
00275 unsigned char* utc_minute,
00276 float* utc_seconds
00277 )
00278 {
00279 int a, b, c, d, e;
00280
00281 unsigned short year;
00282 unsigned char month;
00283 unsigned char day;
00284 unsigned char hour;
00285 unsigned char minute;
00286 unsigned char days_in_month = 0;
00287 double td;
00288 double seconds;
00289 BOOL result;
00290
00291
00292 if( julian_date < 0.0 )
00293 return FALSE;
00294
00295 a = (int)(julian_date+0.5);
00296 b = a + 1537;
00297 c = (int)( ((double)b-122.1)/365.25 );
00298 d = (int)(365.25*c);
00299 e = (int)( ((double)(b-d))/30.6001 );
00300
00301 td = b - d - (int)(30.6001*e) + fmod( julian_date+0.5, 1.0 );
00302 day = (unsigned char)td;
00303 td -= day;
00304 td *= 24.0;
00305 hour = (unsigned char)td;
00306 td -= hour;
00307 td *= 60.0;
00308 minute = (unsigned char)td;
00309 td -= minute;
00310 td *= 60.0;
00311 seconds = td;
00312 month = (unsigned char)(e - 1 - 12*(int)(e/14));
00313 year = (unsigned short)(c - 4715 - (int)( (7.0+(double)month) / 10.0 ));
00314
00315
00316 if( seconds >= 60.0 )
00317 {
00318 seconds -= 60.0;
00319 minute++;
00320 if( minute >= 60 )
00321 {
00322 minute -= 60;
00323 hour++;
00324 if( hour >= 24 )
00325 {
00326 hour -= 24;
00327 day++;
00328
00329 result = TIMECONV_GetNumberOfDaysInMonth( year, month, &days_in_month );
00330 if( result == FALSE )
00331 return FALSE;
00332
00333 if( day > days_in_month )
00334 {
00335 day = 1;
00336 month++;
00337 if( month > 12 )
00338 {
00339 month = 1;
00340 year++;
00341 }
00342 }
00343 }
00344 }
00345 }
00346
00347 *utc_year = year;
00348 *utc_month = month;
00349 *utc_day = day;
00350 *utc_hour = hour;
00351 *utc_minute = minute;
00352 *utc_seconds = (float)seconds;
00353
00354 return TRUE;
00355 }
00356
00357 BOOL TIMECONV_GetGPSTimeFromUTCTime(
00358 unsigned short utc_year,
00359 unsigned char utc_month,
00360 unsigned char utc_day,
00361 unsigned char utc_hour,
00362 unsigned char utc_minute,
00363 float utc_seconds,
00364 unsigned short* gps_week,
00365 double* gps_tow
00366 )
00367 {
00368 double julian_date=0.0;
00369 unsigned char utc_offset=0;
00370 BOOL result;
00371
00372
00373 result = TIMECONV_IsUTCTimeValid( utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds );
00374 if( result == FALSE )
00375 return FALSE;
00376
00377 result = TIMECONV_GetJulianDateFromUTCTime(
00378 utc_year,
00379 utc_month,
00380 utc_day,
00381 utc_hour,
00382 utc_minute,
00383 utc_seconds,
00384 &julian_date );
00385 if( result == FALSE )
00386 return FALSE;
00387
00388 result = TIMECONV_DetermineUTCOffset( julian_date, &utc_offset );
00389 if( result == FALSE )
00390 return FALSE;
00391
00392 result = TIMECONV_GetGPSTimeFromJulianDate(
00393 julian_date,
00394 utc_offset,
00395 gps_week,
00396 gps_tow );
00397 if( result == FALSE )
00398 return FALSE;
00399
00400 return TRUE;
00401 }
00402
00403
00404
00405 BOOL TIMECONV_GetGPSTimeFromRinexTime(
00406 unsigned short utc_year,
00407 unsigned char utc_month,
00408 unsigned char utc_day,
00409 unsigned char utc_hour,
00410 unsigned char utc_minute,
00411 float utc_seconds,
00412 unsigned short* gps_week,
00413 double* gps_tow
00414 )
00415 {
00416 double julian_date=0.0;
00417 unsigned char utc_offset=0;
00418 BOOL result;
00419
00420
00421 result = TIMECONV_IsUTCTimeValid( utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_seconds );
00422 if( result == FALSE )
00423 return FALSE;
00424
00425 result = TIMECONV_GetJulianDateFromUTCTime(
00426 utc_year,
00427 utc_month,
00428 utc_day,
00429 utc_hour,
00430 utc_minute,
00431 utc_seconds,
00432 &julian_date );
00433 if( result == FALSE )
00434 return FALSE;
00435
00436 result = TIMECONV_GetGPSTimeFromJulianDate(
00437 julian_date,
00438 utc_offset,
00439 gps_week,
00440 gps_tow );
00441 if( result == FALSE )
00442 return FALSE;
00443
00444 return TRUE;
00445 }
00446
00447
00448
00449 BOOL TIMECONV_GetUTCTimeFromGPSTime(
00450 unsigned short gps_week,
00451 double gps_tow,
00452 unsigned short* utc_year,
00453 unsigned char* utc_month,
00454 unsigned char* utc_day,
00455 unsigned char* utc_hour,
00456 unsigned char* utc_minute,
00457 float* utc_seconds
00458 )
00459 {
00460 double julian_date = 0.0;
00461 unsigned char utc_offset = 0;
00462 int i;
00463 BOOL result;
00464
00465 if( gps_tow < 0.0 || gps_tow > 604800.0 )
00466 return FALSE;
00467
00468
00469 for( i = 0; i < 4; i++ )
00470 {
00471 result = TIMECONV_GetJulianDateFromGPSTime(
00472 gps_week,
00473 gps_tow,
00474 utc_offset,
00475 &julian_date );
00476 if( result == FALSE )
00477 return FALSE;
00478
00479 result = TIMECONV_DetermineUTCOffset( julian_date, &utc_offset );
00480 if( result == FALSE )
00481 return FALSE;
00482 }
00483
00484 result = TIMECONV_GetUTCTimeFromJulianDate(
00485 julian_date,
00486 utc_year,
00487 utc_month,
00488 utc_day,
00489 utc_hour,
00490 utc_minute,
00491 utc_seconds );
00492 if( result == FALSE )
00493 return FALSE;
00494
00495 return TRUE;
00496 }
00497
00498
00499
00500 BOOL TIMECONV_DetermineUTCOffset(
00501 double julian_date,
00502 unsigned char* utc_offset
00503 )
00504 {
00505 if( julian_date < 0.0 )
00506 return FALSE;
00507
00508 if( julian_date < 2444786.5000 ) *utc_offset = 0;
00509 else if( julian_date < 2445151.5000 ) *utc_offset = 1;
00510 else if( julian_date < 2445516.5000 ) *utc_offset = 2;
00511 else if( julian_date < 2446247.5000 ) *utc_offset = 3;
00512 else if( julian_date < 2447161.5000 ) *utc_offset = 4;
00513 else if( julian_date < 2447892.5000 ) *utc_offset = 5;
00514 else if( julian_date < 2448257.5000 ) *utc_offset = 6;
00515 else if( julian_date < 2448804.5000 ) *utc_offset = 7;
00516 else if( julian_date < 2449169.5000 ) *utc_offset = 8;
00517 else if( julian_date < 2449534.5000 ) *utc_offset = 9;
00518 else if( julian_date < 2450083.5000 ) *utc_offset = 10;
00519 else if( julian_date < 2450630.5000 ) *utc_offset = 11;
00520 else if( julian_date < 2451179.5000 ) *utc_offset = 12;
00521 else if( julian_date < 2453736.5000 ) *utc_offset = 13;
00522 else *utc_offset = 14;
00523
00524 return TRUE;
00525 }
00526
00527
00528
00529
00530 BOOL TIMECONV_GetNumberOfDaysInMonth(
00531 const unsigned short year,
00532 const unsigned char month,
00533 unsigned char* days_in_month
00534 )
00535 {
00536 BOOL is_a_leapyear;
00537 unsigned char utmp = 0;
00538
00539 is_a_leapyear = TIMECONV_IsALeapYear( year );
00540
00541 switch(month)
00542 {
00543 case 1: utmp = TIMECONV_DAYS_IN_JAN; break;
00544 case 2: if( is_a_leapyear ){ utmp = 29; }else{ utmp = 28; }break;
00545 case 3: utmp = TIMECONV_DAYS_IN_MAR; break;
00546 case 4: utmp = TIMECONV_DAYS_IN_APR; break;
00547 case 5: utmp = TIMECONV_DAYS_IN_MAY; break;
00548 case 6: utmp = TIMECONV_DAYS_IN_JUN; break;
00549 case 7: utmp = TIMECONV_DAYS_IN_JUL; break;
00550 case 8: utmp = TIMECONV_DAYS_IN_AUG; break;
00551 case 9: utmp = TIMECONV_DAYS_IN_SEP; break;
00552 case 10: utmp = TIMECONV_DAYS_IN_OCT; break;
00553 case 11: utmp = TIMECONV_DAYS_IN_NOV; break;
00554 case 12: utmp = TIMECONV_DAYS_IN_DEC; break;
00555 default: return FALSE; break;
00556 }
00557
00558 *days_in_month = utmp;
00559
00560 return TRUE;
00561 }
00562
00563
00564
00565
00566 BOOL TIMECONV_IsALeapYear( const unsigned short year )
00567 {
00568 BOOL is_a_leap_year = FALSE;
00569
00570 if( (year%4) == 0 )
00571 {
00572 is_a_leap_year = TRUE;
00573 if( (year%100) == 0 )
00574 {
00575 if( (year%400) == 0 )
00576 {
00577 is_a_leap_year = TRUE;
00578 }
00579 else
00580 {
00581 is_a_leap_year = FALSE;
00582 }
00583 }
00584 }
00585 if( is_a_leap_year )
00586 {
00587 return TRUE;
00588 }
00589 else
00590 {
00591 return FALSE;
00592 }
00593 }
00594
00595
00596
00597
00598
00599 BOOL TIMECONV_GetDayOfYear(
00600 const unsigned short utc_year,
00601 const unsigned char utc_month,
00602 const unsigned char utc_day,
00603 unsigned short* dayofyear
00604 )
00605 {
00606 unsigned char days_in_feb = 0;
00607 BOOL result;
00608 result = TIMECONV_GetNumberOfDaysInMonth( utc_year, 2, &days_in_feb );
00609 if( result == FALSE )
00610 return FALSE;
00611
00612 switch( utc_month )
00613 {
00614 case 1: *dayofyear = utc_day; break;
00615 case 2: *dayofyear = (unsigned short)(TIMECONV_DAYS_IN_JAN + utc_day); break;
00616 case 3: *dayofyear = (unsigned short)(TIMECONV_DAYS_IN_JAN + days_in_feb + utc_day); break;
00617 case 4: *dayofyear = (unsigned short)(62 + days_in_feb + utc_day); break;
00618 case 5: *dayofyear = (unsigned short)(92 + days_in_feb + utc_day); break;
00619 case 6: *dayofyear = (unsigned short)(123 + days_in_feb + utc_day); break;
00620 case 7: *dayofyear = (unsigned short)(153 + days_in_feb + utc_day); break;
00621 case 8: *dayofyear = (unsigned short)(184 + days_in_feb + utc_day); break;
00622 case 9: *dayofyear = (unsigned short)(215 + days_in_feb + utc_day); break;
00623 case 10: *dayofyear = (unsigned short)(245 + days_in_feb + utc_day); break;
00624 case 11: *dayofyear = (unsigned short)(276 + days_in_feb + utc_day); break;
00625 case 12: *dayofyear = (unsigned short)(306 + days_in_feb + utc_day); break;
00626 default: return FALSE; break;
00627 }
00628
00629 return TRUE;
00630 }
00631
00632
00633 BOOL TIMECONV_GetGPSTimeFromYearAndDayOfYear(
00634 const unsigned short year,
00635 const unsigned short dayofyear,
00636 unsigned short* gps_week,
00637 double* gps_tow
00638 )
00639 {
00640 BOOL result;
00641 double julian_date = 0;
00642
00643 if( gps_week == NULL )
00644 return FALSE;
00645 if( gps_tow == NULL )
00646 return FALSE;
00647 if( dayofyear > 366 )
00648 return FALSE;
00649
00650 result = TIMECONV_GetJulianDateFromUTCTime(
00651 year,
00652 1,
00653 1,
00654 0,
00655 0,
00656 0,
00657 &julian_date
00658 );
00659 if( result == FALSE )
00660 return FALSE;
00661
00662 julian_date += dayofyear - 1;
00663
00664 result = TIMECONV_GetGPSTimeFromJulianDate(
00665 julian_date,
00666 0,
00667 gps_week,
00668 gps_tow );
00669
00670 return result;
00671 }