1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "rtc_base.h"
10 #include "platform_log.h"
11 #define HDF_UINT32_MAX 0xffffffffu
12
13 #define HDF_LOG_TAG rtc_base
14
RtcGetMonthDays(const uint8_t isLeapYear,const uint8_t month)15 uint8_t RtcGetMonthDays(const uint8_t isLeapYear, const uint8_t month)
16 {
17 uint8_t days;
18 uint8_t oddMonth;
19
20 if (IS_INVALID_MONTH(month) || (isLeapYear > RTC_TRUE)) {
21 return 0;
22 }
23
24 if (month == RTC_FEBRUARY) {
25 days = RTC_TWO_MONTH_DAY + isLeapYear;
26 } else {
27 oddMonth = (month >= RTC_AUGUST) ? (month - RTC_UNIT_DIFF) : month;
28 days = (oddMonth & RTC_ODD_MONTH_MASK) ? RTC_GREAT_MONTH_DAY : RTC_SMALL_MONTH_DAY;
29 }
30 return days;
31 }
32
RtcIsInvalidDay(const uint8_t day,const uint8_t month,const uint16_t year)33 uint8_t RtcIsInvalidDay(const uint8_t day, const uint8_t month, const uint16_t year)
34 {
35 uint8_t maxDay;
36 maxDay = RtcGetMonthDays(IS_LEAP_YEAR(year), month);
37
38 return ((day == 0) || (day > maxDay)) ? RTC_TRUE : RTC_FALSE;
39 }
40
RtcIsInvalid(const struct RtcTime * time)41 uint8_t RtcIsInvalid(const struct RtcTime *time)
42 {
43 if (time == NULL) {
44 HDF_LOGE("RtcIsInvalid: time is null!");
45 return RTC_FALSE;
46 }
47
48 return (IS_INVALID_YEAR(time->year) || IS_INVALID_MONTH(time->month) ||
49 (RtcIsInvalidDay(time->day, time->month, time->year) == RTC_TRUE) ||
50 IS_INVALID_HOUR(time->hour) || IS_INVALID_MIN(time->minute) ||
51 IS_INVALID_SECOND(time->second) || IS_INVALID_MS(time->millisecond));
52 }
53
RtcGetWeekDay(const struct RtcTime * time)54 uint8_t RtcGetWeekDay(const struct RtcTime *time)
55 {
56 uint32_t days;
57 int8_t month;
58 uint16_t year;
59
60 if ((time == NULL) || IS_INVALID_MONTH(time->month) || IS_INVALID_YEAR(time->year) ||
61 (RtcIsInvalidDay(time->day, time->month, time->year) == RTC_TRUE)) {
62 HDF_LOGE("RtcGetWeekDay: time is invalid!");
63 return RTC_FALSE;
64 }
65
66 days = time->day - RTC_UNIT_DIFF;
67 month = time->month;
68 while (--month >= RTC_JANUARY) {
69 days += RtcGetMonthDays(IS_LEAP_YEAR(time->year), month);
70 }
71
72 year = time->year;
73 while (--year >= RTC_BEGIN_YEAR) {
74 days += RTC_YEAR_DAYS(year);
75 }
76
77 if (days > (HDF_UINT32_MAX - RTC_BEGIN_WEEKDAY)) {
78 HDF_LOGE("RtcGetWeekDay: days is invalid!");
79 return RTC_FALSE;
80 }
81 return ((RTC_BEGIN_WEEKDAY + days - RTC_UNIT_DIFF) % RTC_MAX_WEEKDAY + RTC_UNIT_DIFF);
82 }
83
84 #ifndef __KERNEL__
RtcTimeToTimestamp(const struct RtcTime * time)85 uint64_t RtcTimeToTimestamp(const struct RtcTime *time)
86 {
87 uint64_t seconds;
88 uint32_t days;
89 uint16_t year;
90 int8_t month;
91
92 if (time == NULL) {
93 HDF_LOGE("RtcTimeToTimestamp: time is null!");
94 return RTC_FALSE;
95 }
96 PLAT_LOGV("RtcToTimestamp: year-month-day hour:min:second ms %04u-%02u-%02u %02u:%02u:%02u .%03u",
97 time->year, time->month, time->day, time->hour, time->minute, time->second, time->millisecond);
98 if (RtcIsInvalid(time) == RTC_TRUE) {
99 HDF_LOGE("RtcTimeToTimestamp: time invalid");
100 return 0;
101 }
102
103 seconds = ((uint64_t)time->hour * RTC_MAX_MINUTE + time->minute) * RTC_MAX_SECOND + time->second;
104 days = time->day - RTC_UNIT_DIFF;
105 month = time->month;
106 year = time->year;
107
108 for (month--; month >= RTC_JANUARY; month--) {
109 days += RtcGetMonthDays(IS_LEAP_YEAR(time->year), month);
110 }
111
112 for (year--; year >= RTC_BEGIN_YEAR; year--) {
113 days += RTC_YEAR_DAYS(year);
114 }
115
116 seconds += days * RTC_DAY_SECONDS;
117 return seconds;
118 }
119
TimestampToRtcTime(struct RtcTime * time,const uint64_t seconds)120 void TimestampToRtcTime(struct RtcTime *time, const uint64_t seconds)
121 {
122 uint32_t daySeconds = (uint32_t)(seconds % RTC_DAY_SECONDS);
123 uint32_t days = (uint32_t)(seconds / RTC_DAY_SECONDS);
124
125 if (time == NULL) {
126 HDF_LOGE("TimestampToRtcTime: time is null!");
127 return;
128 }
129
130 time->year = RTC_BEGIN_YEAR;
131 while (days >= RTC_YEAR_DAYS(time->year)) {
132 days -= RTC_YEAR_DAYS(time->year);
133 time->year++;
134 }
135
136 time->month = RTC_JANUARY;
137 while (days >= RtcGetMonthDays(IS_LEAP_YEAR(time->year), time->month)) {
138 days -= RtcGetMonthDays(IS_LEAP_YEAR(time->year), time->month);
139 time->month++;
140 }
141
142 time->day = days;
143 time->second = daySeconds % RTC_MAX_SECOND;
144 time->minute = (daySeconds % RTC_HOUR_SECONDS) / RTC_MAX_MINUTE;
145 time->hour = daySeconds / RTC_HOUR_SECONDS;
146
147 time->day += RTC_UNIT_DIFF;
148 time->weekday = RtcGetWeekDay(time);
149 PLAT_LOGV("TimestampToRtc: year-month-day weekday hour:min:second ms %04u-%02u-%02u %u %02u:%02u:%02u .%03u",
150 time->year, time->month, time->day, time->weekday, time->hour, time->minute, time->second, time->millisecond);
151 }
152 #endif
153