1 /* Parse dates for touch and date.
2 Copyright (C) 1989, 1990, 1991, 1998 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. */
26 #include <sys/types.h>
34 # include <sys/time.h>
41 /* ISDIGIT differs from isdigit, as follows:
42 - Its arg may be any int or unsigned int; it need not be an unsigned char.
43 - It's guaranteed to evaluate its argument exactly once.
44 - It's typically faster.
45 Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
46 only '0' through '9' are digits. Prefer ISDIGIT to isdigit unless
47 it's important to use the locale's definition of `digit' even when the
48 host does not conform to Posix. */
49 #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
51 /* The return value. */
59 touch -t [[CC]YY]mmddhhmm[.ss] FILE...
60 8, 10, or 12 digits, followed by optional .ss
61 (PDS_LEADING_YEAR | PDS_CENTURY | PDS_SECONDS)
63 touch mmddhhmm[YY] FILE... (obsolescent)
69 (PDS_TRAILING_YEAR | PDS_CENTURY)
74 year (const int *digit_pair, size_t n, int allow_century)
79 t.tm_year = *digit_pair;
80 /* Deduce the century based on the year.
81 See POSIX.2 section 4.63.3. */
82 if (digit_pair[0] <= 68)
89 t.tm_year = digit_pair[0] * 100 + digit_pair[1];
100 /* Use current year. */
102 tmp = localtime (&now);
103 t.tm_year = tmp->tm_year;
115 posix_time_parse (const char *s, unsigned int syntax_bits)
117 const char *dot = NULL;
122 size_t s_len = strlen (s);
123 size_t len = (((syntax_bits & PDS_SECONDS) && (dot = strchr (s, '.')))
127 if (len != 8 && len != 10 && len != 12)
132 if (!(syntax_bits & PDS_SECONDS))
135 if (s_len - len != 3)
139 for (i = 0; i < len; i++)
144 for (i = 0; i < len; i++)
145 pair[i] = 10 * (s[2*i] - '0') + s[2*i + 1] - '0';
148 if (syntax_bits & PDS_LEADING_YEAR)
150 if (year (p, len - 4, syntax_bits & PDS_CENTURY))
156 /* Handle 8 digits worth of `MMDDhhmm'. */
157 if (*p < 1 || *p > 12)
162 if (*p < 1 || *p > 31)
167 if (*p < 0 || *p > 23)
172 if (*p < 0 || *p > 59)
177 /* Handle any trailing year. */
178 if (syntax_bits & PDS_TRAILING_YEAR)
180 if (year (p, len, syntax_bits & PDS_CENTURY))
184 /* Handle seconds. */
194 if (!ISDIGIT (dot[0]) || !ISDIGIT (dot[1]))
196 seconds = 10 * (dot[0] - '0') + dot[1] - '0';
198 if (seconds < 0 || seconds > 61)
206 /* Parse a POSIX-style date and return it, or (time_t)-1 for an error. */
209 posixtime (const char *s, unsigned int syntax_bits)
212 if (posix_time_parse (s, syntax_bits))
218 /* Parse a POSIX-style date and return it, or NULL for an error. */
221 posixtm (const char *s, unsigned int syntax_bits)
223 if (posixtime (s, syntax_bits) == -1)
228 #ifdef TEST_POSIXTIME
230 Test mainly with syntax_bits == 13
231 (aka: (PDS_LEADING_YEAR | PDS_CENTURY | PDS_SECONDS))
234 1112131415 13 1323807300 Tue Dec 13 14:15:00 2011
235 1112131415.16 13 1323807316 Tue Dec 13 14:15:16 2011
236 201112131415.16 13 1323807316 Tue Dec 13 14:15:16 2011
237 191112131415.16 13 -1 ***
238 203712131415.16 13 2144348116 Sun Dec 13 14:15:16 2037
239 3712131415.16 13 2144348116 Sun Dec 13 14:15:16 2037
240 6812131415.16 13 -1 ***
241 6912131415.16 13 -1 ***
242 7012131415.16 13 29967316 Sun Dec 13 14:15:16 1970
243 12131415.16 13 913580116 Sun Dec 13 14:15:16 1998
245 1213141599 2 945116100 Mon Dec 13 14:15:00 1999
246 1213141500 2 976738500 Wed Dec 13 14:15:00 2000
251 # define MAX_BUFF_LEN 1024
256 char buff[MAX_BUFF_LEN + 1];
258 buff[MAX_BUFF_LEN] = 0;
259 while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
261 char time_str[MAX_BUFF_LEN];
262 unsigned int syntax_bits;
265 sscanf (buff, "%s %u", time_str, &syntax_bits);
266 t = posixtime (time_str, syntax_bits);
267 result = (t == (time_t) -1 ? "***" : ctime (&t));
268 printf ("%d %s\n", (int) t, result);