diff --git a/ext/POSIX/lib/POSIX.pod b/ext/POSIX/lib/POSIX.pod index 696ef8a80a..ae6a02ea83 100644 --- a/ext/POSIX/lib/POSIX.pod +++ b/ext/POSIX/lib/POSIX.pod @@ -1866,49 +1866,17 @@ Identical to the string form of C<$!>, see L. =item C Convert date and time information to string based on the current -underlying locale of the program (except for any daylight savings time). -Returns the string. +underlying locale of the program. +Returns the string in a mortalized SV; set to an empty string on error. -Synopsis: - - strftime(fmt, sec, min, hour, mday, mon, year, - wday = -1, yday = -1, isdst = 0) - -The month (C) begins at zero, -I, January is 0, not 1. The -year (C) is given in years since 1900, I, the year 1995 is 95; the -year 2001 is 101. Consult your system's C manpage for details -about these and the other arguments. + my $sv = strftime(fmt, sec, min, hour, mday, mon, year, + wday = -1, yday = -1, isdst = -1) The C and C parameters are both ignored. Their values are always determinable from the other parameters. -C should be C<1> or C<0>, depending on whether or not daylight -savings time is in effect for the given time or not. - -If you want your code to be portable, your format (C) argument -should use only the conversion specifiers defined by the ANSI C -standard (C99, to play safe). These are C. -But even then, the B of some of the conversion specifiers are -non-portable. For example, the specifiers C change according -to the locale settings of the user, and both how to set locales (the -locale names) and what output to expect are non-standard. -The specifier C changes according to the timezone settings of the -user and the timezone computation rules of the operating system. -The C specifier is notoriously unportable since the names of -timezones are non-standard. Sticking to the numeric specifiers is the -safest route. - -The arguments, except for C, are made consistent as though by -calling C before calling your system's C function. -To get correct results, you must set C to be the proper value. -When omitted, the function assumes daylight savings is not in effect. - -The string for Tuesday, December 12, 1995 in the C locale. - - $str = POSIX::strftime( "%A, %B %d, %Y", - 0, 0, 0, 12, 11, 95, 2 ); - print "$str\n"; +More details on the behavior and the specification of the other +parameters are described in L. =item C diff --git a/locale.c b/locale.c index e1af38e0a3..f1f4d34519 100644 --- a/locale.c +++ b/locale.c @@ -8154,11 +8154,12 @@ S_maybe_override_codeset(pTHX_ const char * codeset, /* =for apidoc_section $time -=for apidoc sv_strftime_tm -=for apidoc_item sv_strftime_ints +=for apidoc sv_strftime_ints +=for apidoc_item sv_strftime_tm =for apidoc_item my_strftime -These implement the libc strftime(). +These implement libc strftime(), overcoming various deficiencies it has; you +will come to regret sooner or later using it directly instead of these. On failure, they return NULL, and set C to C. @@ -8167,70 +8168,154 @@ handle the UTF-8ness of the current locale, the input C, and the returned result. Only if the current C locale is a UTF-8 one (and S> is not in effect) will the result be marked as UTF-8. +For these, the caller assumes ownership of the returned SV with a reference +count of 1. + C is kept for backwards compatibility. Knowing if its result should be considered UTF-8 or not requires significant extra logic. Note that all three functions are always executed in the underlying C locale of the program, giving results based on that locale. +The stringified C parameter in all is the same as the system libc +C. The available conversion specifications vary by platform. These +days, every specification listed in the ANSI C99 standard should be usable +everywhere. These are C. + +But note that the B of some of the conversion specifiers are +non-portable. For example, the specifiers C change according +to the locale settings of the user, and both how to set locales (the +locale names) and what output to expect are not standardized. +The specifier C changes according to the timezone settings of the +user and the timezone computation rules of the operating system. +The C specifier is notoriously unportable since the names of +timezones are not standardized. Sticking to the numeric specifiers is the +safest route. + +At the time of this writing, for example, C<%s> is not available on +Windows-like systems. + The functions differ as follows: -C takes a pointer to a filled-in S> parameter. It -ignores the values of the C and C fields in it. The other fields -give enough information to accurately calculate these values, and are used for -that purpose. - -The caller assumes ownership of the returned SV with a reference count of 1. - -C takes a bunch of integer parameters that together -completely define a given time. It calculates the S> to pass to -libc strftime(), and calls that function. - -The value of C is used as follows: - =over -=item 0 +=item * -No daylight savings time is in effect - -=item E0 - -Check if daylight savings time is in effect, and adjust the results -accordingly. - -=item E0 - -This value is reserved for internal use by the L module for backwards -compatibility purposes. - -=back - -The caller assumes ownership of the returned SV with a reference count of 1. - -C is like C except that: - -=over - -=item The C parameter and the return are S> instead of -S>. - -This means the UTF-8ness of the result is unspecified. The result MUST be +The C parameter and the return from C are S> +instead of the S> in the other two functions. This means the +UTF-8ness of the format and result are unspecified. The result MUST be arranged to be FREED BY THE CALLER). -=item The C parameter is ignored. +=item * -Daylight savings time is never considered to be in effect. +C and C take a bunch of integer parameters that +together completely define a given time. They calculate the S> +to pass to libc strftime(), and call that function. See below for the meaning +of the parameters. -=item It has extra parameters C and C that are ignored. +C takes a pointer to an already filled-in S> +parameter, so avoids that calculation. -These exist only for historical reasons; the values for the corresponding -fields in S> are calculated from the other arguments. +=item * + +C takes two extra parameters that are ignored, being kept only +for historical reasons. These are C and C. =back -Note that all three functions are always executed in the underlying C -locale of the program, giving results based on that locale. +The C99 Standard calls for S> to contain at least these fields: + + int tm_sec; // seconds after the minute — [0, 60] + int tm_min; // minutes after the hour — [0, 59] + int tm_hour; // hours since midnight — [0, 23] + int tm_mday; // day of the month — [1, 31] + int tm_mon; // months since January — [0, 11] + int tm_year; // years since 1900 + int tm_wday; // days since Sunday — [0, 6] + int tm_yday; // days since January 1 — [0, 365] + int tm_isdst; // Daylight Saving Time flag + +C and C are output only; the other fields give enough +information to accurately calculate these, and are internally used for that +purpose. + +The numbers enclosed in the square brackets above give the maximum legal +ranges for values in the corresponding field. Those ranges are restricted for +some inputs. For example, not all months have 31 days, but all hours have 60 +minutes. If you set a number that is outside the corresponding range, perl +and the libc functions will automatically normalize it to be inside the range, +adjusting other values as necessary. For example, specifying February 29, is +the same as saying March 1 for non-leap years; and using a minute value of 60 +will instead change that to a 0, and increment the hour, which in turn, if the +hour was 23, will roll it over to 0 it and increment the day, and so on. + +Each parameter to C and C populates the +similarly-named field in this structure. + +A value of 60 is legal for C, but only for those moments when an +official leap second has been declared. It is undefined behavior to use them +otherwise, and the behavior does vary depending on the implementation. +Some implementations take your word for it that this is a leap second, leaving +it as the 61st second of the given minute; some roll it over to be the 0th +second of the following minute; some treat it as 0. Some non-conforming +implementations always roll it over to the next minute, regardless of whether +an actual leap second is occurring or not. (And yes, it is a real problem +that different computers have a different conception of what the current time +is; you can search the internet for details.) + +There is no limit (outside the size of C) for the value of C, +but sufficiently negative values (for earlier than 1900) may have different +results on different systems and locales. Some libc implementations may know +when a given locale adopted the Greorian calendar, and adjust for that. +Others will not. (And some countries didn't adopt the Gregorian calendar +until after 1900.) Probably all implementations assume modern time zones go +back forever, before they were actually invented, starting in the last half of +the 19th century. + +The treatment of the C field has varied over previous Perl versions, +and has been buggy (both by perl and by some libc implementations), but is now +aligned, as best we can, with the POSIX Standard, as follows: + +=over + +=item C is 0 + +The function is to assume that daylight savings time is not in effect. This +should now always work properly, as perl uses its own implementation in this +case, avoiding non-conforming libc ones. + +=item C is E0 + +The function is to assume that daylight savings time is in effect, though some +underlying libc implementations treat this as a hint instead of a mandate. + +=item C is E0 + +The function is to itself try to calculate if daylight savings time is in +effect. More recent libc implementations are better at this than earlier +ones. + +=back + +Some libc implementations have extra fields in S>. The two that +perl handles are: + + int tm_gmtoff; // Seconds East of UTC [%z] + const char * tm_zone; // Timezone abbreviation [%Z] + +These are both output only. Using the respective conversion specifications +(enclosed in the square brackets) in the C parameter is a portable way to +gain access to these values, working both on systems that have and don't have +these fields. + +Example, in the C locale: + + my_strftime( "%A, %B %d, %Y", 0, 0, 0, 12, 11, 95, 0, 0, -1 ); + +returns + + "Tuesday, December 12, 1995" + =cut */