/*FUNCTION**************************************************************** * * Function Name : _real_time_to_sec * Returned Value : none * Comments : * This function convert date to secs since 1.1.1970 0:0:0". * *END*********************************************************************/ static uint_32 _date_to_sec( DATE_STRUCT_PTR time ) { #define SEC_IN_MIN 60 #define SEC_IN_HOUR 3600 #define SEC_IN_DAY 86400 #define FEBRUARY 2 #define ZERO_YEAR 1970 static const uint_16 days_no_table[]= { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; uint_32 days = 0; uint_32 month; uint_32 year; days = 365 * (time->YEAR - ZERO_YEAR); /* get leap year */ for( year = ZERO_YEAR; year < time->YEAR; year++) { days += _is_leap_year( year ); } for( month = 1; month < time->MONTH; month++) { days+= days_no_table[month - 1]; /* is leap year? */ if( month == FEBRUARY ) { days+= _is_leap_year( time->YEAR ); } } days += time->DAY-1; return days*SEC_IN_DAY + time->HOUR*SEC_IN_HOUR + time->MINUTE*SEC_IN_MIN + time->SECOND; }
/** * For specified year, month and day of month, returns which day of that year * it is. * * For example, given date 2011-01-03, the corresponding expression is: * _day_of_year(111, 0, 3) == 2 * * @param year Year (year 1900 = 0, can be negative). * @param mon Month (January = 0). * @param mday Day of month (First day is 1). * @return Day of year (First day is 0). */ static int _day_of_year(time_t year, time_t mon, time_t mday) { static int mdays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; static int leap_mdays[] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1; }
/** * Week number of the year, assuming weeks start on monday. * If the week containing January 1st has four or more days in the new year, * then it is considered week 1. Otherwise, it is the last week of the previous * year, and the next week is week 1. Both January 4th and the first Thursday * of January are always in week 1. * * @param tm Normalized broken-down time. * @return The week number (1 - 53). */ static int _iso_week_number(const struct posix_tm *tm) { int day = tm->tm_yday - _wbyear_offset(tm->tm_year); if (day < 0) { /* Last week of previous year. */ return 53; } if (day > 364 + _is_leap_year(tm->tm_year)) { /* First week of next year. */ return 1; } /* All the other days give correct answer. */ return (day / 7 + 1); }
/** * Returns week-based year of the specified time. * * @param tm Normalized broken-down time. * @return Week-based year. */ static int _wbyear(const struct posix_tm *tm) { int day = tm->tm_yday - _wbyear_offset(tm->tm_year); if (day < 0) { /* Last week of previous year. */ return tm->tm_year - 1; } if (day > 364 + _is_leap_year(tm->tm_year)) { /* First week of next year. */ return tm->tm_year + 1; } /* All the other days are in the calendar year. */ return tm->tm_year; }
/** * Returns how many days there are in the given month of the given year. * Note that year is only taken into account if month is February. * * @param year Year since 1900 (can be negative). * @param mon Month of the year. 0 for January, 11 for December. * @return Number of days in the specified month. */ static int _days_in_month(time_t year, time_t mon) { assert(mon >= 0 && mon <= 11); static int month_days[] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; if (mon == 1) { year += 1900; /* february */ return _is_leap_year(year) ? 29 : 28; } else { return month_days[mon]; } }
/** @memo Retrieve the current system date. @doc Retrieves the current system date and returns it in the storage location. @precondition The baseReference must refer to a valid date. @return 0 on success. -1 otherwise. */ int rtp_get_date ( RTP_DATE *date /** Storage location for the current system date. */ ) { unsigned long deltaSecs; *date = baseReference.referenceDate; deltaSecs = rtp_get_system_sec() - baseReference.syncTime; if (deltaSecs > 0) { date->second += deltaSecs; date->second %= 60; deltaSecs /= 60; if (deltaSecs > 0) { date->minute += deltaSecs; date->minute %= 60; deltaSecs /= 60; if (deltaSecs > 0) { date->hour += deltaSecs; date->hour %= 24; deltaSecs /= 24; if (deltaSecs > 0) { int total_days; date->day += deltaSecs; date->day %= 24; deltaSecs /= 24; if (_is_leap_year(date->year)) { total_days = month_start_leap[date->month] + date->day + deltaSecs; } else { total_days = month_start[date->month] + date->day + deltaSecs; } while (1) { if (_is_leap_year(date->year)) { if (total_days < 366) { break; } total_days -= 366; } else { if (total_days < 365) { break; } total_days -= 365; } date->year++; } if (_is_leap_year(date->year)) { for (date->month=0; date->month < 11 && month_start_leap[date->month + 1] < total_days; date->month++) {;} date->day = total_days - month_start_leap[date->month] + 1; } else { for (date->month=0; date->month < 11 && month_start[date->month + 1] < total_days; date->month++) {;} date->day = total_days - month_start[date->month] + 1; } date->month++; } } } } return (0); }
/** * Normalizes the broken-down time and optionally adds specified amount of * seconds. * * @param tm Broken-down time to normalize. * @param sec_add Seconds to add. * @return 0 on success, -1 on overflow */ static int _normalize_time(struct posix_tm *tm, time_t sec_add) { // TODO: DST correction /* Set initial values. */ time_t sec = tm->tm_sec + sec_add; time_t min = tm->tm_min; time_t hour = tm->tm_hour; time_t day = tm->tm_mday - 1; time_t mon = tm->tm_mon; time_t year = tm->tm_year; /* Adjust time. */ min += _floor_div(sec, SECS_PER_MIN); sec = _floor_mod(sec, SECS_PER_MIN); hour += _floor_div(min, MINS_PER_HOUR); min = _floor_mod(min, MINS_PER_HOUR); day += _floor_div(hour, HOURS_PER_DAY); hour = _floor_mod(hour, HOURS_PER_DAY); /* Adjust month. */ year += _floor_div(mon, 12); mon = _floor_mod(mon, 12); /* Now the difficult part - days of month. */ /* First, deal with whole cycles of 400 years = 146097 days. */ year += _floor_div(day, 146097) * 400; day = _floor_mod(day, 146097); /* Then, go in one year steps. */ if (mon <= 1) { /* January and February. */ while (day > 365) { day -= _is_leap_year(year) ? 366 : 365; year++; } } else { /* Rest of the year. */ while (day > 365) { day -= _is_leap_year(year + 1) ? 366 : 365; year++; } } /* Finally, finish it off month per month. */ while (day >= _days_in_month(year, mon)) { day -= _days_in_month(year, mon); mon++; if (mon >= 12) { mon -= 12; year++; } } /* Calculate the remaining two fields. */ tm->tm_yday = _day_of_year(year, mon, day + 1); tm->tm_wday = _day_of_week(year, mon, day + 1); /* And put the values back to the struct. */ tm->tm_sec = (int) sec; tm->tm_min = (int) min; tm->tm_hour = (int) hour; tm->tm_mday = (int) day + 1; tm->tm_mon = (int) mon; /* Casts to work around libc brain-damage. */ if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) { tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX); return -1; } tm->tm_year = (int) year; return 0; }