Add copyright information
[platform/upstream/iotivity.git] / resource / csdk / security / src / strptime.c
1 /* *****************************************************************
2 *
3 * Copyright 2016 Microsoft
4 *
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 ******************************************************************/
19
20 #include <stdio.h>
21 #include <ctype.h>
22 #include <time.h>
23 #include <memory.h>
24 #include <stdbool.h>
25
26 #define TM_BASE_YEAR   1900
27
28 static const int ydays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
29
30 bool is_leap_year(int yy)
31 {
32     int yyyy = yy + TM_BASE_YEAR;
33
34     bool bLeap = false;
35     if (yyyy % 100 == 0)
36     {
37         return yyyy % 400 == 0;
38     }
39     return yyyy % 4 == 0;
40 }
41
42
43 char * strptime(const char *buf, const char *fmt, struct tm *tm)
44 {
45     int temp = 0;
46     char c = '\0';
47
48     //check params
49     if ((fmt == NULL) || (tm == NULL))
50     {
51         return NULL;
52     }
53
54     //initialize the tm struct values
55     memset(tm, 0, sizeof(struct tm));
56     tm->tm_mday = 1;
57
58     while (buf && (c = *fmt++))
59     {
60         temp = 0;
61         if (c == '%')
62         {
63             switch (c = *fmt++)
64             {
65             case '%':
66                 if (c != *buf++)
67                 {
68                     return NULL;
69                 }
70                 break;
71
72             case 'd':   /* day of the month (1..31)*/
73                 sscanf(buf, "%2d", &temp);
74                 if (temp >= 1 && temp <= 31)
75                 {
76                     tm->tm_mday = temp;
77                     buf += 2;
78                 }
79                 else
80                     return NULL;
81                 break;
82
83             case 'H':   /* hour (0..23) */
84                 sscanf(buf, "%2d", &temp);
85                 if (temp >= 0 && temp <= 23)
86                 {
87                     tm->tm_hour = temp;
88                     buf += 2;
89                 }
90                 else
91                     return NULL;
92                 break;
93
94             case 'M':   /* minute (0..59) */
95                 sscanf(buf, "%2d", &temp);
96                 if (temp >= 0 && temp <= 59)
97                 {
98                     tm->tm_min = temp;
99                     buf += 2;
100                 }
101                 else
102                     return NULL;
103                 break;
104
105             case 'm':   /* month (1..12) */
106                 sscanf(buf, "%2d", &temp);
107                 if (temp >= 1 && temp <= 12)
108                 {
109                     tm->tm_mon = temp - 1;
110                     buf += 2;
111                 }
112                 else
113                     return NULL;
114                 break;
115
116             case 'S':   /* seconds (0..59) */
117                 sscanf(buf, "%2d", &temp);
118                 if (temp >= 0 && temp <= 59)
119                 {
120                     tm->tm_sec = temp;
121                     buf += 2;
122                 }
123                 else
124                     return NULL;
125                 break;
126
127             case 'Y':   /* year */
128                 sscanf(buf, "%4d", &temp);
129                 if (temp >= 0 && temp <= 9999)
130                 {
131                     tm->tm_year = temp - TM_BASE_YEAR;
132                     buf += 4;
133                 }
134                 else
135                     return NULL;
136                 break;
137
138             default:
139                 return NULL;
140             }
141         }
142         else
143         {
144             if (c != *buf++)
145                 return NULL;
146         }
147     }
148
149     //calculate tm_wday and tm_yday
150     tm->tm_yday = ydays[tm->tm_mon] + ((is_leap_year(tm->tm_year) && (tm->tm_mon >= 2)) ? 1 : 0) + tm->tm_mday - 1;
151
152     //1st Jan 1900 was Monday, hence weekday = the number of days from 1/1/1900  modulus 7 + 1
153     tm->tm_wday = (365 * tm->tm_year) + (tm->tm_year / 4) + tm->tm_yday + 1;        //1st Jan 1900 was Monday, hence add 1
154     if (is_leap_year(tm->tm_year))
155         tm->tm_wday--;
156     tm->tm_wday %= 7;
157
158     return (char*)buf;
159 }