1.\" $NetBSD: parsedate.3,v 1.25 2020/10/19 15:08:39 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 October 19, 2020 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 (+0550) , 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 acst (+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