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