diff --git a/src/fs/fat/fat-control.c b/src/fs/fat/fat-control.c index 50c7cb5e1d7843728ff1187ba7d2d038f142a064..f7b0b31f7251062f77c69061b95dd8911031a931 100644 --- a/src/fs/fat/fat-control.c +++ b/src/fs/fat/fat-control.c @@ -495,8 +495,8 @@ static int __fatfs_control_truncate_clusters(struct fatfs_control_t *ctrl, NX_U3 NX_PRIVATE void fattime2time(NX_U32 year, NX_U32 mon, NX_U32 day, NX_U32 hour, NX_U32 min, NX_U32 sec, NX_Time * time) { - time->year = year + 1980; - time->month = mon; + time->year = 1980 + year - 1900; + time->month = mon - 1; time->day = day; time->hour = hour; time->minute = min; @@ -505,22 +505,20 @@ NX_PRIVATE void fattime2time(NX_U32 year, NX_U32 mon, NX_U32 day, NX_U32 hour, N NX_PRIVATE void time2fattime(NX_Time * time, NX_U32 * year, NX_U32 * mon, NX_U32 * day, NX_U32 * hour, NX_U32 * min, NX_U32 * sec) { - *year = time->year - 1980; - *mon = time->month; + *year = time->year + 1900 - 1980; + *mon = time->month + 1; *day = time->day; *hour = time->hour; *min = time->minute; *sec = time->second; } -NX_U32 fatfs_pack_timestamp(NX_U32 year, NX_U32 mon, NX_U32 day, NX_U32 hour, NX_U32 min, NX_U32 sec) +NX_TimeStamp fatfs_pack_timestamp(NX_U32 year, NX_U32 mon, NX_U32 day, NX_U32 hour, NX_U32 min, NX_U32 sec) { NX_Time tm; - /* 1. change fat time to std time */ fattime2time(year, mon, day, hour, min, sec, &tm); - /* 2. change std time to date time */ - return (NX_U32)NX_TimeToDate(&tm); + return NX_TimeToTimeStamp(&tm); } void fatfs_current_timestamp(NX_U32 * year, NX_U32 * mon, NX_U32 * day, NX_U32 * hour, NX_U32 * min, NX_U32 * sec) @@ -531,13 +529,11 @@ void fatfs_current_timestamp(NX_U32 * year, NX_U32 * mon, NX_U32 * day, NX_U32 * time2fattime(&tm, year, mon, day, hour, min, sec); } -void fatfs_timestamp(NX_Date * d, NX_U32 * year, NX_U32 * mon, NX_U32 * day, NX_U32 * hour, NX_U32 * min, NX_U32 * sec) +void fatfs_timestamp(NX_TimeStamp * d, NX_U32 * year, NX_U32 * mon, NX_U32 * day, NX_U32 * hour, NX_U32 * min, NX_U32 * sec) { NX_Time tm; - /* 1. change date time to std time */ - NX_DateToTime(*d, &tm); - /* 2. change std time to fat time */ + NX_TimeStampToTime(*d, &tm); time2fattime(&tm, year, mon, day, hour, min, sec); } diff --git a/src/fs/fat/fat-control.h b/src/fs/fat/fat-control.h index d235b44d0f90525018284b861be5efbd3aef5f0a..a63d6ac3e9f3b48fc49361a3b952cfc937df92cf 100644 --- a/src/fs/fat/fat-control.h +++ b/src/fs/fat/fat-control.h @@ -57,9 +57,9 @@ struct fatfs_control_t { NX_U8 * fat_cache_buf; }; -NX_U32 fatfs_pack_timestamp(NX_U32 year, NX_U32 mon, NX_U32 day, NX_U32 hour, NX_U32 min, NX_U32 sec); +NX_TimeStamp fatfs_pack_timestamp(NX_U32 year, NX_U32 mon, NX_U32 day, NX_U32 hour, NX_U32 min, NX_U32 sec); void fatfs_current_timestamp(NX_U32 * year, NX_U32 * mon, NX_U32 * day, NX_U32 * hour, NX_U32 * min, NX_U32 * sec); -void fatfs_timestamp(NX_Date * d, NX_U32 * year, NX_U32 * mon, NX_U32 * day, NX_U32 * hour, NX_U32 * min, NX_U32 * sec); +void fatfs_timestamp(NX_TimeStamp * d, NX_U32 * year, NX_U32 * mon, NX_U32 * day, NX_U32 * hour, NX_U32 * min, NX_U32 * sec); NX_Bool fatfs_control_valid_cluster(struct fatfs_control_t * ctrl, NX_U32 clust); int fatfs_control_nth_cluster(struct fatfs_control_t * ctrl, NX_U32 clust, NX_U32 pos, NX_U32 * next); int fatfs_control_set_last_cluster(struct fatfs_control_t * ctrl, NX_U32 clust); diff --git a/src/fs/fat/fat.c b/src/fs/fat/fat.c index 1805c423689f0fd44a32b781d446d0bbb006833c..9d5e8fb11bd0b7abcea0d074957f36e43f058d09 100644 --- a/src/fs/fat/fat.c +++ b/src/fs/fat/fat.c @@ -261,7 +261,7 @@ NX_PRIVATE NX_Error FatfsSync(NX_FileNode * n) node->parent_dent.first_cluster_lo = (node->first_cluster & 0xFFFF); /* Update node modify time */ - fatfs_timestamp((NX_Date *)&n->mtime, &year, &mon, &day, &hour, &min, &sec); + fatfs_timestamp((NX_TimeStamp *)&n->mtime, &year, &mon, &day, &hour, &min, &sec); node->parent_dent.lmodify_date_year = year; node->parent_dent.lmodify_date_month = mon; node->parent_dent.lmodify_date_day = day; @@ -270,13 +270,13 @@ NX_PRIVATE NX_Error FatfsSync(NX_FileNode * n) node->parent_dent.lmodify_time_seconds = sec; /* Update node access time */ - fatfs_timestamp((NX_Date *)&n->atime, &year, &mon, &day, &hour, &min, &sec); + fatfs_timestamp((NX_TimeStamp *)&n->atime, &year, &mon, &day, &hour, &min, &sec); node->parent_dent.laccess_date_year = year; node->parent_dent.laccess_date_month = mon; node->parent_dent.laccess_date_day = day; /* Update node access time */ - fatfs_timestamp((NX_Date *)(&n->ctime), &year, &mon, &day, &hour, &min, &sec); + fatfs_timestamp((NX_TimeStamp *)(&n->ctime), &year, &mon, &day, &hour, &min, &sec); node->parent_dent.create_date_year = year; node->parent_dent.create_date_month = mon; node->parent_dent.create_date_day = day; diff --git a/src/include/base/time.h b/src/include/base/time.h index 54907f8f7e39e69dac93c42da7a1f228e726f821..be163294b81191a2aaee8c49aa7f77e0160b2f69 100644 --- a/src/include/base/time.h +++ b/src/include/base/time.h @@ -14,9 +14,9 @@ #include -#define NX_TIME_BASE_YEAR 1980 +#define NX_TIME_YEAR_BASE 1900 -typedef NX_U32 NX_Date; +typedef NX_U32 NX_TimeStamp; typedef struct { NX_U8 second; /* [0-59] */ @@ -24,12 +24,12 @@ typedef struct { NX_U8 hour; /* [0-23] */ NX_U8 weekDay; /* [0-6] */ NX_U32 day; /* [1-31] */ - NX_U32 month; /* [1-12] */ - NX_U32 year; /* year */ + NX_U32 month; /* [0-11] */ + NX_U32 year; /* year, offset of 1900 */ NX_U32 yearDay; /* [0-366] */ } NX_Time; -#define NX_TIME_INIT_VAL {0, 0, 0, 0, 0, 1, 1980, 0} +#define NX_TIME_INIT_VAL {0, 0, 0, 0, 1, 0, 0, 0} #define NX_TIME_DEFINE(time) NX_Time time = NX_TIME_INIT_VAL; @@ -37,7 +37,8 @@ void NX_TimeGo(void); void NX_TimePrint(void); NX_Error NX_TimeSet(NX_Time * time); NX_Error NX_TimeGet(NX_Time * time); -NX_Date NX_TimeToDate(NX_Time * time); -NX_Error NX_DateToTime(NX_Date date, NX_Time * time); + +int NX_TimeStampToTime(NX_TimeStamp t, NX_Time * tm); +NX_TimeStamp NX_TimeToTimeStamp(const NX_Time * tm); #endif /* __TIME_TIME_H__ */ diff --git a/src/platform/i386 b/src/platform/i386 index 2849be41d9880cce200e986a20dac90951761a99..c03a7fac3d8f91ca14d3a5793b64cbbdfbf9f34f 160000 --- a/src/platform/i386 +++ b/src/platform/i386 @@ -1 +1 @@ -Subproject commit 2849be41d9880cce200e986a20dac90951761a99 +Subproject commit c03a7fac3d8f91ca14d3a5793b64cbbdfbf9f34f diff --git a/src/time/time.c b/src/time/time.c index 9b57bac153d2c06f203c887b42f79edc0bbe0762..c21175bd593b74331c041b11b84fb9f5075c358f 100644 --- a/src/time/time.c +++ b/src/time/time.c @@ -56,27 +56,27 @@ NX_PRIVATE int MakeWeekDay(int year, int month, int day) return week; } -NX_PRIVATE int MakeMonthDay() +NX_PRIVATE int MakeMonthDay(int year, int month) { - if (systemTime.month == 2) + if (month == 2) { - return monthDayTable[systemTime.month] + IsLeapYear(systemTime.year); + return monthDayTable[month] + IsLeapYear(year); } else { - return monthDayTable[systemTime.month]; + return monthDayTable[month]; } } -NX_PRIVATE int MakeYearDays() +NX_PRIVATE int MakeYearDays(int year, int month, int day) { int i; int sum = 0; - for (i = 1; i < systemTime.month; i++) + for (i = 1; i < month; i++) { if (i == 2) { - sum += monthDayTable[i] + IsLeapYear(systemTime.year); + sum += monthDayTable[i] + IsLeapYear(year); } else { @@ -84,19 +84,19 @@ NX_PRIVATE int MakeYearDays() } } - sum += systemTime.day; - if (systemTime.month >= 2) + sum += day; + if (month >= 2) { - if (systemTime.month == 2) + if (month == 2) { - if (systemTime.day == 28) + if (day == 28) { - sum += IsLeapYear(systemTime.year); + sum += IsLeapYear(year); } } else { - sum += IsLeapYear(systemTime.year); + sum += IsLeapYear(year); } } return sum; @@ -122,15 +122,20 @@ void NX_TimeGo(void) { systemTime.weekDay = 0; } - systemTime.yearDay = MakeYearDays(); - if(systemTime.day > MakeMonthDay()) + systemTime.yearDay = MakeYearDays( + systemTime.year + NX_TIME_YEAR_BASE, + systemTime.month + 1, + systemTime.day); + if(systemTime.day > MakeMonthDay( + systemTime.year + NX_TIME_YEAR_BASE, + systemTime.month + 1)) { systemTime.month++; systemTime.day = 1; - if(systemTime.month > 12) + if(systemTime.month > 11) { systemTime.year++; - systemTime.month = 1; + systemTime.month = 0; } } } @@ -170,8 +175,14 @@ NX_Error NX_TimeSet(NX_Time * time) systemTime.second = time->second; systemTime.year = time->year; - systemTime.weekDay = MakeWeekDay(time->year, time->month, time->day); - systemTime.yearDay = MakeYearDays(); + systemTime.weekDay = MakeWeekDay( + time->year + NX_TIME_YEAR_BASE, + time->month + 1, + time->day); + systemTime.yearDay = MakeYearDays( + systemTime.year + NX_TIME_YEAR_BASE, + systemTime.month + 1, + systemTime.day); return NX_EOK; } @@ -195,58 +206,6 @@ NX_Error NX_TimeGet(NX_Time * time) return NX_EOK; } -#define __TIME_HMS(h, m, s) ((NX_U16)((((h) & 0x1f) << 11) | \ - (((m) & 0x3f) << 5) | (((s) / 2) & 0x1f))) -#define __TIME_YMD(y, m, d) (((NX_U16)(((y)) & 0x7f) << 9) | \ - (((m) & 0xf) << 5) | ((d) & 0x1f)) - -#define __TIME_HOUR(date) ((NX_U32)(((date) >> 11) & 0x1f)) -#define __TIME_MINUTE(date) ((NX_U32)(((date) >> 5) & 0x3f)) -#define __TIME_SECOND(date) ((NX_U32)(((date) & 0x1f) * 2)) -#define __TIME_YEAR(date) ((NX_U32)((((date) >> 9) & 0x7f))) -#define __TIME_MONTH(date) ((NX_U32)(((date) >> 5) & 0xf)) -#define __TIME_DAY(date) ((NX_U32)((date) & 0x1f)) - -#define NX_TIME_DATE(year, month, day, hour, min, sec) ((__TIME_YMD(year, month, day) << 16) | __TIME_HMS(hour, min, sec)) - -#define NX_TIME_HOUR(date) __TIME_HOUR(date) -#define NX_TIME_MINUTE(date) __TIME_MINUTE(date) -#define NX_TIME_SECOND(date) __TIME_SECOND(date) -#define NX_TIME_YEAR(date) __TIME_YEAR(((date) >> 16)) -#define NX_TIME_MONTH(date) __TIME_MONTH(((date) >> 16)) -#define NX_TIME_DAY(date) __TIME_DAY(((date) >> 16)) - -NX_Date NX_TimeToDate(NX_Time * time) -{ - if (!time) - { - return 0; - } - return NX_TIME_DATE(time->year - NX_TIME_BASE_YEAR, time->month, time->day, time->hour, time->minute, time->second); -} - -NX_Error NX_DateToTime(NX_Date date, NX_Time * time) -{ - NX_Time localTime; - - if (!time) - { - return NX_EINVAL; - } - localTime.year = NX_TIME_YEAR(date) + NX_TIME_BASE_YEAR; - localTime.month = NX_TIME_MONTH(date); - localTime.day = NX_TIME_DAY(date); - localTime.hour = NX_TIME_HOUR(date); - localTime.minute = NX_TIME_MINUTE(date); - localTime.second = NX_TIME_SECOND(date); - - localTime.weekDay = MakeWeekDay(localTime.year, localTime.month, localTime.day); - localTime.yearDay = 0; - - *time = localTime; - return NX_EOK; -} - NX_PRIVATE void NX_TimeInit(void) { NX_Time time; diff --git a/src/time/time_stamp.c b/src/time/time_stamp.c new file mode 100644 index 0000000000000000000000000000000000000000..f1c67755f3e8bedaf15e27ecfc073a3902f3a227 --- /dev/null +++ b/src/time/time_stamp.c @@ -0,0 +1,208 @@ +/** + * Copyright (c) 2018-2022, NXOS Development Team + * SPDX-License-Identifier: Apache-2.0 + * + * Contains: system time + * + * Change Logs: + * Date Author Notes + * 2022-05-14 JasonHu Init + */ + +#include + +/* 2000-03-01 (mod 400 year, immediately after feb29 */ +#define LEAPOCH (946684800LL + 86400 * (31 + 29)) +#define DAYS_PER_400Y (365 * 400 + 97) +#define DAYS_PER_100Y (365 * 100 + 24) +#define DAYS_PER_4Y (365 * 4 + 1) + +int NX_TimeStampToTime(NX_TimeStamp t, NX_Time * tm) +{ + NX_TimeStamp days, secs, years; + int remdays, remsecs, remyears; + int qc_cycles, c_cycles, q_cycles; + int months; + int wday, yday, leap; + static const char days_in_month[] = { 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29 }; + + secs = t - LEAPOCH; + + days = secs / 86400; + remsecs = secs % 86400; + if(remsecs < 0) + { + remsecs += 86400; + days--; + } + + wday = (3 + days) % 7; + if(wday < 0) + { + wday += 7; + } + + qc_cycles = days / DAYS_PER_400Y; + remdays = days % DAYS_PER_400Y; + if(remdays < 0) + { + remdays += DAYS_PER_400Y; + qc_cycles--; + } + + c_cycles = remdays / DAYS_PER_100Y; + if(c_cycles == 4) + { + c_cycles--; + } + remdays -= c_cycles * DAYS_PER_100Y; + + q_cycles = remdays / DAYS_PER_4Y; + if(q_cycles == 25) + q_cycles--; + remdays -= q_cycles * DAYS_PER_4Y; + + remyears = remdays / 365; + if(remyears == 4) + { + remyears--; + } + remdays -= remyears * 365; + + leap = !remyears && (q_cycles || !c_cycles); + yday = remdays + 31 + 28 + leap; + if(yday >= 365 + leap) + { + yday -= 365 + leap; + } + + years = remyears + 4 * q_cycles + 100 * c_cycles + 400LL * qc_cycles; + + for(months = 0; days_in_month[months] <= remdays; months++) + remdays -= days_in_month[months]; + + if(months >= 10) + { + months -= 12; + years++; + } + + tm->year = years + 100; + tm->month = months + 2; + tm->day = remdays + 1; + tm->weekDay = wday; + tm->yearDay = yday; + + tm->hour = remsecs / 3600; + tm->minute = remsecs / 60 % 60; + tm->second = remsecs % 60; + + return 0; +} + +NX_PRIVATE NX_TimeStamp YearToSecs(NX_TimeStamp year, int * is_leap) +{ + if(year - 2ULL <= 136) + { + int y = year; + int leaps = (y - 68) >> 2; + if(!((y - 68) & 3)) + { + leaps--; + if(is_leap) + *is_leap = 1; + } + else if(is_leap) + { + *is_leap = 0; + } + return 31536000 * (y - 70) + 86400 * leaps; + } + + int cycles, centuries, leaps, rem; + + if(!is_leap) + is_leap = &(int ){ 0 }; + cycles = (year - 100) / 400; + rem = (year - 100) % 400; + if(rem < 0) + { + cycles--; + rem += 400; + } + if(!rem) + { + *is_leap = 1; + centuries = 0; + leaps = 0; + } + else + { + if(rem >= 200) + { + if(rem >= 300) + centuries = 3, rem -= 300; + else + centuries = 2, rem -= 200; + } + else + { + if(rem >= 100) + centuries = 1, rem -= 100; + else + centuries = 0; + } + if(!rem) + { + *is_leap = 0; + leaps = 0; + } + else + { + leaps = rem / 4U; + rem %= 4U; + *is_leap = !rem; + } + } + + leaps += 97 * cycles + 24 * centuries - *is_leap; + + return (year - 100) * 31536000LL + leaps * 86400LL + 946684800 + 86400; +} + +static int MonthToSecs(int month, int is_leap) +{ + static const int secs_through_month[] = { 0, 31 * 86400, 59 * 86400, 90 * 86400, 120 * 86400, + 151 * 86400, 181 * 86400, 212 * 86400, 243 * 86400, 273 * 86400, 304 * 86400, 334 * 86400 }; + int t = secs_through_month[month]; + if(is_leap && month >= 2) + { + t += 86400; + } + return t; +} + +NX_TimeStamp NX_TimeToTimeStamp(const NX_Time * tm) +{ + int is_leap; + NX_TimeStamp year = tm->year; + int month = tm->month; + if(month >= 12 || month < 0) + { + int adj = month / 12; + month %= 12; + if(month < 0) + { + adj--; + month += 12; + } + year += adj; + } + NX_TimeStamp t = YearToSecs(year, &is_leap); + t += MonthToSecs(month, is_leap); + t += 86400LL * (tm->day - 1); + t += 3600LL * tm->hour; + t += 60LL * tm->minute; + t += tm->second; + return t; +}