xref: /netbsd-src/lib/libutil/parsedate.3 (revision afab4e300d3a9fb07dd8c80daf53d0feb3345706)
1.\"     $NetBSD: parsedate.3,v 1.26 2021/05/16 19:42:35 kre Exp $
2.\"
3.\" Copyright (c) 2006 The NetBSD Foundation, Inc.
4.\" All rights reserved.
5.\"
6.\" This code is derived from software contributed to The NetBSD Foundation
7.\" by Christos Zoulas.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\"    notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\"    notice, this list of conditions and the following disclaimer in the
16.\"    documentation and/or other materials provided with the distribution.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28.\" POSSIBILITY OF SUCH DAMAGE.
29.\"
30.Dd May 16, 2021
31.Dt PARSEDATE 3
32.Os
33.Sh NAME
34.Nm parsedate
35.Nd date parsing function
36.Sh LIBRARY
37.Lb libutil
38.Sh SYNOPSIS
39.In util.h
40.Ft time_t
41.Fn parsedate "const char *datestr" "const time_t *time" "const int *tzoff"
42.Sh DESCRIPTION
43The
44.Fn parsedate
45function parses a date and time from
46.Ar datestr
47described in English relative to an optional
48.Ar time
49point,
50and an optional timezone offset (in minutes behind/west of UTC)
51specified in
52.Ar tzoff .
53If
54.Ar time
55is
56.Dv NULL
57then the current time is used.
58If
59.Ar tzoff
60is
61.Dv NULL ,
62then the current time zone is used.
63.Pp
64The
65.Ar datestr
66is a sequence of white-space separated items.
67The white-space is optional if the concatenated items are not ambiguous.
68The string contains data which can specify a base time (used in
69conjunction with the
70.Ar time
71parameter, totally replacing that parameter's value if sufficient data
72appears in
73.Ar datestr
74to do so), and data specifying an offset from the base time.
75Both of those are optional.
76If no data specifies the base time, then
77.Nm
78simply uses the value given by
79.Ar \&*time
80.Pq "or now" .
81If there is no offset data then no offset is applied.
82An empty
83.Ar datestr ,
84or a
85.Ar datestr
86containing nothing but whitespace,
87is equivalent to midnight at the start of the day specified by
88.Ar \&*time
89.Pq "or today" .
90.Pp
91The following words have the indicated numeric meanings:
92.Dv last =
93\-1,
94.Dv this =
950,
96.Dv first , next ,
97or
98.Dv one =
991,
100.Dv second
101is unused so that it is not confused with
102.Dq seconds ,
103.Dv two =
1042,
105.Dv third
106or
107.Dv three =
1083,
109.Dv fourth
110or
111.Dv four =
1124,
113.Dv fifth
114or
115.Dv five  =
1165,
117.Dv sixth
118or
119.Dv six  =
1206,
121.Dv seventh
122or
123.Dv seven =
1247,
125.Dv eighth
126or
127.Dv eight =
1288,
129.Dv ninth
130or
131.Dv nine =
1329,
133.Dv tenth
134or
135.Dv ten =
13610,
137.Dv eleventh
138or
139.Dv eleven =
14011,
141.Dv twelfth
142or
143.Dv twelve =
14412.
145.Pp
146The following words are recognized in English only:
147.Dv AM ,
148.Dv PM ,
149.Dv a.m. ,
150.Dv p.m. ,
151.Dv midnight ,
152.Dv mn ,
153.Dv noon .
154.Pp
155The months:
156.Dv january ,
157.Dv february ,
158.Dv march ,
159.Dv april ,
160.Dv may ,
161.Dv june ,
162.Dv july ,
163.Dv august ,
164.Dv september ,
165.Dv october ,
166.Dv november ,
167.Dv december ,
168and common abbreviations for them.
169When a month name (or its ordinal number) is given,
170the number of some particular day of that month is required to accompany it.
171This is generally true of any data that specifies a period
172with a duration longer than a day, so simply specifying a year,
173or a month, is invalid, as also is specifying a year and a month.
174.Pp
175The days of the week:
176.Dv sunday ,
177.Dv monday ,
178.Dv tuesday ,
179.Dv wednesday ,
180.Dv thursday ,
181.Dv friday ,
182.Dv saturday ,
183and common abbreviations for them.
184Weekday names are typically ignored if any other data
185is given to specify the date, even if the name given
186is not the day on which the specified date occurred.
187.Pp
188Time units:
189.Dv year ,
190.Dv month ,
191.Dv fortnight ,
192.Dv week ,
193.Dv day ,
194.Dv hour ,
195.Dv minute ,
196.Dv min ,
197.Dv second ,
198.Dv sec ,
199.Dv tomorrow ,
200.Dv yesterday .
201.Pp
202Timezone names:
203.Dv gmt (+0000) ,
204.Dv ut (+0000) ,
205.Dv utc (+0000) ,
206.Dv wet (+0000) ,
207.Dv bst (+0100) ,
208.Dv wat (-0100) ,
209.Dv at (-0200) ,
210.Dv nft (-0330) ,
211.Dv nst (-0330) ,
212.Dv ndt (-0230) ,
213.Dv ast (-0400) ,
214.Dv adt (-0300) ,
215.Dv est (-0500) ,
216.Dv edt (-0400) ,
217.Dv cst (-0600) ,
218.Dv cdt (-0500) ,
219.Dv mst (-0700) ,
220.Dv mdt (-0600) ,
221.Dv pst (-0800) ,
222.Dv pdt (-0700) ,
223.Dv yst (-0900) ,
224.Dv ydt (-0800) ,
225.Dv hst (-1000) ,
226.Dv hdt (-0900) ,
227.Dv cat (-1000) ,
228.Dv ahst (-1000) ,
229.Dv nt (-1100) ,
230.Dv idlw (-1200) ,
231.Dv cet (+0100) ,
232.Dv met (+0100) ,
233.Dv mewt (+0100) ,
234.Dv mest (+0200) ,
235.Dv swt (+0100) ,
236.Dv sst (+0200) ,
237.Dv fwt (+0100) ,
238.Dv fst (+0200) ,
239.Dv eet (+0200) ,
240.Dv bt (+0300) ,
241.Dv it (+0330) ,
242.\".Dv zp4 (+0400) ,
243.\".Dv zp5 (+0500) ,
244.Dv ist (+0530) ,
245.\".Dv zp6 (+0600) ,
246.Dv ict (+0700) ,
247.Dv wast (+0800) ,
248.Dv wadt (+0900) ,
249.Dv awst (+0800) ,
250.Dv awdt (+0900) ,
251.Dv cct (+0800) ,
252.Dv sgt (+0800) ,
253.Dv hkt (+0800) ,
254.Dv jst (+0900) ,
255.Dv cast (+0930) ,
256.Dv cadt (+1030) ,
257.Dv acst (+0930) ,
258.Dv acdt (+1030) ,
259.Dv east (+1000) ,
260.Dv eadt (+1100) ,
261.Dv aest (+1000) ,
262.Dv aedt (+1100) ,
263.Dv gst (+1000) ,
264.Dv nzt (+1200) ,
265.Dv nzst (+1200) ,
266.Dv nzdt (+1300) ,
267.Dv idle (+1200) .
268.Pp
269The timezone names simply specify an offset from
270Coordinated Universal Time (UTC)
271and do not imply validating the time/date to be reasonable in any zone
272that happens to use the abbreviation specified.
273.Pp
274A variety of unambiguous dates are recognized:
275.Bl -tag -compact -width "20 Jun 1994"
276.It 9/10/69
277For years between 69-99 we assume 1900+ and for years between 0-68
278we assume 2000+.
279.It 2006-11-17
280An ISO-8601 date.
281Note that when using the ISO-8601 format date and time with the
282.Sq T
283designator to separate date and time-of-day,
284this must appear at the start of the input string,
285with no preceding whitespace.
286Other modifiers may optionally follow.
287.It 67-09-10
288The year in an ISO-8601 date is always taken literally,
289so this is the year 67, not 2067.
290.It 10/1/2000
291October 1, 2000; the common, but bizarre, US format.
292.It 20 Jun 1994
293.It 23jun2001
294.It 1-sep-06
295Other common abbreviations.
296.It 1/11
297The year can be omitted.
298A missing year is taken from the
299.Ar \&*time
300value, or
301.Dq now
302if
303.Ar time
304is NULL.
305Again, this is the US month/day format (the 11th of January).
306.El
307.Pp
308Standard e-mail (RFC822, RFC2822, etc)
309formats and the output from
310.Xr date 1 ,
311and
312.Xr asctime 3
313are all supported as input,
314as is cvs date format (where years < 100 are treated as
31520th century).
316.Pp
317Times can also be specified in common forms:
318.Bl -tag -compact -width 12:11:01.000012
319.It 10:01
320.It 10:12pm
321.It 12:11:01.000012
322.It 12:21-0500
323.El
324Fractions of seconds (after a decimal point, or comma) are parsed, but ignored.
325If no time is given, midnight on the specified date is assumed.
326If a time is given without a date, that time on the day
327specified by
328.Ar \&*time
329.Pq or now
330is used.
331Missing minutes, or seconds, are taken to be zero.
332.Pp
333A variety of forms for relative items to specify
334an offset from the base time are also supported:
335.Bl -tag -compact -width "this thursday"
336.It -1 month
337.It last friday
338.It one week ago
339.It this thursday
340.It next sunday
341.It +2 years
342.El
343.Pp
344Note that, as a special case for
345.Dv midnight
346with the name of a day only,
347.Dq "midnight tuesday"
348implies 00:00 at the beginning of Tuesday,
349.Pq "the midnight before Tuesday"
350whereas
351.Dq "Sat mn"
352implies 00:00 at the end of Saturday
353.Pq "midnight after Saturday"
354.Pq "i.e. early Sunday morning" .
355.Pp
356Seconds since epoch, UTC, (also known as UNIX time) are also supported
357to specify the base time:
358.Bl -tag -compact -width "E.g.:\ @735275209\ \ \ \ "
359.It "E.g.: @735275209"
360to specify: Tue Apr 20 03:06:49 UTC 1993
361.El
362provided that the value given is within the range
363that can be represented as a
364.Va "struct tm" .
365Negative values
366(times before the epoch)
367are permitted, but no other significant data as part of
368the base time \(en the value given specifies year, month,
369day, hour, minute, and second, there is no more.
370An offset from this base time may still be included.
371Thus
372.Dq "@735275209 +2 months 5 hours 15 minutes"
373produces a time_t which represents
374.Dq "Sun Jun 20 08:21:49 UTC 1993" .
375.Pp
376Text in
377.Ar datestr
378enclosed in parentheses
379.Ql \&(
380and
381.Ql \&)
382is treated as a comment, and ignored.
383Parentheses nest (the comment ends when there have
384been the same number of closing parentheses as there
385were opening parentheses.)
386There is no escape character in comments,
387.Ql \&)
388always ends
389(or decreases the nesting level of)
390the comment.
391.Sh RETURN VALUES
392.Fn parsedate
393returns the number of seconds passed since,
394or before (if negative,)
395the Epoch, or
396.Dv \-1
397if the date could not be parsed properly.
398A non-error result of
399.Dv \-1
400can be distinguished from an error by setting
401.Va errno
402to
403.Dv 0
404before calling
405.Fn parsedate ,
406and checking the value of
407.Va errno
408afterwards.
409.Sh ENVIRONMENT
410If the
411.Ar tzoff
412parameter is given as
413.Dv NULL ,
414then:
415.Bl -tag -width iTZ
416.It Ev TZ
417The timezone to which the input is relative,
418when no zone information is otherwise specified in the
419.Ar datestr
420input.
421.El
422.Sh SEE ALSO
423.Xr date 1 ,
424.Xr touch 1 ,
425.Xr errno 2 ,
426.Xr ctime 3 ,
427.\" WTF ????  eeprom(8)!!  Why?  Just because it calls this function?  Weird!
428.Xr eeprom 8
429.Sh HISTORY
430The parser used in
431.Fn parsedate
432was originally written by Steven M. Bellovin while at the University
433of North Carolina at Chapel Hill.
434It was later tweaked by a couple of people on Usenet.
435Completely overhauled by Rich $alz and Jim Berets in August, 1990.
436Further mangled during its residence with
437.Nx .
438.Pp
439The
440.Fn parsedate
441function first appeared in
442.Nx 4.0 .
443.Sh BUGS
444.Bl -tag -compact -width 1
445.It 1
446The
447.Fn parsedate
448function is not re-entrant or thread-safe.
449.It 2
450The
451.Fn parsedate
452function assumes years less than 0 mean \(mi
453.Fa year ,
454and in non ISO formats,
455that years less than 69 mean 2000 +
456.Fa year ,
457otherwise
458years less than 100 mean 1900 +
459.Fa year .
460That is except in the CVS format, where years less than 100
461mean 1900 +
462.Fa year .
463.It 3
464The
465.Fn parsedate
466function accepts
467.Dq "12 am"
468where
469.Dq "12 midnight"
470is correct, and similarly
471.Dq "12 pm"
472for
473.Dq "12 noon" .
474The correct forms are also accepted.
475.It 4
476There are various weird cases that are hard to explain,
477but are nevertheless considered correct.
478.It 5
479It is very hard to specify years BC,
480and in any case,
481conversions of times before the
482commencement of the modern Gregorian calendar
483(when that occurred depends upon location,
484but late 16th century is a rough guide)
485are suspicious at best,
486and depending upon context,
487often just plain wrong.
488.It 6
489Despite what is stated above,
490.Dq next
491is actually 2.
492The input
493.Dq "next January" ,
494instead of producing a timestamp for January of the
495following year, produces one for January 2nd, of the
496current year.
497Use caution with
498.Dq next
499it rarely does what humans expect.
500For example, on a Sunday
501.Dq "next sunday"
502means the following Sunday (7 days hence)
503whereas
504.Dq "next monday"
505means the monday that follows that (8 days hence)
506rather than
507.Dq tomorrow
508or just
509.Dq Mon
510.Pq without the Dq next
511which is the nearest subsequent Monday.
512.El
513