libc: Bring in getdate() from NetBSD for POSIX conformance.
authorSascha Wildner <saw@online.de>
Sun, 24 May 2020 09:48:26 +0000 (11:48 +0200)
committerSascha Wildner <saw@online.de>
Sun, 24 May 2020 09:53:55 +0000 (11:53 +0200)
etc/mtree/BSD.usr.dist
include/time.h
lib/libc/Versions.def
lib/libc/stdtime/Makefile.inc
lib/libc/stdtime/Symbol.map
lib/libc/stdtime/getdate.3 [new file with mode: 0644]
lib/libc/stdtime/getdate.c [new file with mode: 0644]
share/examples/getdate/datemsk.template [new file with mode: 0644]
share/examples/getdate/posixmsk.example3 [new file with mode: 0644]
share/examples/getdate/posixmsk.example4 [new file with mode: 0644]

index 0e6b02d..f5ec2c3 100644 (file)
             ..
             find_interface
             ..
+            getdate
+            ..
             ipfw
             ..
             IPv6
index a764526..761f65b 100644 (file)
@@ -151,9 +151,6 @@ char *asctime(const struct tm *);
 clock_t clock(void);
 char *ctime(const time_t *);
 double difftime(time_t, time_t);
-#if 0 /* XXX missing */
-struct tm *getdate(const char *);
-#endif
 struct tm *gmtime(const time_t *);
 struct tm *localtime(const time_t *);
 time_t mktime(struct tm *);
