1.\" $NetBSD: parsedate.3,v 1.27 2024/05/02 18:34:01 rillig 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.Pq but see the BUGS section below , 101.Dv second 102is unused so that it is not confused with 103.Dq seconds , 104.Dv two = 1052, 106.Dv third 107or 108.Dv three = 1093, 110.Dv fourth 111or 112.Dv four = 1134, 114.Dv fifth 115or 116.Dv five = 1175, 118.Dv sixth 119or 120.Dv six = 1216, 122.Dv seventh 123or 124.Dv seven = 1257, 126.Dv eighth 127or 128.Dv eight = 1298, 130.Dv ninth 131or 132.Dv nine = 1339, 134.Dv tenth 135or 136.Dv ten = 13710, 138.Dv eleventh 139or 140.Dv eleven = 14111, 142.Dv twelfth 143or 144.Dv twelve = 14512. 146.Pp 147The following words are recognized in English only: 148.Dv AM , 149.Dv PM , 150.Dv a.m. , 151.Dv p.m. , 152.Dv midnight , 153.Dv mn , 154.Dv noon . 155.Pp 156The months: 157.Dv january , 158.Dv february , 159.Dv march , 160.Dv april , 161.Dv may , 162.Dv june , 163.Dv july , 164.Dv august , 165.Dv september , 166.Dv october , 167.Dv november , 168.Dv december , 169and common abbreviations for them. 170When a month name (or its ordinal number) is given, 171the number of some particular day of that month is required to accompany it. 172This is generally true of any data that specifies a period 173with a duration longer than a day, so simply specifying a year, 174or a month, is invalid, as also is specifying a year and a month. 175.Pp 176The days of the week: 177.Dv sunday , 178.Dv monday , 179.Dv tuesday , 180.Dv wednesday , 181.Dv thursday , 182.Dv friday , 183.Dv saturday , 184and common abbreviations for them. 185Weekday names are typically ignored if any other data 186is given to specify the date, even if the name given 187is not the day on which the specified date occurred. 188.Pp 189Time units: 190.Dv year , 191.Dv month , 192.Dv fortnight , 193.Dv week , 194.Dv day , 195.Dv hour , 196.Dv minute , 197.Dv min , 198.Dv second , 199.Dv sec , 200.Dv tomorrow , 201.Dv yesterday . 202.Pp 203Timezone names: 204.Dv gmt (+0000) , 205.Dv ut (+0000) , 206.Dv utc (+0000) , 207.Dv wet (+0000) , 208.Dv bst (+0100) , 209.Dv wat (-0100) , 210.Dv at (-0200) , 211.Dv nft (-0330) , 212.Dv nst (-0330) , 213.Dv ndt (-0230) , 214.Dv ast (-0400) , 215.Dv adt (-0300) , 216.Dv est (-0500) , 217.Dv edt (-0400) , 218.Dv cst (-0600) , 219.Dv cdt (-0500) , 220.Dv mst (-0700) , 221.Dv mdt (-0600) , 222.Dv pst (-0800) , 223.Dv pdt (-0700) , 224.Dv yst (-0900) , 225.Dv ydt (-0800) , 226.Dv hst (-1000) , 227.Dv hdt (-0900) , 228.Dv cat (-1000) , 229.Dv ahst (-1000) , 230.Dv nt (-1100) , 231.Dv idlw (-1200) , 232.Dv cet (+0100) , 233.Dv met (+0100) , 234.Dv mewt (+0100) , 235.Dv mest (+0200) , 236.Dv swt (+0100) , 237.Dv sst (+0200) , 238.Dv fwt (+0100) , 239.Dv fst (+0200) , 240.Dv eet (+0200) , 241.Dv bt (+0300) , 242.Dv it (+0330) , 243.\".Dv zp4 (+0400) , 244.\".Dv zp5 (+0500) , 245.Dv ist (+0530) , 246.\".Dv zp6 (+0600) , 247.Dv ict (+0700) , 248.Dv wast (+0800) , 249.Dv wadt (+0900) , 250.Dv awst (+0800) , 251.Dv awdt (+0900) , 252.Dv cct (+0800) , 253.Dv sgt (+0800) , 254.Dv hkt (+0800) , 255.Dv jst (+0900) , 256.Dv cast (+0930) , 257.Dv cadt (+1030) , 258.Dv acst (+0930) , 259.Dv acdt (+1030) , 260.Dv east (+1000) , 261.Dv eadt (+1100) , 262.Dv aest (+1000) , 263.Dv aedt (+1100) , 264.Dv gst (+1000) , 265.Dv nzt (+1200) , 266.Dv nzst (+1200) , 267.Dv nzdt (+1300) , 268.Dv idle (+1200) . 269.Pp 270The timezone names simply specify an offset from 271Coordinated Universal Time (UTC) 272and do not imply validating the time/date to be reasonable in any zone 273that happens to use the abbreviation specified. 274.Pp 275A variety of unambiguous dates are recognized: 276.Bl -tag -compact -width "20 Jun 1994" 277.It 9/10/69 278For years between 69-99 we assume 1900+ and for years between 0-68 279we assume 2000+. 280.It 2006-11-17 281An ISO-8601 date. 282Note that when using the ISO-8601 format date and time with the 283.Sq T 284designator to separate date and time-of-day, 285this must appear at the start of the input string, 286with no preceding whitespace. 287Other modifiers may optionally follow. 288.It 67-09-10 289The year in an ISO-8601 date is always taken literally, 290so this is the year 67, not 2067. 291.It 10/1/2000 292October 1, 2000; the common, but bizarre, US format. 293.It 20 Jun 1994 294.It 23jun2001 295.It 1-sep-06 296Other common abbreviations. 297.It 1/11 298The year can be omitted. 299A missing year is taken from the 300.Ar \&*time 301value, or 302.Dq now 303if 304.Ar time 305is NULL. 306Again, this is the US month/day format (the 11th of January). 307.El 308.Pp 309Standard e-mail (RFC822, RFC2822, etc) 310formats and the output from 311.Xr date 1 , 312and 313.Xr asctime 3 314are all supported as input, 315as is cvs date format (where years < 100 are treated as 31620th century). 317.Pp 318Times can also be specified in common forms: 319.Bl -tag -compact -width 12:11:01.000012 320.It 10:01 321.It 10:12pm 322.It 12:11:01.000012 323.It 12:21-0500 324.El 325Fractions of seconds (after a decimal point, or comma) are parsed, but ignored. 326If no time is given, midnight on the specified date is assumed. 327If a time is given without a date, that time on the day 328specified by 329.Ar \&*time 330.Pq or now 331is used. 332Missing minutes, or seconds, are taken to be zero. 333.Pp 334A variety of forms for relative items to specify 335an offset from the base time are also supported: 336.Bl -tag -compact -width "this thursday" 337.It -1 month 338.It last friday 339.It one week ago 340.It this thursday 341.It next sunday 342.It +2 years 343.El 344.Pp 345Note that, as a special case for 346.Dv midnight 347with the name of a day only, 348.Dq "midnight tuesday" 349implies 00:00 at the beginning of Tuesday, 350.Pq "the midnight before Tuesday" 351whereas 352.Dq "Sat mn" 353implies 00:00 at the end of Saturday 354.Pq "midnight after Saturday" 355.Pq "i.e. early Sunday morning" . 356.Pp 357Seconds since epoch, UTC, (also known as UNIX time) are also supported 358to specify the base time: 359.Bl -tag -compact -width "E.g.:\ @735275209\ \ \ \ " 360.It "E.g.: @735275209" 361to specify: Tue Apr 20 03:06:49 UTC 1993 362.El 363provided that the value given is within the range 364that can be represented as a 365.Va "struct tm" . 366Negative values 367(times before the epoch) 368are permitted, but no other significant data as part of 369the base time \(en the value given specifies year, month, 370day, hour, minute, and second, there is no more. 371An offset from this base time may still be included. 372Thus 373.Dq "@735275209 +2 months 5 hours 15 minutes" 374produces a time_t which represents 375.Dq "Sun Jun 20 08:21:49 UTC 1993" . 376.Pp 377Text in 378.Ar datestr 379enclosed in parentheses 380.Ql \&( 381and 382.Ql \&) 383is treated as a comment, and ignored. 384Parentheses nest (the comment ends when there have 385been the same number of closing parentheses as there 386were opening parentheses.) 387There is no escape character in comments, 388.Ql \&) 389always ends 390(or decreases the nesting level of) 391the comment. 392.Sh RETURN VALUES 393.Fn parsedate 394returns the number of seconds passed since, 395or before (if negative,) 396the Epoch, or 397.Dv \-1 398if the date could not be parsed properly. 399A non-error result of 400.Dv \-1 401can be distinguished from an error by setting 402.Va errno 403to 404.Dv 0 405before calling 406.Fn parsedate , 407and checking the value of 408.Va errno 409afterwards. 410.Sh ENVIRONMENT 411If the 412.Ar tzoff 413parameter is given as 414.Dv NULL , 415then: 416.Bl -tag -width iTZ 417.It Ev TZ 418The timezone to which the input is relative, 419when no zone information is otherwise specified in the 420.Ar datestr 421input. 422.El 423.Sh SEE ALSO 424.Xr date 1 , 425.Xr touch 1 , 426.Xr errno 2 , 427.Xr ctime 3 , 428.\" WTF ???? eeprom(8)!! Why? Just because it calls this function? Weird! 429.Xr eeprom 8 430.Sh HISTORY 431The parser used in 432.Fn parsedate 433was originally written by Steven M. Bellovin while at the University 434of North Carolina at Chapel Hill. 435It was later tweaked by a couple of people on Usenet. 436Completely overhauled by Rich $alz and Jim Berets in August, 1990. 437Further mangled during its residence with 438.Nx . 439.Pp 440The 441.Fn parsedate 442function first appeared in 443.Nx 4.0 . 444.Sh BUGS 445.Bl -tag -compact -width 1 446.It 1 447The 448.Fn parsedate 449function is not re-entrant or thread-safe. 450.It 2 451The 452.Fn parsedate 453function assumes years less than 0 mean \(mi 454.Fa year , 455and in non ISO formats, 456that years less than 69 mean 2000 + 457.Fa year , 458otherwise 459years less than 100 mean 1900 + 460.Fa year . 461That is except in the CVS format, where years less than 100 462mean 1900 + 463.Fa year . 464.It 3 465The 466.Fn parsedate 467function accepts 468.Dq "12 am" 469where 470.Dq "12 midnight" 471is correct, and similarly 472.Dq "12 pm" 473for 474.Dq "12 noon" . 475The correct forms are also accepted. 476.It 4 477There are various weird cases that are hard to explain, 478but are nevertheless considered correct. 479.It 5 480It is very hard to specify years BC, 481and in any case, 482conversions of times before the 483commencement of the modern Gregorian calendar 484(when that occurred depends upon location, 485but late 16th century is a rough guide) 486are suspicious at best, 487and depending upon context, 488often just plain wrong. 489.It 6 490Despite what is stated above, 491.Dq next 492is actually 2. 493The input 494.Dq "next January" , 495instead of producing a timestamp for January of the 496following year, produces one for January 2nd, of the 497current year. 498Use caution with 499.Dq next 500it rarely does what humans expect. 501For example, on a Sunday 502.Dq "next sunday" 503means the following Sunday (7 days hence) 504whereas 505.Dq "next monday" 506means the monday that follows that (8 days hence) 507rather than 508.Dq tomorrow 509or just 510.Dq Mon 511.Pq without the Dq next 512which is the nearest subsequent Monday. 513.El 514