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