1 /* Parse dates for touch and date.
2 Copyright (C) 1989, 1990, 1991, 1998, 2000 Free Software Foundation Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Yacc-based version written by Jim Kingdon and David MacKenzie.
19 Rewritten by Jim Meyering. */
29 #include <sys/types.h>
37 # include <sys/time.h>
44 /* ISDIGIT differs from isdigit, as follows:
45 - Its arg may be any int or unsigned int; it need not be an unsigned char.
46 - It's guaranteed to evaluate its argument exactly once.
47 - It's typically faster.
48 Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
49 only '0' through '9' are digits. Prefer ISDIGIT to isdigit unless
50 it's important to use the locale's definition of `digit' even when the
51 host does not conform to Posix. */
52 #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
54 /* The return value. */
62 touch -t [[CC]YY]mmddhhmm[.ss] FILE...
63 8, 10, or 12 digits, followed by optional .ss
64 (PDS_LEADING_YEAR | PDS_CENTURY | PDS_SECONDS)
66 touch mmddhhmm[YY] FILE... (obsolescent)
72 (PDS_TRAILING_YEAR | PDS_CENTURY)
77 year (const int *digit_pair
, size_t n
, int allow_century
)
82 t
.tm_year
= *digit_pair
;
83 /* Deduce the century based on the year.
84 See POSIX.2 section 4.63.3. */
85 if (digit_pair
[0] <= 68)
92 t
.tm_year
= digit_pair
[0] * 100 + digit_pair
[1];
103 /* Use current year. */
105 tmp
= localtime (&now
);
106 t
.tm_year
= tmp
->tm_year
;
118 posix_time_parse (const char *s
, unsigned int syntax_bits
)
120 const char *dot
= NULL
;
125 size_t s_len
= strlen (s
);
126 size_t len
= (((syntax_bits
& PDS_SECONDS
) && (dot
= strchr (s
, '.')))
130 if (len
!= 8 && len
!= 10 && len
!= 12)
135 if (!(syntax_bits
& PDS_SECONDS
))
138 if (s_len
- len
!= 3)
142 for (i
= 0; i
< len
; i
++)
147 for (i
= 0; i
< len
; i
++)
148 pair
[i
] = 10 * (s
[2*i
] - '0') + s
[2*i
+ 1] - '0';
151 if (syntax_bits
& PDS_LEADING_YEAR
)
153 if (year (p
, len
- 4, syntax_bits
& PDS_CENTURY
))
159 /* Handle 8 digits worth of `MMDDhhmm'. */
160 if (*p
< 1 || *p
> 12)
165 if (*p
< 1 || *p
> 31)
170 if (*p
< 0 || *p
> 23)
175 if (*p
< 0 || *p
> 59)
180 /* Handle any trailing year. */
181 if (syntax_bits
& PDS_TRAILING_YEAR
)
183 if (year (p
, len
, syntax_bits
& PDS_CENTURY
))
187 /* Handle seconds. */
197 if (!ISDIGIT (dot
[0]) || !ISDIGIT (dot
[1]))
199 seconds
= 10 * (dot
[0] - '0') + dot
[1] - '0';
201 if (seconds
< 0 || seconds
> 61)
209 /* Parse a POSIX-style date and return it, or (time_t)-1 for an error. */
212 posixtime (const char *s
, unsigned int syntax_bits
)
215 if (posix_time_parse (s
, syntax_bits
))
221 /* Parse a POSIX-style date and return it, or NULL for an error. */
224 posixtm (const char *s
, unsigned int syntax_bits
)
226 if (posixtime (s
, syntax_bits
) == -1)
231 #ifdef TEST_POSIXTIME
233 Test mainly with syntax_bits == 13
234 (aka: (PDS_LEADING_YEAR | PDS_CENTURY | PDS_SECONDS))
237 1112131415 13 1323807300 Tue Dec 13 14:15:00 2011
238 1112131415.16 13 1323807316 Tue Dec 13 14:15:16 2011
239 201112131415.16 13 1323807316 Tue Dec 13 14:15:16 2011
240 191112131415.16 13 -1 ***
241 203712131415.16 13 2144348116 Sun Dec 13 14:15:16 2037
242 3712131415.16 13 2144348116 Sun Dec 13 14:15:16 2037
243 6812131415.16 13 -1 ***
244 6912131415.16 13 -1 ***
245 7012131415.16 13 29967316 Sun Dec 13 14:15:16 1970
246 12131415.16 13 913580116 Sun Dec 13 14:15:16 1998
248 1213141599 2 945116100 Mon Dec 13 14:15:00 1999
249 1213141500 2 976738500 Wed Dec 13 14:15:00 2000
254 # define MAX_BUFF_LEN 1024
259 char buff
[MAX_BUFF_LEN
+ 1];
261 buff
[MAX_BUFF_LEN
] = 0;
262 while (fgets (buff
, MAX_BUFF_LEN
, stdin
) && buff
[0])
264 char time_str
[MAX_BUFF_LEN
];
265 unsigned int syntax_bits
;
268 sscanf (buff
, "%s %u", time_str
, &syntax_bits
);
269 t
= posixtime (time_str
, syntax_bits
);
270 result
= (t
== (time_t) -1 ? "***" : ctime (&t
));
271 printf ("%d %s\n", (int) t
, result
);