Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 25 Sep 2014 14:53:19 -0500
From:      Bryan Drewery <bdrewery@FreeBSD.org>
To:        "Pedro F. Giffuni" <pfg@FreeBSD.org>, src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r272122 - head/lib/libc/stdtime
Message-ID:  <542472AF.7020402@FreeBSD.org>
In-Reply-To: <201409251852.s8PIqIRD033822@svn.freebsd.org>
References:  <201409251852.s8PIqIRD033822@svn.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
This is an OpenPGP/MIME signed message (RFC 4880 and 3156)
--8kqUtjJGjGjuu4x8BkdPXcgquw85HWItm
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

On 9/25/2014 1:52 PM, Pedro F. Giffuni wrote:
> Author: pfg
> Date: Thu Sep 25 18:52:17 2014
> New Revision: 272122
> URL: http://svnweb.freebsd.org/changeset/base/272122
>=20
> Log:
>   Add strptime(3) support for %U and %W
>  =20
>   Add support for the missing POSIX-2001 %U and %W features: the
>   existing  FreeBSD strptime code recognizes both directives and
>   validates that the week number lies in the permitted range,
>   but then simply discards the value.
>  =20
>   Initial support for the feature was written by Paul Green with
>   important fixes by Andrey Chernov. Additional support for
>   handling tm_wday/tm_yday was written by David Carlier.
>  =20
>   PR:		137307
>   MFC after:	1 month

Seems Relnotes worthy.

>=20
> Modified:
>   head/lib/libc/stdtime/strptime.c
>=20
> Modified: head/lib/libc/stdtime/strptime.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
> --- head/lib/libc/stdtime/strptime.c	Thu Sep 25 18:43:52 2014	(r272121)=

> +++ head/lib/libc/stdtime/strptime.c	Thu Sep 25 18:52:17 2014	(r272122)=