@@ -195,7 +192,9 @@ int timer_settime(timer_t, int, const struct itimerspec *__restrict,
 
 #if __XSI_VISIBLE
 extern int daylight;
+extern int getdate_err;
 extern long timezone;
+struct tm *getdate(const char *) __strftimelike(1, 0);
 char *strptime(const char * __restrict, const char * __restrict,
     struct tm * __restrict) __strftimelike(2, 0);
 #endif
index cce3fc4..c49ab23 100644 (file)
@@ -49,6 +49,10 @@ DF506.0 {
 DF508.0 {
 } DF506.0;
 
+# version for DragonFly 5.9
+DF510.0 {
+} DF508.0;
+
 # This is our private namespace.  Any global interfaces that are
 # strictly for use only by other DragonFly applications and libraries
 # are listed here.  We use a separate namespace so we can write
@@ -56,4 +60,4 @@ DF508.0 {
 #
 # Please do NOT increment the version of this namespace.
 DFprivate_1.0 {
-} DF508.0;
+} DF510.0;
index d8b3f20..343834b 100644 (file)
@@ -5,11 +5,12 @@
 
 CMAPS+=        ${.CURDIR}/stdtime/Symbol.map
 
-SRCS+= asctime.c difftime.c localtime.c strftime.c strptime.c timelocal.c \
-       time32.c timespec_get.c
+SRCS+= asctime.c difftime.c getdate.c localtime.c \
+       strftime.c strptime.c timelocal.c time32.c timespec_get.c
 
 .if ${LIB} == "c"
-MAN+=  ctime.3 offtime.3 strftime.3 strptime.3 time2posix.3 timespec_get.3
+MAN+=  ctime.3 getdate.3 offtime.3 strftime.3 strptime.3 \
+       time2posix.3 timespec_get.3
 MAN+=  tzfile.5
 
 MLINKS+=ctime.3 asctime.3 \
index fafb2de..b300a69 100644 (file)
@@ -37,3 +37,7 @@ DF404.0 {
 DF406.0 {
     timespec_get;
 };
+
+DF510.0 {
+    getdate;
+};
diff --git a/lib/libc/stdtime/getdate.3 b/lib/libc/stdtime/getdate.3
new file mode 100644 (file)
index 0000000..68a2af2
--- /dev/null
@@ -0,0 +1,232 @@
+.\"    $NetBSD: getdate.3,v 1.10 2018/02/11 13:28:49 wiz Exp $
+.\"
+.\" Copyright (c) 2009, 2011, 2012, The NetBSD Foundation.
+.\" All Rights Reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Brian Ginsbach.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd May 24, 2020
+.Dt GETDATE 3
+.Os
+.Sh NAME
+.Nm getdate ,
+.Nm getdate_err
+.Nd convert user format date and time
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In time.h
+.Ft "struct tm *"
+.Fo "getdate"
+.Fa "const char *str"
+.Fc
+.Vt extern int getdate_err ;
+.Sh DESCRIPTION
+The
+.Fn getdate
+function converts a date or time character string pointed to by
+.Fa str
+into a static
+.Vt tm
+structure described in
+.Xr tm 3 .
+.Pp
+The input string is parsed and interpreted using templates.
+A text file containing templates is specified by the
+environment variable
+.Ev DATEMSK .
+This should contain the full path to the template file.
+Lines in the template file represent acceptable date and/or time
+conversion specifications.
+These specifications are similar to those given for
+.Xr strptime 3 .
+The first line in the template file that matches the input string
+is used to interpret and convert to internal time format.
+.Ss Internal Format Conversion
+The following rules apply to converting the input into the internal format.
+.Bl -bullet -offset indent
+.It
+If only the weekday is given, the conversion assumes today when the
+weekday matches today or the first future matching weekday.
+.It
+If only the month and no year is given, the conversion assumes the
+current month when the month matches or the first future matching month.
+The first day of the month is assumed if no day is given.
+.It
+If only the year is given, the values of the
+.Fa tm_mon ,
+.Fa tm_mday ,
+.Fa tm_wday ,
+.Fa tm_yday ,
+and
+.Fa tm_isdst
+members of the returned
+.Vt "struct tm"
+are unspecified.
+.It
+If the century is given, but the year within the century is not given,
+the conversion assumes the current year.
+.It
+If no hour, minute, and second are given, the conversion assumes
+the current hour, minute, and second.
+.It
+If no date is given, the conversion assumes today when the given hour
+is greater than the current hour and tomorrow when the given hour is less.
+.It
+If
+.Cm \&%Z
+is being scanned, then the broken-down time is based on the
+current time of the matched timezone and not the current runtime
+environment timezone.
+.El
+.Sh RETURN VALUES
+If successful, the
+.Fn getdate
+function returns a pointer to a static
+.Vt tm
+structure containing the broken-down time.
+Otherwise, a null pointer is returned and
+.Va getdate_err
+is set to indicate the error.
+.Pp
+The variable
+.Va getdate_err
+can have the following values:
+.Bl -tag -width NNN
+.It 1
+.Ev DATEMSK
+environment variable is null or undefined.
+.It 2
+Cannot open the template file for reading.
+.It 3
+Get file status failed for template file.
+.It 4
+Template file is not a regular file.
+.It 5
+Encountered an error while reading the template file.
+.It 6
+Cannot allocate memory.
+.It 7
+Input string does not match any line in the template file.
+.It 8
+Input string is invalid (for example, February 31)
+or could not be represented in a
+.Vt time_t .
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width DATEMSK
+.It Ev DATEMSK
+The full path to the text file containing the templates
+for acceptable date and/or time conversions.
+.El
+.Sh FILES
+.Bl -tag -width DATEMSK
+.It  Pa /usr/share/examples/getdate/datemsk.template
+An example template file that could be specified via the
+.Ev DATEMSK
+environment variable.
+.El
+.Sh EXAMPLES
+The following example shows the possible contents of a template file:
+.Pp
+.Bd -literal -offset indent -compact
+%m
+%A %B %d, %Y, %H:%M:%S
+%A
+%B
+%m/%d/%y %I %p
+%d,%m,%Y %H:%M
+at %A the %dst of %B in %Y
+run job at %I %p, %B %dnd
+%A den %d. %B %Y %H.%M Uhr
+.Ed
+.Pp
+The following are examples of valid input for the above template:
+.Pp
+.Bd -literal -offset indent -compact
+10/1/87 4 PM
+Friday
+Friday September 18, 1987, 10:30:30
+24,9,1986 10:30
+at monday the 1st of december in 1986
+run job at 3 PM, december 2nd
+.Ed
+.Pp
+The following examples show how local data and time specification can be
+defined in the template.
+.Bl -column -offset indent ".Li Friday 12:00:00" ".Sy Line in Template"
+.It Sy "Input String" Ta Sy "Line in Template"
+.It Li 11/27/86 Ta Li \&%m/\&%d/\&%y
+.It Li 27.11.86 Ta Li \&%d.\&%m.\&%y
+.It Li 86-11-27 Ta Li \&%y-\&%m-\&%d
+.It Li "Friday 12:00:00" Ta Li "\&%A \&%H:\&%M:\&%S"
+.El
+.Pp
+The following examples illustrate the Internal Format Conversion rules
+given that the current date is
+.Li "Mon Sep 22 12:19:47 EDT 1986"
+and the
+.Ev LC_TIME
+environment variable is set to the default C locale.
+.Bl -column -offset indent ".Li Jan Wed 1989" ".Sy Line in Template" ".Sy Date"
+.It Sy Input String Ta Sy Line in Template Ta Sy Date
+.It Li Mon Ta Li \&%a Ta Li "Mon Sep 22 12:19:47 EDT 1986"
+.It Li Sun Ta Li \&%a Ta Li "Sun Sep 28 12:19:47 EDT 1986"
+.It Li Fri Ta Li \&%a Ta Li "Fri Sep 26 12:19:47 EDT 1986"
+.It Li September Ta Li \&%B Ta Li "Mon Sep  1 12:19:47 EDT 1986"
+.It Li January Ta Li \&%B Ta Li "Thu Jan  1 12:19:47 EST 1987"
+.It Li December Ta Li \&%B Ta Li "Mon Dec  1 12:19:47 EST 1986"
+.It Li "Sep Mon" Ta Li "\&%b %a" Ta Li "Mon Sep  1 12:19:47 EDT 1986"
+.It Li "Jan Fri" Ta Li "\&%b %a" Ta Li "Fri Jan  2 12:19:47 EST 1987"
+.It Li "Dec Mon" Ta Li "\&%b %a" Ta Li "Mon Dec  1 12:19:47 EST 1986"
+.It Li "Jan Wed 1989" Ta Li "\&%b \&%a \&%Y" Ta Li "Wed Jan  4 12:19:47 EST 1989"
+.It Li "Fri 9" Ta Li "\&%a \&%H" Ta Li "Fri Sep 26 09:00:00 EDT 1986"
+.It Li "Feb 10:30" Ta Li "\&%b \&%H:\&%S" Ta Li "Sun Feb  1 10:00:30 EST 1987"
+.It Li 10:30 Ta Li "\&%H:\&%M" Ta Li "Tue Sep 23 10:30:00 EDT 1986"
+.It Li 13:30 Ta Li "\&%H:\&%M" Ta Li "Tue Sep 22 13:30:00 EDT 1986"
+.El
+.Sh SEE ALSO
+.Xr ctime 3 ,
+.Xr localtime 3 ,
+.Xr mktime 3 ,
+.Xr strftime 3 ,
+.Xr strptime 3 ,
+.Xr time 3
+.Sh STANDARDS
+The
+.Fn getdate
+function conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Nm
+function appeared in
+.At V.4 .
+.Sh BUGS
+The
+.Nm
+interface is inherently unsafe for multi-threaded programs or libraries,
+since it returns a pointer to a static variable and uses a global state
+variable.
diff --git a/lib/libc/stdtime/getdate.c b/lib/libc/stdtime/getdate.c
new file mode 100644 (file)
index 0000000..129a9c3
--- /dev/null
@@ -0,0 +1,274 @@
+/*     $NetBSD: getdate.c,v 1.4 2018/01/04 20:57:29 kamil Exp $        */
+/*
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Brian Ginsbach.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "namespace.h"
+
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <util.h>
+
+#include "un-namespace.h"
+
+#define TMSENTINEL     (-1)
+
+/*
+ * getdate_err is set to one of the following values on error.
+ *
+ * 1   The DATEMSK environment variable is null or undefined.
+ * 2   The template file cannot be opened for reading.
+ * 3   Failed to get file status information.
+ * 4   Template file is not a regular file.
+ * 5   Encountered an error while reading the template file.
+ * 6   Cannot allocate memory.
+ * 7   Input string does not match any line in the template.
+ * 8   Input string is invalid (for example, February 31) or could not
+ *     be represented in a time_t.
+ */
+
+int getdate_err;
+
+struct tm *
+getdate(const char *str)
+{
+       char *datemsk, *line, *rp;
+       FILE *fp;
+       struct stat sb;
+       static struct tm rtm, tmnow;
+       struct tm *tmp, *rtmp = &rtm;
+       size_t lineno = 0;
+       time_t now;
+
+       if (((datemsk = getenv("DATEMSK")) == NULL) || *datemsk == '\0') {
+               getdate_err = 1;
+               return (NULL);
+       }
+
+       if (stat(datemsk, &sb) < 0) {
+               getdate_err = 3;
+               return (NULL);
+       }
+
+       if ((sb.st_mode & S_IFMT) != S_IFREG) {
+               getdate_err = 4;
+               return (NULL);
+       }
+
+       if ((fp = fopen(datemsk, "re")) == NULL) {
+               getdate_err = 2;
+               return (NULL);
+       }
+
+       /* loop through datemsk file */
+       errno = 0;
+       rp = NULL;
+       while ((line = fparseln(fp, NULL, &lineno, NULL, 0)) != NULL) {
+               /* initialize tmp with sentinels */
+               rtm.tm_sec = rtm.tm_min = rtm.tm_hour = TMSENTINEL;
+               rtm.tm_mday = rtm.tm_mon = rtm.tm_year = TMSENTINEL;
+               rtm.tm_wday = rtm.tm_yday = rtm.tm_isdst = TMSENTINEL;
+               rtm.tm_gmtoff = 0;
+               rtm.tm_zone = NULL;
+               rp = strptime(str, line, rtmp);
+               free(line);
+               if (rp != NULL)
+                       break;
+               errno = 0;
+       }
+       if (errno != 0 || ferror(fp)) {
+               if (errno == ENOMEM)
+                       getdate_err = 6;
+               else
+                       getdate_err = 5;
+               fclose(fp);
+               return (NULL);
+       }
+       if (feof(fp) || (rp != NULL && *rp != '\0')) {
+               getdate_err = 7;
+               return (NULL);
+       }
+       fclose(fp);
+
+       time(&now);
+       tmp = localtime(&now);
+       tmnow = *tmp;
+
+       /*
+        * This implementation does not accept setting the broken-down time
+        * to anything other than the localtime().  It is not possible to
+        * change the scanned timezone with %Z.
+        *
+        * Note IRIX and Solaris accept only the current zone for %Z.
+        * XXX Is there any implementation that matches the standard?
+        * XXX (Or am I reading the standard wrong?)
+        *
+        * Note: Neither XPG 6 (POSIX 2004) nor XPG 7 (POSIX 2008)
+        * requires strptime(3) support for %Z.
+        */
+
+       /*
+        * Given only a weekday find the first matching weekday starting
+        * with the current weekday and moving into the future.
+        */
+       if (rtm.tm_wday != TMSENTINEL && rtm.tm_year == TMSENTINEL &&
+           rtm.tm_mon == TMSENTINEL && rtm.tm_mday == TMSENTINEL) {
+               rtm.tm_year = tmnow.tm_year;
+               rtm.tm_mon = tmnow.tm_mon;
+               rtm.tm_mday = tmnow.tm_mday +
+                       (rtm.tm_wday - tmnow.tm_wday + 7) % 7;
+       }
+
+       /*
+        * Given only a month (and no year) find the first matching month
+        * starting with the current month and moving into the future.
+        */
+       if (rtm.tm_mon != TMSENTINEL) {
+               if (rtm.tm_year == TMSENTINEL) {
+                       rtm.tm_year = tmnow.tm_year +
+                               ((rtm.tm_mon < tmnow.tm_mon)? 1 : 0);
+               }
+               if (rtm.tm_mday == TMSENTINEL) {
+                       /* assume the first of the month */
+                       rtm.tm_mday = 1;
+                       /*
+                        * XXX This isn't documented! Just observed behavior.
+                        *
+                        * Given the weekday find the first matching weekday
+                        * starting with the weekday of the first day of the
+                        * the month and moving into the future.
+                        */
+                       if (rtm.tm_wday != TMSENTINEL) {
+                               struct tm tm;
+
+                               memset(&tm, 0, sizeof(struct tm));
+                               tm.tm_year = rtm.tm_year;
+                               tm.tm_mon = rtm.tm_mon;
+                               tm.tm_mday = 1;
+                               mktime(&tm);
+                               rtm.tm_mday +=
+                                       (rtm.tm_wday - tm.tm_wday + 7) % 7;
+                       }
+               }
+       }
+
+       /*
+        * Given no time of day assume the current time of day.
+        */
+       if (rtm.tm_hour == TMSENTINEL &&
+           rtm.tm_min == TMSENTINEL && rtm.tm_sec == TMSENTINEL) {
+               rtm.tm_hour = tmnow.tm_hour;
+               rtm.tm_min = tmnow.tm_min;
+               rtm.tm_sec = tmnow.tm_sec;
+       }
+       /*
+        * Given an hour and no date, find the first matching hour starting
+        * with the current hour and moving into the future
+        */
+       if (rtm.tm_hour != TMSENTINEL &&
+           rtm.tm_year == TMSENTINEL && rtm.tm_mon == TMSENTINEL &&
+           rtm.tm_mday == TMSENTINEL) {
+               rtm.tm_year = tmnow.tm_year;
+               rtm.tm_mon = tmnow.tm_mon;
+               rtm.tm_mday = tmnow.tm_mday;
+               if (rtm.tm_hour < tmnow.tm_hour)
+                       rtm.tm_hour += 24;
+       }
+
+       /*
+        * Set to 'sane' values; mktime(3) does funny things otherwise.
+        * No hours, no minutes, no seconds, no service.
+        */
+       if (rtm.tm_hour == TMSENTINEL)
+               rtm.tm_hour = 0;
+       if (rtm.tm_min == TMSENTINEL)
+               rtm.tm_min = 0;
+       if (rtm.tm_sec == TMSENTINEL)
+               rtm.tm_sec = 0;
+
+       /*
+        * Given only a year the values of month, day of month, day of year,
+        * week day and is daylight (summer) time are unspecified.
+        * (Specified on the Solaris man page not POSIX.)
+        */
+       if (rtm.tm_year != TMSENTINEL &&
+           rtm.tm_mon == TMSENTINEL && rtm.tm_mday == TMSENTINEL) {
+               rtm.tm_mon = 0;
+               rtm.tm_mday = 1;
+               /*
+                * XXX More undocumented functionality but observed.
+                *
+                * Given the weekday find the first matching weekday
+                * starting with the weekday of the first day of the
+                * month and moving into the future.
+                */
+               if (rtm.tm_wday != TMSENTINEL) {
+                       struct tm tm;
+
+                       memset(&tm, 0, sizeof(struct tm));
+                       tm.tm_year = rtm.tm_year;
+                       tm.tm_mon = rtm.tm_mon;
+                       tm.tm_mday = 1;
+                       mktime(&tm);
+                       rtm.tm_mday += (rtm.tm_wday - tm.tm_wday + 7) % 7;
+               }
+       }
+
+       /*
+        * Given only the century but no year within, the current year
+        * is assumed.  (Specified on the Solaris man page not POSIX.)
+        *
+        * Warning ugly end case
+        *
+        * This is more work since strptime(3) doesn't "do the right thing".
+        */
+       if (rtm.tm_year != TMSENTINEL && (rtm.tm_year - 1900) >= 0) {
+               rtm.tm_year -= 1900;
+               rtm.tm_year += (tmnow.tm_year % 100);
+       }
+
+       /*
+        * mktime() will normalize all values and also check that the
+        * value will fit into a time_t.
+        *
+        * This is only for POSIX correctness.  A date >= 1900 is
+        * really ok, but using a time_t limits things.
+        */
+       if (mktime(rtmp) < 0) {
+               getdate_err = 8;
+               return (NULL);
+       }
+
+       return (rtmp);
+}
diff --git a/share/examples/getdate/datemsk.template b/share/examples/getdate/datemsk.template
new file mode 100644 (file)
index 0000000..4f859e1
--- /dev/null
@@ -0,0 +1,38 @@
+# $NetBSD: datemsk.template,v 1.1 2009/05/14 02:37:36 ginsbach Exp $
+# getdate(3) DATEMSK template file
+%m/%d/%y %I:%M:%S %p
+%m/%d/%Y %I:%M:%S %p
+%m/%d/%y %H:%M:%S
+%m/%d/%Y %H:%M:%S
+%m/%d/%y %I:%M %p
+%m/%d/%Y %I:%M %p
+%m/%d/%y %H:%M
+%m/%d/%Y %H:%M
+%m/%d/%y %I %p
+%m/%d/%Y %I %p
+%m/%d/%y %H
+%m/%d/%Y %H
+%m/%d/%y
+%m/%d/%Y
+%m/%d
+%b %d, %Y %I:%M:%S %p
+%b %d, %Y %H:%M:%S
+%B %d, %Y %I:%M:%S %p
+%B %d, %Y %H:%M:%S
+%b %d, %Y %I:%M %p
+%b %d, %Y %H:%M
+%B %d, %Y %I:%M %p
+%B %d, %Y %H:%M
+%b %d, %Y %I %p
+%b %d, %Y %H
+%B %d, %Y %I %p
+%B %d, %Y %H
+%b %d, %Y
+%B %d, %Y
+%b %d
+%B %d
+%m%d%H%M%y
+%m%d%H%M%Y
+%m%d%H%M
+%m%d%H
+%m%d
diff --git a/share/examples/getdate/posixmsk.example3 b/share/examples/getdate/posixmsk.example3
new file mode 100644 (file)
index 0000000..870fee2
--- /dev/null
@@ -0,0 +1,9 @@
+# $NetBSD: posixmsk.example3,v 1.1 2009/05/14 02:37:36 ginsbach Exp $
+#
+# The Open Group Base Specifications Issue 7 / IEEE Std 1003.1-2008
+# Example 3
+#
+%m/%d/%y
+%d.%m.%y
+%y-%m-%d
+%A %H:%M:%S
diff --git a/share/examples/getdate/posixmsk.example4 b/share/examples/getdate/posixmsk.example4
new file mode 100644 (file)
index 0000000..80412c2
--- /dev/null
@@ -0,0 +1,12 @@
+# $NetBSD: posixmsk.example4,v 1.1 2009/05/14 02:37:36 ginsbach Exp $
+#
+# The Open Group Base Specifications Issue 7 / IEEE Std 1003.1-2008
+# Example 4
+#
+%a
+%B
+%b %a
+%b %a %Y
+%a %H
+%b %H:%S
+%H:%M