undefined reference to strptime之自定义strptime函数

详见博客 : http://blog.csdn.net/freeape/article/details/47132843

简介

  strptime()函数能够按照特定时间格式将字符串转换为时间类型。简单点说可以将字符串时间转化为时间戳。这个函数包含在time.h头文件中,在Unix或者类Unix系统中,我们会经常接触到。但是到了跑Nuttx系统的Pixhawk,真是醉了,很多东西都没有,或者少了很多东西,比如time.h中就没有这个函数的实现,又如dirent.h中的一些文件类型的宏定义也没有了。但是我们很需要,比如在时间的比较上,我们不能去拿字符串去操作来比较,会搞死人的,直接得到时间戳,三下两除二就搞定了,那就要用到strptime这个函数了。

实现

mystrptime.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
/*
* Note:因time.h中没有strptime函数(UNIX中是有的),本文件是对strptime功能的自定义实现;
* We do not implement alternate representations. However, we always
* check whether a given modifier is allowed for a certain conversion.
*/

#include "mystrptime.h"


static const char *day[7] = {
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday"
};
static const char *abday[7] = {
"Sun","Mon","Tue","Wed","Thu","Fri","Sat"
};
static const char *mon[12] = {
"January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"
};
static const char *abmon[12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static const char *am_pm[2] = {
"AM", "PM"
};


static int conv_num(const char **buf, int *dest, int llim, int ulim)
{

int result = 0;

/* The limit also determines the number of valid digits. */
int rulim = ulim;

if (**buf < '0' || **buf > '9')
return (0);

do {
result *= 10;
result += *(*buf)++ - '0';
rulim /= 10;
} while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');

if (result < llim || result > ulim)
return (0);

*dest = result;
return (1);
}

char * mystrptime(const char *buf, const char *fmt, struct tm *tm)
{

char c;
const char *bp;
size_t len = 0;
int alt_format, i, split_year = 0;

bp = buf;

while ((c = *fmt) != '\0') {
/* Clear `alternate' modifier prior to new conversion. */
alt_format = 0;

/* Eat up white-space. */
if (isspace(c)) {
while (isspace(*bp))
bp++;

fmt++;
continue;
}

if ((c = *fmt++) != '%')
goto literal;


again: switch (c = *fmt++) {
case '%': /* "%%" is converted to "%". */
literal:
if (c != *bp++)
return (0);
break;

/*
* "Alternative" modifiers. Just set the appropriate flag
* and start over again.
*/

case 'E': /* "%E?" alternative conversion modifier. */
LEGAL_ALT(0);
alt_format |= ALT_E;
goto again;

case 'O': /* "%O?" alternative conversion modifier. */
LEGAL_ALT(0);
alt_format |= ALT_O;
goto again;

/*
* "Complex" conversion rules, implemented through recursion.
*/

case 'c': /* Date and time, using the locale's format. */
LEGAL_ALT(ALT_E);
if (!(bp = mystrptime(bp, "%x %X", tm)))
return (0);
break;

case 'D': /* The date as "%m/%d/%y". */
LEGAL_ALT(0);
if (!(bp = mystrptime(bp, "%m/%d/%y", tm)))
return (0);
break;

case 'R': /* The time as "%H:%M". */
LEGAL_ALT(0);
if (!(bp = mystrptime(bp, "%H:%M", tm)))
return (0);
break;

case 'r': /* The time in 12-hour clock representation. */
LEGAL_ALT(0);
if (!(bp = mystrptime(bp, "%I:%M:%S %p", tm)))
return (0);
break;

case 'T': /* The time as "%H:%M:%S". */
LEGAL_ALT(0);
if (!(bp = mystrptime(bp, "%H:%M:%S", tm)))
return (0);
break;

case 'X': /* The time, using the locale's format. */
LEGAL_ALT(ALT_E);
if (!(bp = mystrptime(bp, "%H:%M:%S", tm)))
return (0);
break;

case 'x': /* The date, using the locale's format. */
LEGAL_ALT(ALT_E);
if (!(bp = mystrptime(bp, "%m/%d/%y", tm)))
return (0);
break;

/*
* "Elementary" conversion rules.
*/

case 'A': /* The day of week, using the locale's form. */
case 'a':
LEGAL_ALT(0);
for (i = 0; i < 7; i++) {
/* Full name. */
len = strlen(day[i]);
if (strncasecmp(day[i], bp, len) == 0)
break;

/* Abbreviated name. */
len = strlen(abday[i]);
if (strncasecmp(abday[i], bp, len) == 0)
break;
}

/* Nothing matched. */
if (i == 7)
return (0);

tm->tm_wday = i;
bp += len;
break;

case 'B': /* The month, using the locale's form. */
case 'b':
case 'h':
LEGAL_ALT(0);
for (i = 0; i < 12; i++) {
/* Full name. */
len = strlen(mon[i]);
if (strncasecmp(mon[i], bp, len) == 0)
break;

/* Abbreviated name. */
len = strlen(abmon[i]);
if (strncasecmp(abmon[i], bp, len) == 0)
break;
}

/* Nothing matched. */
if (i == 12)
return (0);

tm->tm_mon = i;
bp += len;
break;

case 'C': /* The century number. */
LEGAL_ALT(ALT_E);
if (!(conv_num(&bp, &i, 0, 99)))
return (0);

if (split_year) {
tm->tm_year = (tm->tm_year % 100) + (i * 100);
} else {
tm->tm_year = i * 100;
split_year = 1;
}
break;

case 'd': /* The day of month. */
case 'e':
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &tm->tm_mday, 1, 31)))
return (0);
break;

case 'k': /* The hour (24-hour clock representation). */
LEGAL_ALT(0);
/* FALLTHROUGH */
case 'H':
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &tm->tm_hour, 0, 23)))
return (0);
break;