> @@ -55,10 +55,32 @@ __FBSDID("$FreeBSD$");
>  #include "un-namespace.h"
>  #include "libc_private.h"
>  #include "timelocal.h"
> +#include "tzfile.h"
> =20
>  static char * _strptime(const char *, const char *, struct tm *, int *=
, locale_t);
> =20
> -#define	asizeof(a)	(sizeof (a) / sizeof ((a)[0]))
> +#define	asizeof(a)	(sizeof(a) / sizeof((a)[0]))
> +
> +#define	FLAG_NONE	(1 << 0)
> +#define	FLAG_YEAR	(1 << 1)
> +#define	FLAG_MONTH	(1 << 2)
> +#define	FLAG_YDAY	(1 << 3)
> +#define	FLAG_MDAY	(1 << 4)
> +#define	FLAG_WDAY	(1 << 5)
> +
> +/*
> + * Calculate the week day of the first day of a year. Valid for
> + * the Gregorian calendar, which began Sept 14, 1752 in the UK
> + * and its colonies. Ref:
> + * http://en.wikipedia.org/wiki/Calculating_the_day_of_the_week/
> + */
> +
> +static int
> +first_wday_of(int year)
> +{
> +	return (((2 * (3 - (year / 100) % 4)) + (year % 100) +
> +		((year % 100) / 4) + (isleap(year) ? 6 : 0) + 1) % 7);
> +}
> =20
>  static char *
>  _strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp,
> @@ -66,9 +88,17 @@ _strptime(const char *buf, const char *f
>  {
>  	char	c;
>  	const char *ptr;
> +	int	day_offset =3D -1, wday_offset;
>  	int	i, len;
> +	int flags;
>  	int Ealternative, Oalternative;
> -	struct lc_time_T *tptr =3D __get_current_time_locale(locale);
> +	const struct lc_time_T *tptr =3D __get_current_time_locale(locale);
> +	static int start_of_month[2][13] =3D {
> +		{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
> +		{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
> +	};
> +
> +	flags =3D FLAG_NONE;
> =20
>  	ptr =3D fmt;
>  	while (*ptr !=3D 0) {
> @@ -119,7 +149,9 @@ label:
>  			if (i < 19)
>  				return (NULL);
> =20
> -			tm->tm_year =3D i * 100 - 1900;
> +			tm->tm_year =3D i * 100 - TM_YEAR_BASE;
> +			flags |=3D FLAG_YEAR;
> +
>  			break;
> =20
>  		case 'c':
> @@ -197,6 +229,8 @@ label:
>  				return (NULL);
> =20
>  			tm->tm_yday =3D i - 1;
> +			flags |=3D FLAG_YDAY;
> +
>  			break;
> =20
>  		case 'M':
> @@ -303,7 +337,32 @@ label:
>  				return (NULL);
> =20
>  			tm->tm_wday =3D i;
> +			if (day_offset >=3D 0 && (i - day_offset) !=3D 0) {
> +				tm->tm_yday +=3D i - day_offset;
> +				i =3D 0;
> +				while (tm->tm_yday >=3D
> +					start_of_month[isleap(tm->tm_year +
> +							TM_YEAR_BASE)][i])
> +					i++;
> +				if (i > 12)
> +				{
> +					i =3D 1;
> +					tm->tm_yday -=3D
> +						start_of_month[isleap(tm->tm_year +
> +								TM_YEAR_BASE)]
> +						[12];
> +					tm->tm_year++;
> +				}
> +				tm->tm_mon =3D i - 1;
> +				tm->tm_mday =3D tm->tm_yday -
> +					start_of_month[isleap(tm->tm_year +
> +							TM_YEAR_BASE)]
> +					[i - 1] + 1;
> +			}
>  			buf +=3D len;
> +			flags |=3D FLAG_YEAR | FLAG_MONTH | FLAG_YDAY |
> +				 FLAG_MDAY | FLAG_WDAY;
> +
>  			break;
> =20
>  		case 'U':
> @@ -313,6 +372,8 @@ label:
>  			 * information present in the tm structure at this
>  			 * point to calculate a real value, so just check the
>  			 * range for now.
> +			 * We expect that the year has already been
> +			 * parsed.
>  			 */
>  			if (!isdigit_l((unsigned char)*buf, locale))
>  				return (NULL);
> @@ -327,6 +388,45 @@ label:
>  			if (i > 53)
>  				return (NULL);
> =20
> +			/* Week numbers are l-origin. So that we can always
> +			 * return the date of a Sunday (or Monday), treat week
> +			 * 0 as week 1.
> +			 */
> +
> +			if (i =3D=3D 0)
> +				i =3D 1;
> +
> +			if (c =3D=3D 'U')
> +				day_offset =3D TM_SUNDAY;
> +			else
> +				day_offset =3D TM_MONDAY;
> +
> +			/* Set the date to the first Sunday (or Monday)
> +			 * of the specified week of the year.
> +			 */
> +
> +			tm->tm_yday =3D (7 - first_wday_of(tm->tm_year +
> +				TM_YEAR_BASE) + day_offset) % 7 + (i - 1) * 7;
> +			i =3D 0;
> +			while (tm->tm_yday >=3D
> +				start_of_month[isleap(tm->tm_year + TM_YEAR_BASE)][i])
> +				i++;
> +			if (i > 12)
> +			{
> +				i =3D 1;
> +				tm->tm_yday -=3D
> +					start_of_month[isleap(tm->tm_year +
> +							TM_YEAR_BASE)][12];
> +				tm->tm_year++;
> +			}
> +			tm->tm_mon =3D i - 1;
> +			tm->tm_mday =3D tm->tm_yday -
> +				start_of_month[isleap(tm->tm_year + TM_YEAR_BASE)]
> +				[i - 1] + 1;
> +			tm->tm_wday =3D day_offset;
> +			flags |=3D FLAG_YEAR | FLAG_MONTH | FLAG_YDAY |
> +				 FLAG_MDAY | FLAG_WDAY;
> +
>  			break;
> =20
>  		case 'w':
> @@ -338,6 +438,7 @@ label:
>  				return (NULL);
> =20
>  			tm->tm_wday =3D i;
> +			flags !=3D FLAG_WDAY;
> =20
>  			break;
> =20
> @@ -374,6 +475,7 @@ label:
>  				return (NULL);
> =20
>  			tm->tm_mday =3D i;
> +			flags |=3D FLAG_MDAY;
> =20
>  			break;
> =20
> @@ -413,6 +515,8 @@ label:
> =20
>  			tm->tm_mon =3D i;
>  			buf +=3D len;
> +			flags |=3D FLAG_MONTH;
> +
>  			break;
> =20
>  		case 'm':
> @@ -430,6 +534,7 @@ label:
>  				return (NULL);
> =20
>  			tm->tm_mon =3D i - 1;
> +			flags |=3D FLAG_MONTH;
> =20
>  			break;
> =20
> @@ -471,13 +576,14 @@ label:
>  				len--;
>  			}
>  			if (c =3D=3D 'Y')
> -				i -=3D 1900;
> +				i -=3D TM_YEAR_BASE;
>  			if (c =3D=3D 'y' && i < 69)
>  				i +=3D 100;
>  			if (i < 0)
>  				return (NULL);
> =20
>  			tm->tm_year =3D i;
> +			flags |=3D FLAG_YEAR;
> =20
>  			break;
> =20
> @@ -543,10 +649,25 @@ label:
>  			break;
>  		}
>  	}
> +
> +	if (flags & (FLAG_YEAR | FLAG_MONTH)) {
> +		if (!tm->tm_yday && (flags & FLAG_MDAY))
> +			tm->tm_yday =3D start_of_month[isleap(tm->tm_year
> +				+ TM_YEAR_BASE)][tm->tm_mon] + (tm->tm_mday - 1);
> +		if (!tm->tm_wday) {
> +			i =3D 0;
> +			wday_offset =3D first_wday_of(tm->tm_year);
> +			while (i++ <=3D tm->tm_yday)
> +				if (wday_offset++ >=3D 6)
> +					wday_offset =3D 0;
> +
> +			tm->tm_wday =3D wday_offset;
> +		}
> +	}
> +
>  	return ((char *)buf);
>  }
> =20
> -
>  char *
>  strptime_l(const char * __restrict buf, const char * __restrict fmt,
>      struct tm * __restrict tm, locale_t loc)
>=20


--=20
Regards,
Bryan Drewery


--8kqUtjJGjGjuu4x8BkdPXcgquw85HWItm
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)

iQEcBAEBAgAGBQJUJHKvAAoJEDXXcbtuRpfPksoH/0JL4qt5Hwwmn+P3bT3MsLfo
GqvUAzNmie1oBHl0hC8VrCBi5WBmep0YwWbLkdG1j6FK57zpa0H2cS/Eyx2Aj27C
GYxLDdwW8pGrOMGFL2RV3gQtzFgyKzdo0pgkR6kuTvyX8qNrrerXOtuse0IP9+cK
l90sJfrmNnJVv5537nAwYng6RsMGdglH/gh8HZMbjde66X9sUt79YIVaQs1GkkEb
f55QeKHgnFuqhhZLSX7QUD1o+gJDV/DqvHIl8IbmLgJYZgVir2Sc6ql5MKNmpCFl
A6mx0LjbVIFttHOZEGyQyJ59R29qBh4g/Lw7WuncUw41I6ynv3w2rxvQPP9khVo=
=SRWK
-----END PGP SIGNATURE-----

--8kqUtjJGjGjuu4x8BkdPXcgquw85HWItm--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?542472AF.7020402>