Module Name:    src
Committed By:   kre
Date:           Wed Mar 22 01:49:37 UTC 2017

Modified Files:
        src/lib/libutil: parsedate.3 parsedate.y

Log Message:
Make parsedate handle "12 noon" and "12 midnight" (including when
the time is "12:00" or "12:00:00) - but only for exactly 12 o'clock.
"12:00:01" is am or pm, not noon or midnight.

"12 am" remains as an alias for "12 midnight", and "12 pm" for midnight,
though both are strictly invalid (and meaningless.)

Note that "12 pm" means 00:00:00 (ie: midnight at the start of the
day, not at the end.)


To generate a diff of this commit:
cvs rdiff -u -r1.22 -r1.23 src/lib/libutil/parsedate.3
cvs rdiff -u -r1.30 -r1.31 src/lib/libutil/parsedate.y

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libutil/parsedate.3
diff -u src/lib/libutil/parsedate.3:1.22 src/lib/libutil/parsedate.3:1.23
--- src/lib/libutil/parsedate.3:1.22	Fri Dec 23 06:01:41 2016
+++ src/lib/libutil/parsedate.3	Wed Mar 22 01:49:36 2017
@@ -1,4 +1,4 @@
-.\"     $NetBSD: parsedate.3,v 1.22 2016/12/23 06:01:41 abhinav Exp $
+.\"     $NetBSD: parsedate.3,v 1.23 2017/03/22 01:49:36 kre Exp $
 .\"
 .\" Copyright (c) 2006 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 7, 2015
+.Dd March 22, 2017
 .Dt PARSEDATE 3
 .Os
 .Sh NAME
@@ -393,9 +393,21 @@ otherwise
 years less than 100 mean 1900 +
 .Fa year .
 .It 3
+The
+.Fn parsedate
+function accepts
+.Dq "12 am"
+where
+.Dq "12 midnight"
+is correct, and similarly
+.Dq "12 pm"
+for
+.Dq "12 noon" .
+The correct forms are also accepted.
+.It 4
 There are various weird cases that are hard to explain,
 but are nevertheless considered correct.
-.It 4
+.It 5
 It is very hard to specify years BC,
 and in any case,
 conversions of times before the

Index: src/lib/libutil/parsedate.y
diff -u src/lib/libutil/parsedate.y:1.30 src/lib/libutil/parsedate.y:1.31
--- src/lib/libutil/parsedate.y:1.30	Wed Mar 22 00:59:06 2017
+++ src/lib/libutil/parsedate.y	Wed Mar 22 01:49:36 2017
@@ -14,7 +14,7 @@
 
 #include <sys/cdefs.h>
 #ifdef __RCSID
-__RCSID("$NetBSD: parsedate.y,v 1.30 2017/03/22 00:59:06 kre Exp $");
+__RCSID("$NetBSD: parsedate.y,v 1.31 2017/03/22 01:49:36 kre Exp $");
 #endif
 
 #include <stdio.h>
@@ -64,10 +64,10 @@ typedef enum _DSTMODE {
 } DSTMODE;
 
 /*
-**  Meridian:  am, pm, or 24-hour style.
+**  Meridian:  am, pm, or 24-hour style (plus "noon" and "midnight").
 */
 typedef enum _MERIDIAN {
-    MERam, MERpm, MER24
+    MERam, MERpm, MER24, MER_NOON, MER_MN
 } MERIDIAN;
 
 
@@ -191,22 +191,58 @@ at_number:
 
 time:
 	  tUNUMBER tMERIDIAN {
-		param->yyHour = $1;
 		param->yyMinutes = 0;
 		param->yySeconds = 0;
-		param->yyMeridian = $2;
+		if ($2 == MER_NOON || $2 == MER_MN) {
+			if ($1 == 12) {
+				switch ($2) {
+				case MER_NOON: param->yyHour = 12; break;
+				case MER_MN  : param->yyHour = 0;  break;
+				default:	/* impossible */;  break;
+				}
+				param->yyMeridian = MER24;
+			} else
+				YYREJECT;
+		} else {
+			param->yyHour = $1;
+			param->yyMeridian = $2;
+		}
 	  }
 	| tUNUMBER ':' tUNUMBER o_merid {
-		param->yyHour = $1;
 		param->yyMinutes = $3;
 		param->yySeconds = 0;
-		param->yyMeridian = $4;
+		if ($4 == MER_NOON || $4 == MER_MN) {
+			if ($1 == 12 && $3 == 0) {
+				switch ($4) {
+				case MER_NOON: param->yyHour = 12; break;
+				case MER_MN  : param->yyHour = 0;  break;
+				default:	/* impossible */;  break;
+				}
+				param->yyMeridian = MER24;
+			} else
+				YYREJECT;
+		} else {
+			param->yyHour = $1;
+			param->yyMeridian = $4;
+		}
 	  }
 	| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
-		param->yyHour = $1;
 		param->yyMinutes = $3;
 		param->yySeconds = $5;
-		param->yyMeridian = $6;
+		if ($6 == MER_NOON || $6 == MER_MN) {
+			if ($1 == 12 && $3 == 0 && $5 == 0) {
+				switch ($6) {
+				case MER_NOON: param->yyHour = 12; break;
+				case MER_MN  : param->yyHour = 0;  break;
+				default:	/* impossible */;  break;
+				}
+				param->yyMeridian = MER24;
+			} else
+				YYREJECT;
+		} else {
+			param->yyHour = $1;
+			param->yyMeridian = $6;
+		}
 	  }
 	| tUNUMBER ':' tUNUMBER ':' tUNUMBER '.' tUNUMBER {
 		param->yyHour = $1;
@@ -223,7 +259,16 @@ time:
 		/* Tues midnight --> Weds 00:00, midnight Tues -> Tues 00:00 */
 		if ($1 == 0 && param->yyHaveDay)
 			param->yyDayNumber++;
-	}
+	  }
+	| tUNUMBER tTIME {
+		if ($1 == 12 && ($2 == 0 || $2 == 12)) {
+			param->yyHour = $2;
+			param->yyMinutes = 0;
+			param->yySeconds = 0;
+			param->yyMeridian = MER24;
+		} else
+			YYREJECT;
+	  }
 ;
 
 time_numericzone:
@@ -362,6 +407,7 @@ number:
 o_merid:
 	  /* empty */		{ $$ = MER24; }
 	| tMERIDIAN		{ $$ = $1; }
+	| tTIME			{ $$ = $1 == 0 ? MER_MN : MER_NOON; }
 ;
 
 %%

Reply via email to