case 'l': /* The hour (12-hour clock representation). */
LEGAL_ALT(0);
/* FALLTHROUGH */
case 'I':
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &tm->tm_hour, 1, 12)))
return (0);
if (tm->tm_hour == 12)
tm->tm_hour = 0;
break;

case 'j': /* The day of year. */
LEGAL_ALT(0);
if (!(conv_num(&bp, &i, 1, 366)))
return (0);
tm->tm_yday = i - 1;
break;

case 'M': /* The minute. */
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &tm->tm_min, 0, 59)))
return (0);
break;

case 'm': /* The month. */
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &i, 1, 12)))
return (0);
tm->tm_mon = i - 1;
break;

case 'p': /* The locale's equivalent of AM/PM. */
LEGAL_ALT(0);
/* AM? */
if (strcasecmp(am_pm[0], bp) == 0) {
if (tm->tm_hour > 11)
return (0);

bp += strlen(am_pm[0]);
break;
}
/* PM? */
else if (strcasecmp(am_pm[1], bp) == 0) {
if (tm->tm_hour > 11)
return (0);

tm->tm_hour += 12;
bp += strlen(am_pm[1]);
break;
}

/* Nothing matched. */
return (0);

case 'S': /* The seconds. */
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &tm->tm_sec, 0, 61)))
return (0);
break;

case 'U': /* The week of year, beginning on sunday. */
case 'W': /* The week of year, beginning on monday. */
LEGAL_ALT(ALT_O);
/*
* XXX This is bogus, as we can not assume any valid
* information present in the tm structure at this
* point to calculate a real value, so just check the
* range for now.
*/

if (!(conv_num(&bp, &i, 0, 53)))
return (0);
break;

case 'w': /* The day of week, beginning on sunday. */
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &tm->tm_wday, 0, 6)))
return (0);
break;

case 'Y': /* The year. */
LEGAL_ALT(ALT_E);
if (!(conv_num(&bp, &i, 0, 9999)))
return (0);

tm->tm_year = i - TM_YEAR_BASE;
break;

case 'y': /* The year within 100 years of the epoch. */
LEGAL_ALT(ALT_E | ALT_O);
if (!(conv_num(&bp, &i, 0, 99)))
return (0);

if (split_year) {
tm->tm_year = ((tm->tm_year / 100) * 100) + i;
break;
}
split_year = 1;
if (i <= 68)
tm->tm_year = i + 2000 - TM_YEAR_BASE;
else
tm->tm_year = i + 1900 - TM_YEAR_BASE;
break;

/*
* Miscellaneous conversions.
*/

case 'n': /* Any kind of white-space. */
case 't':
LEGAL_ALT(0);
while (isspace(*bp))
bp++;
break;


default: /* Unknown/unsupported conversion. */
return (0);
}


}

/* LINTED functional specification */
return ((char *)bp);
}


time_t to_seconds(const char *date,int mode)
{
struct tm storage={0,0,0,0,0,0,0,0,0};
char *p=NULL;
time_t retval=0;

if(1 == mode)p=(char *)mystrptime(date,"%Y-%m-%d",&storage);
else if(0 == mode)p=(char *)mystrptime(date,"%Y_%m_%d",&storage);
if(p==NULL)
{
retval=0;
}
else
{
retval=mktime(&storage);
}
return retval;
}
mystrptime.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef MYSTRPTIME_H_
#define MYSTRPTIME_H_

#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <string.h>

#define ALT_E 0x01
#define ALT_O 0x02
#define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); }
#define TM_YEAR_BASE 1900

char *mystrptime(const char *buf, const char *fmt, struct tm *tm);
time_t to_seconds(const char *date,int mode);

#endif

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*Test*/
/*
#intclude <stdio.h>
#include "mystrptime.h"

int main ()
{
time_t ts;
ts = to_seconds("2015-07-29",1);
//ts = to_seconds("2015_07_29",0);
printf("ts=%d\n",ts);
return(0);
}
*/