1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - RTC - libraries
3 File: convert.c
4
5 Copyright 2003-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-18#$
14 $Rev: 8573 $
15 $Author:$
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro/types.h>
19 #include <nitro/rtc.h>
20
21
22 /*---------------------------------------------------------------------------*
23 Static Variable Definitions
24 *---------------------------------------------------------------------------*/
25 static s32 sDayOfYear[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
26
27
28 /*---------------------------------------------------------------------------*
29 Internal Function Declarations
30 *---------------------------------------------------------------------------*/
31
32 // Simple leap year determination (if leap year, TRUE)
33 // * Limited to the range of years that the RTC can take, 2000-2099.
RTCi_IsLeapYear(u32 year)34 static inline BOOL RTCi_IsLeapYear(u32 year)
35 {
36 // A leap year is a year that is divisible by four and not divisible by 100, or a year that is divisible by 400
37 return !((year & 0x03));
38 }
39
40 /*---------------------------------------------------------------------------*
41 Function Definitions
42 *---------------------------------------------------------------------------*/
43
44 /*---------------------------------------------------------------------------*
45 Name: RTC_ConvertDateToDay
46
47 Description: Converts date data from RTCDate type to the total number of days since the year 2000.
48
49 Arguments: date - Pointer to date data
50
51 Returns: The total number of days since January 1, 2000.
52 *---------------------------------------------------------------------------*/
RTC_ConvertDateToDay(const RTCDate * date)53 s32 RTC_ConvertDateToDay(const RTCDate *date)
54 {
55 s32 dayNum;
56
57 if (date->year >= 100
58 || (date->month < 1) || (date->month > 12)
59 || (date->day < 1) || (date->day > 31)
60 || (date->week >= RTC_WEEK_MAX) || (date->month < 1) || (date->month > 12))
61 {
62 return -1;
63 }
64
65 // Convert the month and day to the number of days
66 dayNum = (s32)(date->day - 1);
67 dayNum += sDayOfYear[date->month - 1];
68 if ((date->month >= 3) && RTCi_IsLeapYear(date->year))
69 {
70 // In a leap year, increment days by one starting in March
71 dayNum++;
72 }
73
74 // Convert year to number of days
75 dayNum += date->year * 365;
76 // Calculate the number of leap years up to the specified year -1, and add that number of days
77 // Because date->year is only from 0 up to 99, the leap year calculation is a simplified version.
78 dayNum += (date->year + 3) / 4;
79
80 return dayNum;
81 }
82
83 /*---------------------------------------------------------------------------*
84 Name: RTCi_ConvertTimeToSecond
85
86 Description: Converts time data in RTCTime type to the total number of seconds since 0:00.
87
88 Arguments: time - Pointer to the time data
89
90 Returns: Total number of seconds since 0:00.
91 *---------------------------------------------------------------------------*/
RTCi_ConvertTimeToSecond(const RTCTime * time)92 s32 RTCi_ConvertTimeToSecond(const RTCTime *time)
93 {
94 return (s32)((time->hour * 60 + time->minute) * 60 + time->second);
95 }
96
97 /*---------------------------------------------------------------------------*
98 Name: RTC_ConvertDateTimeToSecond
99
100 Description: Converts date and time data in RTCDate and RTCTime types to total number of seconds.
101
102 Arguments: date - Pointer to date data
103 time - Pointer to the time data
104
105 Returns: Total number of seconds since 0:00, January 1, 2000, local time.
106 *---------------------------------------------------------------------------*/
RTC_ConvertDateTimeToSecond(const RTCDate * date,const RTCTime * time)107 s64 RTC_ConvertDateTimeToSecond(const RTCDate *date, const RTCTime *time)
108 {
109 s32 day, sec;
110 day = RTC_ConvertDateToDay(date);
111 if (day == -1)
112 {
113 return -1;
114 }
115 sec = RTCi_ConvertTimeToSecond(time);
116 if (sec == -1)
117 {
118 return -1;
119 }
120 return ((s64)day) * (60 * 60 * 24) + sec;
121 }
122
123 /*---------------------------------------------------------------------------*
124 Name: RTC_ConvertDayToDate
125
126 Description: Converts the total number of days since the year 2000 to date data in RTCDate type.
127
128 Arguments: date - Pointer to save destination date data
129 day - The total number of days since January 1, 2000
130
131 Returns: None.
132 *---------------------------------------------------------------------------*/
RTC_ConvertDayToDate(RTCDate * date,s32 day)133 void RTC_ConvertDayToDate(RTCDate *date, s32 day)
134 {
135 u32 year;
136 s32 month;
137
138 if (day < 0)
139 {
140 day = 0;
141 }
142 if (day > 36524)
143 {
144 day = 36524;
145 }
146
147 // January 1, 2000 was a Saturday
148 date->week = (RTCWeek)((day + 6) % 7);
149
150 for (year = 0; year < 99; year++)
151 {
152 s32 prev = day;
153 day -= (RTCi_IsLeapYear(year)) ? 366 : 365;
154 if (day < 0)
155 {
156 day = prev;
157 break;
158 }
159 }
160 if (day > 365)
161 {
162 day = 365;
163 }
164
165 date->year = year;
166
167 if (RTCi_IsLeapYear(year))
168 {
169 if (day < 31 + 29)
170 {
171 if (day < 31)
172 {
173 month = 1;
174 }
175 else
176 {
177 month = 2;
178 day -= 31;
179 }
180 date->month = (u32)month;
181 date->day = (u32)(day + 1);
182 return;
183 }
184 else
185 {
186 day--;
187 }
188 }
189
190 for (month = 11; month >= 0; month--)
191 {
192 if (day >= sDayOfYear[month])
193 {
194 date->month = (u32)(month + 1);
195 date->day = (u32)(day - sDayOfYear[month] + 1);
196 return;
197 }
198 }
199
200 SDK_ASSERT("Internal Error.");
201 }
202
203 /*---------------------------------------------------------------------------*
204 Name: RTCi_ConvertSecondToTime
205
206 Description: Converts the total number of seconds since 0:00 to time data in RTCTime type.
207
208 Arguments: time - Pointer to save destination date data
209 sec - Total number of seconds since 0:00
210
211 Returns: None.
212 *---------------------------------------------------------------------------*/
RTCi_ConvertSecondToTime(RTCTime * time,s32 sec)213 void RTCi_ConvertSecondToTime(RTCTime *time, s32 sec)
214 {
215 if (sec < 0)
216 {
217 sec = 0;
218 }
219 if (sec > 86399)
220 {
221 sec = 86399;
222 }
223
224 time->second = (u32)(sec % 60);
225 sec /= 60;
226 time->minute = (u32)(sec % 60);
227 sec /= 60;
228 time->hour = (u32)sec;
229 }
230
231 /*---------------------------------------------------------------------------*
232 Name: RTC_ConvertDateTimeToSecond
233
234 Description: Converts total number of seconds to date and time data in RTCDate and RTCTime types.
235
236 Arguments: date - Pointer to save destination date data
237 time - Pointer to the save destination time data
238 sec - Total number of seconds since 0:00, January 1, 2000
239
240 Returns: None.
241 *---------------------------------------------------------------------------*/
RTC_ConvertSecondToDateTime(RTCDate * date,RTCTime * time,s64 sec)242 void RTC_ConvertSecondToDateTime(RTCDate *date, RTCTime *time, s64 sec)
243 {
244 if (sec < 0)
245 {
246 sec = 0;
247 }
248 else if (sec > 3155759999)
249 {
250 sec = 3155759999;
251 }
252 RTCi_ConvertSecondToTime(time, (s32)(sec % 86400));
253 RTC_ConvertDayToDate(date, (s32)(sec / 86400));
254 }
255
256 /*---------------------------------------------------------------------------*
257 Name: RTC_GetDayOfWeek
258
259 Description: Returns the day of the week based on RTCDate type data.
260 (This is found based on a calculation rather than using the day of the week inside RTCDate.)
261
262 Arguments: date - Pointer to date data
263
264 Returns: Day of week RTC_WEEK_xxxx.
265 *---------------------------------------------------------------------------*/
RTC_GetDayOfWeek(RTCDate * date)266 RTCWeek RTC_GetDayOfWeek(RTCDate *date)
267 {
268 int cent;
269 int year = (int)(2000 + date->year);
270 int month = (int)date->month;
271 int day = (int)date->day;
272
273 month -= 2;
274 if (month < 1)
275 {
276 month += 12;
277 --year;
278 }
279
280 cent = year / 100;
281 year %= 100;
282 return (RTCWeek)(((26 * month - 2) / 10 + day + year + year / 4 + cent / 4 + 5 * cent) % 7);
283 // Sunday, Monday, ... Saturday are defined as 0 through 6 for RTC_WEEK_xxxx
284 }
285
286 /*---------------------------------------------------------------------------*
287 End of file
288 *---------------------------------------------------------------------------*/
289