1f9f848faSopenharmony_ci/* 2f9f848faSopenharmony_ci * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. 3f9f848faSopenharmony_ci * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. 4f9f848faSopenharmony_ci * 5f9f848faSopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 6f9f848faSopenharmony_ci * are permitted provided that the following conditions are met: 7f9f848faSopenharmony_ci * 8f9f848faSopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of 9f9f848faSopenharmony_ci * conditions and the following disclaimer. 10f9f848faSopenharmony_ci * 11f9f848faSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list 12f9f848faSopenharmony_ci * of conditions and the following disclaimer in the documentation and/or other materials 13f9f848faSopenharmony_ci * provided with the distribution. 14f9f848faSopenharmony_ci * 15f9f848faSopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used 16f9f848faSopenharmony_ci * to endorse or promote products derived from this software without specific prior written 17f9f848faSopenharmony_ci * permission. 18f9f848faSopenharmony_ci * 19f9f848faSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20f9f848faSopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21f9f848faSopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22f9f848faSopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 23f9f848faSopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24f9f848faSopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25f9f848faSopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26f9f848faSopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27f9f848faSopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28f9f848faSopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29f9f848faSopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30f9f848faSopenharmony_ci */ 31f9f848faSopenharmony_ci 32f9f848faSopenharmony_ci#include "tzdst.h" 33f9f848faSopenharmony_ci#include "tzdst_pri.h" 34f9f848faSopenharmony_ci#include "stdio.h" 35f9f848faSopenharmony_ci#include "stdlib.h" 36f9f848faSopenharmony_ci#include "unistd.h" 37f9f848faSopenharmony_ci#include "los_printf.h" 38f9f848faSopenharmony_ci#include "los_typedef.h" 39f9f848faSopenharmony_ci#include "securec.h" 40f9f848faSopenharmony_ci 41f9f848faSopenharmony_ci 42f9f848faSopenharmony_ci/* 2: leap year or normal year */ 43f9f848faSopenharmony_ciSTATIC const INT32 g_monLengths[2][MONSPERYEAR] = { 44f9f848faSopenharmony_ci { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 45f9f848faSopenharmony_ci { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 46f9f848faSopenharmony_ci}; 47f9f848faSopenharmony_ci 48f9f848faSopenharmony_ci/* Time Zone functions */ 49f9f848faSopenharmony_ci#define IS_NUM(x) (((x) >= '0') && ((x) <= '9')) 50f9f848faSopenharmony_ci 51f9f848faSopenharmony_cilong int timezone; 52f9f848faSopenharmony_ci 53f9f848faSopenharmony_ciSTATIC VOID BufferInsert(CHAR *buf, size_t bufLen, size_t positions, CHAR data) 54f9f848faSopenharmony_ci{ 55f9f848faSopenharmony_ci if (bufLen <= positions) { 56f9f848faSopenharmony_ci return; 57f9f848faSopenharmony_ci } 58f9f848faSopenharmony_ci if (memmove_s(&buf[positions + 1], bufLen - positions - 1, &buf[positions], bufLen - positions - 1) != EOK) { 59f9f848faSopenharmony_ci PRINTK("%s falied \n", __FUNCTION__); 60f9f848faSopenharmony_ci return; 61f9f848faSopenharmony_ci } 62f9f848faSopenharmony_ci 63f9f848faSopenharmony_ci buf[positions] = data; 64f9f848faSopenharmony_ci} 65f9f848faSopenharmony_ci 66f9f848faSopenharmony_ci#define OPERATE_OFF 3 67f9f848faSopenharmony_ci#define HOUR_HIGH_OFF 4 68f9f848faSopenharmony_ci#define HOUR_LOW_OFF 5 69f9f848faSopenharmony_ci#define MIN_HIGH_OFF 7 70f9f848faSopenharmony_ci#define MIN_LOW_OFF 8 71f9f848faSopenharmony_ci#define SEC_HIGH_OFF 10 72f9f848faSopenharmony_ci#define SEC_LOW_OFF 11 73f9f848faSopenharmony_ci 74f9f848faSopenharmony_ci/* 75f9f848faSopenharmony_ci * tzn[+/-]hh[:mm[:ss]][dzn] 76f9f848faSopenharmony_ci * tzn + 11 :30 : 7 dzn 77f9f848faSopenharmony_ci * tzn - 9 : 7 :11 dzn 78f9f848faSopenharmony_ci */ 79f9f848faSopenharmony_ciSTATIC BOOL TimezoneFormat(CHAR *standardString, size_t bufLen) 80f9f848faSopenharmony_ci{ 81f9f848faSopenharmony_ci if ((standardString[OPERATE_OFF] == '-') || (standardString[OPERATE_OFF] == '+')) { 82f9f848faSopenharmony_ci if (!IS_NUM(standardString[OPERATE_OFF + 1])) { 83f9f848faSopenharmony_ci return FALSE; 84f9f848faSopenharmony_ci } 85f9f848faSopenharmony_ci } else if (IS_NUM(standardString[OPERATE_OFF])) { 86f9f848faSopenharmony_ci BufferInsert(standardString, bufLen, OPERATE_OFF, '+'); /* no operate is default to add */ 87f9f848faSopenharmony_ci } else { 88f9f848faSopenharmony_ci return FALSE; 89f9f848faSopenharmony_ci } 90f9f848faSopenharmony_ci 91f9f848faSopenharmony_ci if (!IS_NUM(standardString[HOUR_LOW_OFF])) { 92f9f848faSopenharmony_ci BufferInsert(standardString, bufLen, HOUR_HIGH_OFF, '0'); /* hour only one bit, padding 0 to high bit */ 93f9f848faSopenharmony_ci } 94f9f848faSopenharmony_ci 95f9f848faSopenharmony_ci if (standardString[HOUR_LOW_OFF + 1] == ':') { 96f9f848faSopenharmony_ci if (!IS_NUM(standardString[MIN_HIGH_OFF])) { 97f9f848faSopenharmony_ci return FALSE; 98f9f848faSopenharmony_ci } else if (!IS_NUM(standardString[MIN_LOW_OFF])) { 99f9f848faSopenharmony_ci BufferInsert(standardString, bufLen, MIN_HIGH_OFF, '0'); /* minute only one bit, padding 0 to high bit */ 100f9f848faSopenharmony_ci } 101f9f848faSopenharmony_ci } else { 102f9f848faSopenharmony_ci /* no minute bits, default is 0 */ 103f9f848faSopenharmony_ci BufferInsert(standardString, bufLen, HOUR_LOW_OFF + 1, ':'); 104f9f848faSopenharmony_ci BufferInsert(standardString, bufLen, MIN_HIGH_OFF, '0'); 105f9f848faSopenharmony_ci BufferInsert(standardString, bufLen, MIN_LOW_OFF, '0'); 106f9f848faSopenharmony_ci } 107f9f848faSopenharmony_ci 108f9f848faSopenharmony_ci if (standardString[MIN_LOW_OFF + 1] == ':') { 109f9f848faSopenharmony_ci if (!IS_NUM(standardString[SEC_HIGH_OFF])) { 110f9f848faSopenharmony_ci return FALSE; 111f9f848faSopenharmony_ci } else if (!IS_NUM(standardString[SEC_LOW_OFF])) { 112f9f848faSopenharmony_ci BufferInsert(standardString, bufLen, SEC_HIGH_OFF, '0'); /* second only one bit, padding 0 to high bit */ 113f9f848faSopenharmony_ci } 114f9f848faSopenharmony_ci } else { 115f9f848faSopenharmony_ci /* no second bits, default is 0 */ 116f9f848faSopenharmony_ci BufferInsert(standardString, bufLen, MIN_LOW_OFF + 1, ':'); 117f9f848faSopenharmony_ci BufferInsert(standardString, bufLen, SEC_HIGH_OFF, '0'); 118f9f848faSopenharmony_ci BufferInsert(standardString, bufLen, SEC_LOW_OFF, '0'); 119f9f848faSopenharmony_ci } 120f9f848faSopenharmony_ci return TRUE; 121f9f848faSopenharmony_ci} 122f9f848faSopenharmony_ci 123f9f848faSopenharmony_ciSTATIC INLINE INT32 StringToDigital(CHAR high, CHAR low) 124f9f848faSopenharmony_ci{ 125f9f848faSopenharmony_ci /* 10: decimal base number */ 126f9f848faSopenharmony_ci return ((high - '0') * 10) + (low - '0'); 127f9f848faSopenharmony_ci} 128f9f848faSopenharmony_ci 129f9f848faSopenharmony_ci/* 130f9f848faSopenharmony_ci * tzn[+/-]hh[:mm[:ss]][dzn] 131f9f848faSopenharmony_ci * tzn + 11 :30 : 7 dzn 132f9f848faSopenharmony_ci * tzn - 9 : 7 :11 dzn 133f9f848faSopenharmony_ci */ 134f9f848faSopenharmony_civoid settimezone(const char *buff) 135f9f848faSopenharmony_ci{ 136f9f848faSopenharmony_ci#define STANDARD_TZ_LEN 15 137f9f848faSopenharmony_ci#define MIN_BUF_LEN (OPERATE_OFF + 1) 138f9f848faSopenharmony_ci INT32 hour; 139f9f848faSopenharmony_ci INT32 minute; 140f9f848faSopenharmony_ci INT32 second; 141f9f848faSopenharmony_ci size_t buffLen; 142f9f848faSopenharmony_ci CHAR standardString[STANDARD_TZ_LEN] = {0}; 143f9f848faSopenharmony_ci 144f9f848faSopenharmony_ci if (buff == NULL) { 145f9f848faSopenharmony_ci goto ERROR; 146f9f848faSopenharmony_ci } 147f9f848faSopenharmony_ci 148f9f848faSopenharmony_ci buffLen = strlen(buff); 149f9f848faSopenharmony_ci if (buffLen < MIN_BUF_LEN) { 150f9f848faSopenharmony_ci goto ERROR; 151f9f848faSopenharmony_ci } 152f9f848faSopenharmony_ci 153f9f848faSopenharmony_ci (VOID)memset_s(standardString, STANDARD_TZ_LEN, '#', STANDARD_TZ_LEN); 154f9f848faSopenharmony_ci if (memcpy_s(standardString, STANDARD_TZ_LEN, buff, buffLen) != EOK) { 155f9f848faSopenharmony_ci goto ERROR; 156f9f848faSopenharmony_ci } 157f9f848faSopenharmony_ci 158f9f848faSopenharmony_ci if (!TimezoneFormat(standardString, STANDARD_TZ_LEN)) { 159f9f848faSopenharmony_ci goto ERROR; 160f9f848faSopenharmony_ci } 161f9f848faSopenharmony_ci 162f9f848faSopenharmony_ci hour = StringToDigital(standardString[HOUR_HIGH_OFF], standardString[HOUR_LOW_OFF]); 163f9f848faSopenharmony_ci minute = StringToDigital(standardString[MIN_HIGH_OFF], standardString[MIN_LOW_OFF]); 164f9f848faSopenharmony_ci second = StringToDigital(standardString[SEC_HIGH_OFF], standardString[SEC_LOW_OFF]); 165f9f848faSopenharmony_ci /* [-12:00:00, +14:00:00] limits */ 166f9f848faSopenharmony_ci if ((minute > 59 || second > 59) || 167f9f848faSopenharmony_ci ((standardString[OPERATE_OFF] == '-') && ((hour > 12) || ((hour == 12) && ((minute != 0) || (second != 0))))) || 168f9f848faSopenharmony_ci ((standardString[OPERATE_OFF] == '+') && ((hour > 14) || ((hour == 14) && ((minute != 0) || (second != 0)))))) { 169f9f848faSopenharmony_ci goto ERROR; 170f9f848faSopenharmony_ci } 171f9f848faSopenharmony_ci 172f9f848faSopenharmony_ci if (lock()) { 173f9f848faSopenharmony_ci goto ERROR; 174f9f848faSopenharmony_ci } 175f9f848faSopenharmony_ci 176f9f848faSopenharmony_ci /* 1h: 3600s, 1min: 60s */ 177f9f848faSopenharmony_ci timezone = hour * 3600 + minute * 60 + second; 178f9f848faSopenharmony_ci if (standardString[OPERATE_OFF] == '-') { 179f9f848faSopenharmony_ci timezone = -timezone; 180f9f848faSopenharmony_ci } 181f9f848faSopenharmony_ci 182f9f848faSopenharmony_ci unlock(); 183f9f848faSopenharmony_ci 184f9f848faSopenharmony_ci return; 185f9f848faSopenharmony_ci 186f9f848faSopenharmony_ciERROR: 187f9f848faSopenharmony_ci PRINT_ERR("TZ file data error\n"); 188f9f848faSopenharmony_ci} 189f9f848faSopenharmony_ci 190f9f848faSopenharmony_ci/* DST functions */ 191f9f848faSopenharmony_ci#define DST_STR_LEN_FORMAT_MDAY 15 /* for example "Feb-03 03:00:00" */ 192f9f848faSopenharmony_ci#define DST_STR_LEN_FORMAT_WDAY 20 /* for example "Oct-1st-Fri 02:59:59" */ 193f9f848faSopenharmony_ci#define DST_SET_LENGTH_MAX (DST_STR_LEN_FORMAT_WDAY + 1) 194f9f848faSopenharmony_ci 195f9f848faSopenharmony_ci#define MONTH_NAME_LEN 3 196f9f848faSopenharmony_ciSTATIC const CHAR *g_strMonth[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", 197f9f848faSopenharmony_ci "Aug", "Sep", "Oct", "Nov", "Dec" }; 198f9f848faSopenharmony_ciSTATIC const CHAR *g_strMonthWeek[] = { "1st", "2nd", "3rd", "4th", "5th" }; 199f9f848faSopenharmony_ciSTATIC const CHAR *g_strWeekDay[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 200f9f848faSopenharmony_ci 201f9f848faSopenharmony_ciSTATIC BOOL g_isDstWork = FALSE; 202f9f848faSopenharmony_ciINT32 g_dstForwardSeconds = 0; 203f9f848faSopenharmony_ciSTATIC CHAR g_strDstStart[DST_SET_LENGTH_MAX] = {0}; 204f9f848faSopenharmony_ciSTATIC CHAR g_strDstEnd[DST_SET_LENGTH_MAX] = {0}; 205f9f848faSopenharmony_ci 206f9f848faSopenharmony_ciINT32 DstForwardSecondGet(VOID) 207f9f848faSopenharmony_ci{ 208f9f848faSopenharmony_ci return g_dstForwardSeconds; 209f9f848faSopenharmony_ci} 210f9f848faSopenharmony_ci 211f9f848faSopenharmony_ciSTATIC INT32 GetMonthFromString(const CHAR *strMonth) 212f9f848faSopenharmony_ci{ 213f9f848faSopenharmony_ci UINT32 index; 214f9f848faSopenharmony_ci for (index = 0; index < sizeof(g_strMonth) / sizeof(CHAR *); index++) { 215f9f848faSopenharmony_ci if (strncmp(strMonth, g_strMonth[index], MONTH_NAME_LEN) == 0) { 216f9f848faSopenharmony_ci /* A legal month is from 0 to 11. */ 217f9f848faSopenharmony_ci return (int)index; 218f9f848faSopenharmony_ci } 219f9f848faSopenharmony_ci } 220f9f848faSopenharmony_ci 221f9f848faSopenharmony_ci return -1; 222f9f848faSopenharmony_ci} 223f9f848faSopenharmony_ci 224f9f848faSopenharmony_ciSTATIC INT32 GetWeekDayFromString(const CHAR *strWeekDay) 225f9f848faSopenharmony_ci{ 226f9f848faSopenharmony_ci UINT32 index; 227f9f848faSopenharmony_ci for (index = 0; index < sizeof(g_strWeekDay) / sizeof(CHAR *); index++) { 228f9f848faSopenharmony_ci if (strncmp(strWeekDay, g_strWeekDay[index], MONTH_NAME_LEN) == 0) { 229f9f848faSopenharmony_ci /* Day of the week (0-6, Sunday = 0) */ 230f9f848faSopenharmony_ci return (INT32)index; 231f9f848faSopenharmony_ci } 232f9f848faSopenharmony_ci } 233f9f848faSopenharmony_ci 234f9f848faSopenharmony_ci return -1; 235f9f848faSopenharmony_ci} 236f9f848faSopenharmony_ci 237f9f848faSopenharmony_ciSTATIC INT32 GetMonthWeekFromString(const CHAR *strMonthWeek) 238f9f848faSopenharmony_ci{ 239f9f848faSopenharmony_ci UINT32 index; 240f9f848faSopenharmony_ci for (index = 0; index < sizeof(g_strMonthWeek) / sizeof(CHAR *); index++) { 241f9f848faSopenharmony_ci if (strncmp(strMonthWeek, g_strMonthWeek[index], MONTH_NAME_LEN) == 0) { 242f9f848faSopenharmony_ci /* Month of the week (1-5) */ 243f9f848faSopenharmony_ci return (INT32)(index + 1); 244f9f848faSopenharmony_ci } 245f9f848faSopenharmony_ci } 246f9f848faSopenharmony_ci 247f9f848faSopenharmony_ci return -1; 248f9f848faSopenharmony_ci} 249f9f848faSopenharmony_ci 250f9f848faSopenharmony_ci/* Day of the month 1 ~ 31 */ 251f9f848faSopenharmony_ciSTATIC INT32 GetMonthDayFromString(INT32 month, const CHAR *strMonDay) 252f9f848faSopenharmony_ci{ 253f9f848faSopenharmony_ci INT32 monDay; 254f9f848faSopenharmony_ci 255f9f848faSopenharmony_ci if (((strMonDay[0] < '0') || (strMonDay[0] > '9')) || 256f9f848faSopenharmony_ci ((strMonDay[1] < '0') || (strMonDay[1] > '9'))) { 257f9f848faSopenharmony_ci return -1; 258f9f848faSopenharmony_ci } 259f9f848faSopenharmony_ci 260f9f848faSopenharmony_ci monDay = StringToDigital(strMonDay[0], strMonDay[1]); 261f9f848faSopenharmony_ci if (monDay > 31) { 262f9f848faSopenharmony_ci return -1; 263f9f848faSopenharmony_ci } 264f9f848faSopenharmony_ci 265f9f848faSopenharmony_ci /* Not every year have 29 days in Feb when set DST. */ 266f9f848faSopenharmony_ci if ((monDay == 29) && ((month + 1) == 2)) { 267f9f848faSopenharmony_ci return -1; 268f9f848faSopenharmony_ci } 269f9f848faSopenharmony_ci 270f9f848faSopenharmony_ci if (monDay > g_monLengths[0][month]) { 271f9f848faSopenharmony_ci return -1; 272f9f848faSopenharmony_ci } 273f9f848faSopenharmony_ci 274f9f848faSopenharmony_ci /* Day of the month (1-31) */ 275f9f848faSopenharmony_ci return monDay; 276f9f848faSopenharmony_ci} 277f9f848faSopenharmony_ci 278f9f848faSopenharmony_ci/* 279f9f848faSopenharmony_ci * time format HH:MM:SS 280f9f848faSopenharmony_ci * index 01234567 281f9f848faSopenharmony_ci * 0~23 for hours per day 282f9f848faSopenharmony_ci * 0~59 for minutes per hour 283f9f848faSopenharmony_ci * 0~59 for seconds per minute 284f9f848faSopenharmony_ci */ 285f9f848faSopenharmony_ciSTATIC INT32 GetDaySecondsFromString(const CHAR *strTimeString) 286f9f848faSopenharmony_ci{ 287f9f848faSopenharmony_ci INT32 hour, min, sec; 288f9f848faSopenharmony_ci 289f9f848faSopenharmony_ci if (((strTimeString[0] < '0') || (strTimeString[0] > '9')) || 290f9f848faSopenharmony_ci ((strTimeString[1] < '0') || (strTimeString[1] > '9'))) { 291f9f848faSopenharmony_ci return -1; 292f9f848faSopenharmony_ci } 293f9f848faSopenharmony_ci 294f9f848faSopenharmony_ci if (((strTimeString[3] < '0') || (strTimeString[3] > '9')) || 295f9f848faSopenharmony_ci ((strTimeString[4] < '0') || (strTimeString[4] > '9'))) { 296f9f848faSopenharmony_ci return -1; 297f9f848faSopenharmony_ci } 298f9f848faSopenharmony_ci 299f9f848faSopenharmony_ci if (((strTimeString[6] < '0') || (strTimeString[6] > '9')) || 300f9f848faSopenharmony_ci ((strTimeString[7] < '0') || (strTimeString[7] > '9'))) { 301f9f848faSopenharmony_ci return -1; 302f9f848faSopenharmony_ci } 303f9f848faSopenharmony_ci 304f9f848faSopenharmony_ci if ((strTimeString[2] != ':') || (strTimeString[5] != ':')) { 305f9f848faSopenharmony_ci return -1; 306f9f848faSopenharmony_ci } 307f9f848faSopenharmony_ci 308f9f848faSopenharmony_ci hour = StringToDigital(strTimeString[0], strTimeString[1]); 309f9f848faSopenharmony_ci min = StringToDigital(strTimeString[3], strTimeString[4]); 310f9f848faSopenharmony_ci sec = StringToDigital(strTimeString[6], strTimeString[7]); 311f9f848faSopenharmony_ci /* Hours (0-23) */ 312f9f848faSopenharmony_ci if ((hour < 0) || (hour > 23)) { 313f9f848faSopenharmony_ci return -1; 314f9f848faSopenharmony_ci } 315f9f848faSopenharmony_ci 316f9f848faSopenharmony_ci /* Minutes (0-59) */ 317f9f848faSopenharmony_ci if ((min < 0) || (min > 59)) { 318f9f848faSopenharmony_ci return -1; 319f9f848faSopenharmony_ci } 320f9f848faSopenharmony_ci 321f9f848faSopenharmony_ci /* Seconds (0-59), not consider of the leap seconds in DST. */ 322f9f848faSopenharmony_ci if ((sec < 0) || (sec > 59)) { 323f9f848faSopenharmony_ci return -1; 324f9f848faSopenharmony_ci } 325f9f848faSopenharmony_ci /* 1h: 3600s, 1min: 60s */ 326f9f848faSopenharmony_ci return hour * 3600 + min * 60 + sec; 327f9f848faSopenharmony_ci} 328f9f848faSopenharmony_ci 329f9f848faSopenharmony_ciSTATIC INT32 DstGetDayOfMonth(INT32 year, INT32 month, INT32 mweek, INT32 wday) 330f9f848faSopenharmony_ci{ 331f9f848faSopenharmony_ci#define FIRST_DAY 4 /* the first day of 1970.1.1 is Thursday. */ 332f9f848faSopenharmony_ci INT32 firstWeekDay; /* First week day in this month of the specified year. */ 333f9f848faSopenharmony_ci INT32 firstMdayOfTargetWday; /* First target month day in this month of the specified year. */ 334f9f848faSopenharmony_ci INT32 targetMdayOfTargetWday; /* The target month day specified by user. */ 335f9f848faSopenharmony_ci struct tm time = {0}; 336f9f848faSopenharmony_ci INT64 seconds, days; 337f9f848faSopenharmony_ci 338f9f848faSopenharmony_ci time.tm_year = year; 339f9f848faSopenharmony_ci time.tm_mon = month; 340f9f848faSopenharmony_ci time.tm_mday = 1; 341f9f848faSopenharmony_ci /* 14: Hour-value range is [0,23] */ 342f9f848faSopenharmony_ci time.tm_hour = 14; 343f9f848faSopenharmony_ci time.tm_isdst = 0; 344f9f848faSopenharmony_ci 345f9f848faSopenharmony_ci seconds = mktime(&time); 346f9f848faSopenharmony_ci 347f9f848faSopenharmony_ci if (seconds == -1) { 348f9f848faSopenharmony_ci return -1; 349f9f848faSopenharmony_ci } 350f9f848faSopenharmony_ci days = seconds / SECSPERDAY; 351f9f848faSopenharmony_ci if (days < 0) { 352f9f848faSopenharmony_ci days = -days; 353f9f848faSopenharmony_ci firstWeekDay = DAYSPERWEEK - (days - (DAYSPERWEEK - FIRST_DAY)) % DAYSPERWEEK; 354f9f848faSopenharmony_ci } else { 355f9f848faSopenharmony_ci if (days > FIRST_DAY) { 356f9f848faSopenharmony_ci firstWeekDay = 1 + (days - FIRST_DAY) % DAYSPERWEEK; 357f9f848faSopenharmony_ci } else { 358f9f848faSopenharmony_ci firstWeekDay = FIRST_DAY; 359f9f848faSopenharmony_ci } 360f9f848faSopenharmony_ci } 361f9f848faSopenharmony_ci 362f9f848faSopenharmony_ci firstMdayOfTargetWday = 1 + (DAYSPERWEEK + wday - firstWeekDay) % DAYSPERWEEK; 363f9f848faSopenharmony_ci /* 364f9f848faSopenharmony_ci * Users may use 5th weekday to represent the last week of this month 365f9f848faSopenharmony_ci * for example "Oct-5th-Fri", but there does not exist the 5th Friday in October, so the last monweek is 4th. 366f9f848faSopenharmony_ci */ 367f9f848faSopenharmony_ci targetMdayOfTargetWday = firstMdayOfTargetWday + (mweek - 1) * DAYSPERWEEK; 368f9f848faSopenharmony_ci if (targetMdayOfTargetWday > g_monLengths[(INT32)isleap(year + TM_YEAR_BASE)][month]) { 369f9f848faSopenharmony_ci targetMdayOfTargetWday -= 7; 370f9f848faSopenharmony_ci } 371f9f848faSopenharmony_ci 372f9f848faSopenharmony_ci return targetMdayOfTargetWday; 373f9f848faSopenharmony_ci} 374f9f848faSopenharmony_ci 375f9f848faSopenharmony_ci/* 376f9f848faSopenharmony_ci * time format decode 377f9f848faSopenharmony_ci * 1. Feb-03 03:00:00 378f9f848faSopenharmony_ci * idx 012345678901234 379f9f848faSopenharmony_ci * 2. Oct-1st-Fri 02:59:59 380f9f848faSopenharmony_ci * idx 12345678901234567890 381f9f848faSopenharmony_ci */ 382f9f848faSopenharmony_ciSTATIC INT32 DateDecode(INT32 year, const CHAR *dstString, INT32 *month, INT32 *monDay, INT32 *sec) 383f9f848faSopenharmony_ci{ 384f9f848faSopenharmony_ci INT32 monWeek, weekDay; 385f9f848faSopenharmony_ci /* For example "Feb-03 03:00:00" */ 386f9f848faSopenharmony_ci if (strlen(dstString) == DST_STR_LEN_FORMAT_MDAY) { 387f9f848faSopenharmony_ci if ((dstString[3] != '-') || (dstString[6] != ' ')) { 388f9f848faSopenharmony_ci return -1; 389f9f848faSopenharmony_ci } 390f9f848faSopenharmony_ci 391f9f848faSopenharmony_ci *month = GetMonthFromString(&dstString[0]); 392f9f848faSopenharmony_ci if (*month == -1) { 393f9f848faSopenharmony_ci return -1; 394f9f848faSopenharmony_ci } 395f9f848faSopenharmony_ci 396f9f848faSopenharmony_ci *monDay = GetMonthDayFromString(*month, &dstString[4]); 397f9f848faSopenharmony_ci if (*monDay == -1) { 398f9f848faSopenharmony_ci return -1; 399f9f848faSopenharmony_ci } 400f9f848faSopenharmony_ci 401f9f848faSopenharmony_ci *sec = GetDaySecondsFromString(&dstString[7]); 402f9f848faSopenharmony_ci if (*sec == -1) { 403f9f848faSopenharmony_ci return -1; 404f9f848faSopenharmony_ci } 405f9f848faSopenharmony_ci } else if (strlen(dstString) == DST_STR_LEN_FORMAT_WDAY) { 406f9f848faSopenharmony_ci /* For example "Oct-1st-Fri 02:59:59" */ 407f9f848faSopenharmony_ci if ((dstString[3] != '-') || (dstString[7] != '-') || (dstString[11] != ' ')) { 408f9f848faSopenharmony_ci return -1; 409f9f848faSopenharmony_ci } 410f9f848faSopenharmony_ci 411f9f848faSopenharmony_ci *month = GetMonthFromString(&dstString[0]); 412f9f848faSopenharmony_ci if (*month == -1) { 413f9f848faSopenharmony_ci return -1; 414f9f848faSopenharmony_ci } 415f9f848faSopenharmony_ci 416f9f848faSopenharmony_ci monWeek = GetMonthWeekFromString(&dstString[4]); 417f9f848faSopenharmony_ci if (monWeek == -1) { 418f9f848faSopenharmony_ci return -1; 419f9f848faSopenharmony_ci } 420f9f848faSopenharmony_ci 421f9f848faSopenharmony_ci weekDay = GetWeekDayFromString(&dstString[8]); 422f9f848faSopenharmony_ci if (weekDay == -1) { 423f9f848faSopenharmony_ci return -1; 424f9f848faSopenharmony_ci } 425f9f848faSopenharmony_ci 426f9f848faSopenharmony_ci *sec = GetDaySecondsFromString(&dstString[12]); 427f9f848faSopenharmony_ci if (*sec == -1) { 428f9f848faSopenharmony_ci return -1; 429f9f848faSopenharmony_ci } 430f9f848faSopenharmony_ci 431f9f848faSopenharmony_ci *monDay = DstGetDayOfMonth(year, *month, monWeek, weekDay); 432f9f848faSopenharmony_ci if (*monDay == -1) { 433f9f848faSopenharmony_ci return -1; 434f9f848faSopenharmony_ci } 435f9f848faSopenharmony_ci } else { 436f9f848faSopenharmony_ci return -1; 437f9f848faSopenharmony_ci } 438f9f848faSopenharmony_ci 439f9f848faSopenharmony_ci return 0; 440f9f848faSopenharmony_ci} 441f9f848faSopenharmony_ci 442f9f848faSopenharmony_ciSTATIC INT64 DstConfigDecode(INT32 year, const CHAR *dstString) 443f9f848faSopenharmony_ci{ 444f9f848faSopenharmony_ci INT32 month, monDay, sec; 445f9f848faSopenharmony_ci INT32 ret; 446f9f848faSopenharmony_ci struct tm time = {0}; 447f9f848faSopenharmony_ci INT64 dstSeconds; 448f9f848faSopenharmony_ci 449f9f848faSopenharmony_ci ret = DateDecode(year, dstString, &month, &monDay, &sec); 450f9f848faSopenharmony_ci if (ret == -1) { 451f9f848faSopenharmony_ci return -1; 452f9f848faSopenharmony_ci } 453f9f848faSopenharmony_ci /* get the DST period */ 454f9f848faSopenharmony_ci time.tm_year = year; 455f9f848faSopenharmony_ci time.tm_mon = month; 456f9f848faSopenharmony_ci time.tm_mday = monDay; 457f9f848faSopenharmony_ci time.tm_isdst = 0; 458f9f848faSopenharmony_ci 459f9f848faSopenharmony_ci dstSeconds = mktime(&time); 460f9f848faSopenharmony_ci 461f9f848faSopenharmony_ci if (dstSeconds == -1) { 462f9f848faSopenharmony_ci return -1; 463f9f848faSopenharmony_ci } 464f9f848faSopenharmony_ci 465f9f848faSopenharmony_ci return dstSeconds + sec; 466f9f848faSopenharmony_ci} 467f9f848faSopenharmony_ci 468f9f848faSopenharmony_ciSTATIC BOOL DstConfigCheck(const CHAR *strDstStart, const CHAR *strDstEnd) 469f9f848faSopenharmony_ci{ 470f9f848faSopenharmony_ci INT64 dstStart, dstEnd; 471f9f848faSopenharmony_ci const INT32 year = 70; /* 70 stands for epoch time */ 472f9f848faSopenharmony_ci 473f9f848faSopenharmony_ci if ((strDstStart == NULL) || (strDstEnd == NULL)) { 474f9f848faSopenharmony_ci return FALSE; 475f9f848faSopenharmony_ci } 476f9f848faSopenharmony_ci 477f9f848faSopenharmony_ci dstStart = DstConfigDecode(year, strDstStart); 478f9f848faSopenharmony_ci dstEnd = DstConfigDecode(year, strDstEnd); 479f9f848faSopenharmony_ci if ((dstStart < 0) || (dstEnd < 0)) { 480f9f848faSopenharmony_ci return FALSE; 481f9f848faSopenharmony_ci } 482f9f848faSopenharmony_ci 483f9f848faSopenharmony_ci if (dstStart >= dstEnd) { 484f9f848faSopenharmony_ci return FALSE; 485f9f848faSopenharmony_ci } 486f9f848faSopenharmony_ci 487f9f848faSopenharmony_ci return TRUE; 488f9f848faSopenharmony_ci} 489f9f848faSopenharmony_ci 490f9f848faSopenharmony_ciSTATIC BOOL CheckDstPeriodInner(const struct tm * const tm, INT64 seconds, INT64 dstStart, INT64 dstEnd) 491f9f848faSopenharmony_ci{ 492f9f848faSopenharmony_ci if (tm != NULL) { 493f9f848faSopenharmony_ci if (tm->tm_isdst < 0) { 494f9f848faSopenharmony_ci /* it must to be. */ 495f9f848faSopenharmony_ci if ((seconds >= dstStart) && (seconds < dstStart + g_dstForwardSeconds)) { 496f9f848faSopenharmony_ci return FALSE; 497f9f848faSopenharmony_ci } 498f9f848faSopenharmony_ci 499f9f848faSopenharmony_ci /* determine the time period of the second pass, out of the DST period. */ 500f9f848faSopenharmony_ci if ((seconds > dstEnd) && (seconds <= dstEnd + g_dstForwardSeconds)) { 501f9f848faSopenharmony_ci return TRUE; 502f9f848faSopenharmony_ci } 503f9f848faSopenharmony_ci } else if (tm->tm_isdst > 0) { 504f9f848faSopenharmony_ci /* the logical judgment here is the opposite of common sense */ 505f9f848faSopenharmony_ci return TRUE; 506f9f848faSopenharmony_ci } else { 507f9f848faSopenharmony_ci /* tm->tm_isdst is zero */ 508f9f848faSopenharmony_ci return FALSE; 509f9f848faSopenharmony_ci } 510f9f848faSopenharmony_ci } 511f9f848faSopenharmony_ci 512f9f848faSopenharmony_ci if ((seconds < dstStart) || (seconds >= dstEnd)) { 513f9f848faSopenharmony_ci return FALSE; /* daylight saving time is not effect. */ 514f9f848faSopenharmony_ci } 515f9f848faSopenharmony_ci 516f9f848faSopenharmony_ci return TRUE; 517f9f848faSopenharmony_ci} 518f9f848faSopenharmony_ci 519f9f848faSopenharmony_ciBOOL CheckWithinDstPeriod(const struct tm * const tm, INT64 seconds) 520f9f848faSopenharmony_ci{ 521f9f848faSopenharmony_ci INT64 dstStart, dstEnd; 522f9f848faSopenharmony_ci struct tm time = {0}; 523f9f848faSopenharmony_ci 524f9f848faSopenharmony_ci if (g_isDstWork == FALSE) { 525f9f848faSopenharmony_ci return FALSE; 526f9f848faSopenharmony_ci } 527f9f848faSopenharmony_ci 528f9f848faSopenharmony_ci /* represent a local time. */ 529f9f848faSopenharmony_ci if (tm != NULL) { 530f9f848faSopenharmony_ci (void)memcpy_s(&time, sizeof(struct tm), tm, sizeof(struct tm)); 531f9f848faSopenharmony_ci time.tm_isdst = 0; 532f9f848faSopenharmony_ci /* the input-param of seconds is unused in this case. */ 533f9f848faSopenharmony_ci seconds = mktime(&time); 534f9f848faSopenharmony_ci if (seconds == -1) { 535f9f848faSopenharmony_ci return FALSE; 536f9f848faSopenharmony_ci } 537f9f848faSopenharmony_ci } else { 538f9f848faSopenharmony_ci /* represent a standard time, not care TZ. */ 539f9f848faSopenharmony_ci if (gmtime_r(&seconds, &time) == NULL) { 540f9f848faSopenharmony_ci return FALSE; 541f9f848faSopenharmony_ci } 542f9f848faSopenharmony_ci } 543f9f848faSopenharmony_ci 544f9f848faSopenharmony_ci dstStart = DstConfigDecode(time.tm_year, g_strDstStart); 545f9f848faSopenharmony_ci dstEnd = DstConfigDecode(time.tm_year, g_strDstEnd); 546f9f848faSopenharmony_ci if ((dstStart == -1) || (dstEnd == -1)) { 547f9f848faSopenharmony_ci return FALSE; 548f9f848faSopenharmony_ci } 549f9f848faSopenharmony_ci 550f9f848faSopenharmony_ci return CheckDstPeriodInner(tm, seconds, dstStart, dstEnd); 551f9f848faSopenharmony_ci} 552f9f848faSopenharmony_ci 553f9f848faSopenharmony_ciint dst_disable(VOID) 554f9f848faSopenharmony_ci{ 555f9f848faSopenharmony_ci if (lock()) { 556f9f848faSopenharmony_ci return -1; 557f9f848faSopenharmony_ci } 558f9f848faSopenharmony_ci 559f9f848faSopenharmony_ci g_isDstWork = FALSE; 560f9f848faSopenharmony_ci 561f9f848faSopenharmony_ci unlock(); 562f9f848faSopenharmony_ci 563f9f848faSopenharmony_ci return 0; 564f9f848faSopenharmony_ci} 565f9f848faSopenharmony_ci 566f9f848faSopenharmony_ciint dst_enable(const char *strDstStartTime, const char *strDstEndTime, int swForwardSeconds) 567f9f848faSopenharmony_ci{ 568f9f848faSopenharmony_ci if (lock()) { 569f9f848faSopenharmony_ci return -1; 570f9f848faSopenharmony_ci } 571f9f848faSopenharmony_ci 572f9f848faSopenharmony_ci /* Check if the format of dst config is correct. */ 573f9f848faSopenharmony_ci if (DstConfigCheck(strDstStartTime, strDstEndTime) != TRUE) { 574f9f848faSopenharmony_ci unlock(); 575f9f848faSopenharmony_ci return -1; 576f9f848faSopenharmony_ci } 577f9f848faSopenharmony_ci 578f9f848faSopenharmony_ci if ((swForwardSeconds < 0) || (swForwardSeconds >= 24 * 3600)) { /* seconds per day 24 * 3600 */ 579f9f848faSopenharmony_ci unlock(); 580f9f848faSopenharmony_ci return -1; 581f9f848faSopenharmony_ci } 582f9f848faSopenharmony_ci 583f9f848faSopenharmony_ci g_isDstWork = FALSE; 584f9f848faSopenharmony_ci if (strncpy_s(g_strDstStart, DST_SET_LENGTH_MAX, strDstStartTime, strlen(strDstStartTime)) != EOK) { 585f9f848faSopenharmony_ci unlock(); 586f9f848faSopenharmony_ci return -1; 587f9f848faSopenharmony_ci } 588f9f848faSopenharmony_ci if (strncpy_s(g_strDstEnd, DST_SET_LENGTH_MAX, strDstEndTime, strlen(strDstEndTime)) != EOK) { 589f9f848faSopenharmony_ci unlock(); 590f9f848faSopenharmony_ci return -1; 591f9f848faSopenharmony_ci } 592f9f848faSopenharmony_ci 593f9f848faSopenharmony_ci g_dstForwardSeconds = swForwardSeconds; 594f9f848faSopenharmony_ci g_isDstWork = TRUE; 595f9f848faSopenharmony_ci 596f9f848faSopenharmony_ci unlock(); 597f9f848faSopenharmony_ci 598f9f848faSopenharmony_ci return 0; 599f9f848faSopenharmony_ci} 600f9f848faSopenharmony_ci 601f9f848faSopenharmony_ciint dst_inquire(int year, struct tm *pstDstStart, struct tm *pstDstEnd) 602f9f848faSopenharmony_ci{ 603f9f848faSopenharmony_ci INT64 dstStart, dstEnd; 604f9f848faSopenharmony_ci 605f9f848faSopenharmony_ci if (lock()) { 606f9f848faSopenharmony_ci return -1; 607f9f848faSopenharmony_ci } 608f9f848faSopenharmony_ci 609f9f848faSopenharmony_ci if (!g_isDstWork) { 610f9f848faSopenharmony_ci unlock(); 611f9f848faSopenharmony_ci return -1; 612f9f848faSopenharmony_ci } 613f9f848faSopenharmony_ci 614f9f848faSopenharmony_ci if ((pstDstStart == NULL) || (pstDstEnd == NULL)) { 615f9f848faSopenharmony_ci unlock(); 616f9f848faSopenharmony_ci return -1; 617f9f848faSopenharmony_ci } 618f9f848faSopenharmony_ci 619f9f848faSopenharmony_ci dstStart = DstConfigDecode(year, g_strDstStart); 620f9f848faSopenharmony_ci dstEnd = DstConfigDecode(year, g_strDstEnd); 621f9f848faSopenharmony_ci if ((dstStart == -1) || (dstEnd == -1)) { 622f9f848faSopenharmony_ci unlock(); 623f9f848faSopenharmony_ci return -1; 624f9f848faSopenharmony_ci } 625f9f848faSopenharmony_ci 626f9f848faSopenharmony_ci dstStart += timezone; 627f9f848faSopenharmony_ci dstEnd += timezone; 628f9f848faSopenharmony_ci if ((gmtime_r(&dstStart, pstDstStart) == NULL) || (gmtime_r(&dstEnd, pstDstEnd) == NULL)) { 629f9f848faSopenharmony_ci unlock(); 630f9f848faSopenharmony_ci return -1; 631f9f848faSopenharmony_ci } 632f9f848faSopenharmony_ci 633f9f848faSopenharmony_ci unlock(); 634f9f848faSopenharmony_ci return 0; 635f9f848faSopenharmony_ci} 636f9f848faSopenharmony_ci 637