EmbeddedPkg/TimeBaseLib: Add function to get Week day.
[mirror_edk2.git] / EmbeddedPkg / Library / TimeBaseLib / TimeBaseLib.c
CommitLineData
b4895995
LL
1/** @file\r
2*\r
3* Copyright (c) 2016, Hisilicon Limited. All rights reserved.\r
4* Copyright (c) 2016, Linaro Limited. All rights reserved.\r
5*\r
6* This program and the accompanying materials\r
7* are licensed and made available under the terms and conditions of the BSD License\r
8* which accompanies this distribution. The full text of the license may be found at\r
9* http://opensource.org/licenses/bsd-license.php\r
10*\r
11* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13*\r
14**/\r
15\r
16#include <Uefi/UefiBaseType.h>\r
17#include <Uefi/UefiSpec.h>\r
18#include <Library/DebugLib.h>\r
19#include <Library/TimeBaseLib.h>\r
20\r
21/**\r
22 Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME\r
23 **/\r
24VOID\r
25EFIAPI\r
26EpochToEfiTime (\r
27 IN UINTN EpochSeconds,\r
28 OUT EFI_TIME *Time\r
29 )\r
30{\r
31 UINTN a;\r
32 UINTN b;\r
33 UINTN c;\r
34 UINTN d;\r
35 UINTN g;\r
36 UINTN j;\r
37 UINTN m;\r
38 UINTN y;\r
39 UINTN da;\r
40 UINTN db;\r
41 UINTN dc;\r
42 UINTN dg;\r
43 UINTN hh;\r
44 UINTN mm;\r
45 UINTN ss;\r
46 UINTN J;\r
47\r
48 J = (EpochSeconds / 86400) + 2440588;\r
49 j = J + 32044;\r
50 g = j / 146097;\r
51 dg = j % 146097;\r
52 c = (((dg / 36524) + 1) * 3) / 4;\r
53 dc = dg - (c * 36524);\r
54 b = dc / 1461;\r
55 db = dc % 1461;\r
56 a = (((db / 365) + 1) * 3) / 4;\r
57 da = db - (a * 365);\r
58 y = (g * 400) + (c * 100) + (b * 4) + a;\r
59 m = (((da * 5) + 308) / 153) - 2;\r
60 d = da - (((m + 4) * 153) / 5) + 122;\r
61\r
62 Time->Year = y - 4800 + ((m + 2) / 12);\r
63 Time->Month = ((m + 2) % 12) + 1;\r
64 Time->Day = d + 1;\r
65\r
66 ss = EpochSeconds % 60;\r
67 a = (EpochSeconds - ss) / 60;\r
68 mm = a % 60;\r
69 b = (a - mm) / 60;\r
70 hh = b % 24;\r
71\r
72 Time->Hour = hh;\r
73 Time->Minute = mm;\r
74 Time->Second = ss;\r
75 Time->Nanosecond = 0;\r
76\r
77}\r
78\r
79/**\r
91c31ff0 80 Calculate Epoch days\r
b4895995
LL
81 **/\r
82UINTN\r
83EFIAPI\r
91c31ff0 84EfiGetEpochDays (\r
b4895995
LL
85 IN EFI_TIME *Time\r
86 )\r
87{\r
88 UINTN a;\r
89 UINTN y;\r
90 UINTN m;\r
91 UINTN JulianDate; // Absolute Julian Date representation of the supplied Time\r
92 UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY\r
b4895995
LL
93\r
94 a = (14 - Time->Month) / 12 ;\r
95 y = Time->Year + 4800 - a;\r
96 m = Time->Month + (12*a) - 3;\r
97\r
98 JulianDate = Time->Day + ((153*m + 2)/5) + (365*y) + (y/4) - (y/100) + (y/400) - 32045;\r
99\r
100 ASSERT (JulianDate >= EPOCH_JULIAN_DATE);\r
101 EpochDays = JulianDate - EPOCH_JULIAN_DATE;\r
102\r
91c31ff0
MA
103 return EpochDays;\r
104}\r
105/**\r
106 Converts EFI_TIME to Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC)\r
107 **/\r
108UINTN\r
109EFIAPI\r
110EfiTimeToEpoch (\r
111 IN EFI_TIME *Time\r
112 )\r
113{\r
114 UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY\r
115 UINTN EpochSeconds;\r
116\r
117 EpochDays = EfiGetEpochDays (Time);\r
118\r
b4895995
LL
119 EpochSeconds = (EpochDays * SEC_PER_DAY) + ((UINTN)Time->Hour * SEC_PER_HOUR) + (Time->Minute * SEC_PER_MIN) + Time->Second;\r
120\r
121 return EpochSeconds;\r
122}\r
123\r
91c31ff0
MA
124/**\r
125 returns Day of the week [0-6] 0=Sunday\r
126 **/\r
127UINTN\r
128EfiTimeToWday (\r
129 IN EFI_TIME *Time\r
130 )\r
131{\r
132 UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY\r
133\r
134 EpochDays = EfiGetEpochDays (Time);\r
135\r
136 // 4=1/1/1970 was a Thursday\r
137\r
138 return (EpochDays + 4) % 7;\r
139}\r
140\r
b4895995
LL
141BOOLEAN\r
142EFIAPI\r
143IsLeapYear (\r
144 IN EFI_TIME *Time\r
145 )\r
146{\r
147 if (Time->Year % 4 == 0) {\r
148 if (Time->Year % 100 == 0) {\r
149 if (Time->Year % 400 == 0) {\r
150 return TRUE;\r
151 } else {\r
152 return FALSE;\r
153 }\r
154 } else {\r
155 return TRUE;\r
156 }\r
157 } else {\r
158 return FALSE;\r
159 }\r
160}\r
161\r
162BOOLEAN\r
163EFIAPI\r
164IsDayValid (\r
165 IN EFI_TIME *Time\r
166 )\r
167{\r
168 STATIC CONST INTN DayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\r
169\r
170 if (Time->Day < 1 ||\r
171 Time->Day > DayOfMonth[Time->Month - 1] ||\r
172 (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))\r
173 ) {\r
174 return FALSE;\r
175 }\r
176\r
177 return TRUE;\r
178}\r
179\r
180BOOLEAN\r
181EFIAPI\r
182IsTimeValid(\r
183 IN EFI_TIME *Time\r
184 )\r
185{\r
186 // Check the input parameters are within the range specified by UEFI\r
187 if ((Time->Year < 2000) ||\r
188 (Time->Year > 2099) ||\r
189 (Time->Month < 1 ) ||\r
190 (Time->Month > 12 ) ||\r
191 (!IsDayValid (Time) ) ||\r
192 (Time->Hour > 23 ) ||\r
193 (Time->Minute > 59 ) ||\r
194 (Time->Second > 59 ) ||\r
195 (Time->Nanosecond > 999999999) ||\r
196 (!((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440)))) ||\r
197 (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)))\r
198 ) {\r
199 return FALSE;\r
200 }\r
201\r
202 return TRUE;\r
203}\r