xref: /aosp_15_r20/external/cronet/third_party/apache-portable-runtime/src/time/win32/timestr.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "apr_arch_atime.h"
18 #include "apr_portable.h"
19 #include "apr_strings.h"
20 
21 #if APR_HAVE_STDLIB_H
22 #include <stdlib.h>
23 #endif
24 
25 APR_DECLARE_DATA const char apr_month_snames[12][4] =
26 {
27     "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
28 };
29 APR_DECLARE_DATA const char apr_day_snames[7][4] =
30 {
31     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
32 };
33 
apr_rfc822_date(char * date_str,apr_time_t t)34 APR_DECLARE(apr_status_t) apr_rfc822_date(char *date_str, apr_time_t t)
35 {
36     apr_time_exp_t xt;
37     const char *s;
38     int real_year;
39 
40     apr_time_exp_gmt(&xt, t);
41 
42     /* example: "Sat, 08 Jan 2000 18:31:41 GMT" */
43     /*           12345678901234567890123456789  */
44 
45     s = &apr_day_snames[xt.tm_wday][0];
46     *date_str++ = *s++;
47     *date_str++ = *s++;
48     *date_str++ = *s++;
49     *date_str++ = ',';
50     *date_str++ = ' ';
51     *date_str++ = xt.tm_mday / 10 + '0';
52     *date_str++ = xt.tm_mday % 10 + '0';
53     *date_str++ = ' ';
54     s = &apr_month_snames[xt.tm_mon][0];
55     *date_str++ = *s++;
56     *date_str++ = *s++;
57     *date_str++ = *s++;
58     *date_str++ = ' ';
59     real_year = 1900 + xt.tm_year;
60     /* This routine isn't y10k ready. */
61     *date_str++ = real_year / 1000 + '0';
62     *date_str++ = real_year % 1000 / 100 + '0';
63     *date_str++ = real_year % 100 / 10 + '0';
64     *date_str++ = real_year % 10 + '0';
65     *date_str++ = ' ';
66     *date_str++ = xt.tm_hour / 10 + '0';
67     *date_str++ = xt.tm_hour % 10 + '0';
68     *date_str++ = ':';
69     *date_str++ = xt.tm_min / 10 + '0';
70     *date_str++ = xt.tm_min % 10 + '0';
71     *date_str++ = ':';
72     *date_str++ = xt.tm_sec / 10 + '0';
73     *date_str++ = xt.tm_sec % 10 + '0';
74     *date_str++ = ' ';
75     *date_str++ = 'G';
76     *date_str++ = 'M';
77     *date_str++ = 'T';
78     *date_str++ = 0;
79     return APR_SUCCESS;
80 }
81 
apr_ctime(char * date_str,apr_time_t t)82 APR_DECLARE(apr_status_t) apr_ctime(char *date_str, apr_time_t t)
83 {
84     apr_time_exp_t xt;
85     const char *s;
86     int real_year;
87 
88     /* example: "Wed Jun 30 21:49:08 1993" */
89     /*           123456789012345678901234  */
90 
91     apr_time_exp_lt(&xt, t);
92     s = &apr_day_snames[xt.tm_wday][0];
93     *date_str++ = *s++;
94     *date_str++ = *s++;
95     *date_str++ = *s++;
96     *date_str++ = ' ';
97     s = &apr_month_snames[xt.tm_mon][0];
98     *date_str++ = *s++;
99     *date_str++ = *s++;
100     *date_str++ = *s++;
101     *date_str++ = ' ';
102     *date_str++ = xt.tm_mday / 10 + '0';
103     *date_str++ = xt.tm_mday % 10 + '0';
104     *date_str++ = ' ';
105     *date_str++ = xt.tm_hour / 10 + '0';
106     *date_str++ = xt.tm_hour % 10 + '0';
107     *date_str++ = ':';
108     *date_str++ = xt.tm_min / 10 + '0';
109     *date_str++ = xt.tm_min % 10 + '0';
110     *date_str++ = ':';
111     *date_str++ = xt.tm_sec / 10 + '0';
112     *date_str++ = xt.tm_sec % 10 + '0';
113     *date_str++ = ' ';
114     real_year = 1900 + xt.tm_year;
115     *date_str++ = real_year / 1000 + '0';
116     *date_str++ = real_year % 1000 / 100 + '0';
117     *date_str++ = real_year % 100 / 10 + '0';
118     *date_str++ = real_year % 10 + '0';
119     *date_str++ = 0;
120 
121     return APR_SUCCESS;
122 }
123 
124 
125 #ifndef _WIN32_WCE
126 
win32_strftime_extra(char * s,size_t max,const char * format,const struct tm * tm)127 static apr_size_t win32_strftime_extra(char *s, size_t max, const char *format,
128                                        const struct tm *tm)
129 {
130    /* If the new format string is bigger than max, the result string won't fit
131     * anyway. If format strings are added, made sure the padding below is
132     * enough */
133     char *new_format = (char *) malloc(max + 11);
134     size_t i, j, format_length = strlen(format);
135     apr_size_t return_value;
136     int length_written;
137 
138     for (i = 0, j = 0; (i < format_length && j < max);) {
139         if (format[i] != '%') {
140             new_format[j++] = format[i++];
141             continue;
142         }
143         switch (format[i+1]) {
144             case 'C':
145                 length_written = apr_snprintf(new_format + j, max - j, "%2d",
146                     (tm->tm_year + 1970)/100);
147                 j = (length_written == -1) ? max : (j + length_written);
148                 i += 2;
149                 break;
150             case 'D':
151                 /* Is this locale dependent? Shouldn't be...
152                    Also note the year 2000 exposure here */
153                 memcpy(new_format + j, "%m/%d/%y", 8);
154                 i += 2;
155                 j += 8;
156                 break;
157             case 'r':
158                 memcpy(new_format + j, "%I:%M:%S %p", 11);
159                 i += 2;
160                 j += 11;
161                 break;
162             case 'R':
163                 memcpy(new_format + j, "%H:%M", 5);
164                 i += 2;
165                 j += 5;
166                 break;
167             case 'T':
168                 memcpy(new_format + j, "%H:%M:%S", 8);
169                 i += 2;
170                 j += 8;
171                 break;
172             case 'e':
173                 length_written = apr_snprintf(new_format + j, max - j, "%2d",
174                     tm->tm_mday);
175                 j = (length_written == -1) ? max : (j + length_written);
176                 i += 2;
177                 break;
178             default:
179                 /* We know we can advance two characters forward here. Also
180                  * makes sure that %% is preserved. */
181                 new_format[j++] = format[i++];
182                 new_format[j++] = format[i++];
183         }
184     }
185     if (j >= max) {
186         *s = '\0';  /* Defensive programming, okay since output is undefined*/
187         return_value = 0;
188     } else {
189         new_format[j] = '\0';
190         return_value = strftime(s, max, new_format, tm);
191     }
192     free(new_format);
193     return return_value;
194 }
195 
196 #endif
197 
198 
apr_strftime(char * s,apr_size_t * retsize,apr_size_t max,const char * format,apr_time_exp_t * xt)199 APR_DECLARE(apr_status_t) apr_strftime(char *s, apr_size_t *retsize,
200                                        apr_size_t max, const char *format,
201                                        apr_time_exp_t *xt)
202 {
203 #ifdef _WIN32_WCE
204     return APR_ENOTIMPL;
205 #else
206     struct tm tm;
207     memset(&tm, 0, sizeof tm);
208     tm.tm_sec  = xt->tm_sec;
209     tm.tm_min  = xt->tm_min;
210     tm.tm_hour = xt->tm_hour;
211     tm.tm_mday = xt->tm_mday;
212     tm.tm_mon  = xt->tm_mon;
213     tm.tm_year = xt->tm_year;
214     tm.tm_wday = xt->tm_wday;
215     tm.tm_yday = xt->tm_yday;
216     tm.tm_isdst = xt->tm_isdst;
217     (*retsize) = win32_strftime_extra(s, max, format, &tm);
218     return APR_SUCCESS;
219 #endif
220 }
221