The rest of tzcode94g from Arthur David Olson.
Obtained From: Arthur David Olson, ftp://elsie.nci.nih.gov/pub/tzcode94g.tar.gz
This commit is contained in:
parent
233ca9a9cf
commit
48d96b1761
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/tzcode/dist/; revision=2708
56
lib/libc/stdtime/asctime.c
Normal file
56
lib/libc/stdtime/asctime.c
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char elsieid[] = "@(#)asctime.c 7.5";
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
||||
/*LINTLIBRARY*/
|
||||
|
||||
#include "private.h"
|
||||
#include "tzfile.h"
|
||||
|
||||
/*
|
||||
** A la X3J11, with core dump avoidance.
|
||||
*/
|
||||
|
||||
char *
|
||||
asctime(timeptr)
|
||||
register const struct tm * timeptr;
|
||||
{
|
||||
static const char wday_name[][3] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
};
|
||||
static const char mon_name[][3] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
/*
|
||||
** Big enough for something such as
|
||||
** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n
|
||||
** (two three-character abbreviations, five strings denoting integers,
|
||||
** three explicit spaces, two explicit colons, a newline,
|
||||
** and a trailing ASCII nul).
|
||||
*/
|
||||
static char result[3 * 2 + 5 * INT_STRLEN_MAXIMUM(int) +
|
||||
3 + 2 + 1 + 1];
|
||||
register const char * wn;
|
||||
register const char * mn;
|
||||
|
||||
if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
|
||||
wn = "???";
|
||||
else wn = wday_name[timeptr->tm_wday];
|
||||
if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)
|
||||
mn = "???";
|
||||
else mn = mon_name[timeptr->tm_mon];
|
||||
/*
|
||||
** The X3J11-suggested format is
|
||||
** "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n"
|
||||
** Since the .2 in 02.2d is ignored, we drop it.
|
||||
*/
|
||||
(void) sprintf(result, "%.3s %.3s%3d %02d:%02d:%02d %d\n",
|
||||
wn, mn,
|
||||
timeptr->tm_mday, timeptr->tm_hour,
|
||||
timeptr->tm_min, timeptr->tm_sec,
|
||||
TM_YEAR_BASE + timeptr->tm_year);
|
||||
return result;
|
||||
}
|
74
lib/libc/stdtime/difftime.c
Normal file
74
lib/libc/stdtime/difftime.c
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char elsieid[] = "@(#)difftime.c 7.4";
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
||||
/*LINTLIBRARY*/
|
||||
|
||||
#include "private.h"
|
||||
|
||||
/*
|
||||
** Algorithm courtesy Paul Eggert (eggert@twinsun.com).
|
||||
*/
|
||||
|
||||
#ifdef HAVE_LONG_DOUBLE
|
||||
#define long_double long double
|
||||
#endif /* defined HAVE_LONG_DOUBLE */
|
||||
#ifndef HAVE_LONG_DOUBLE
|
||||
#define long_double double
|
||||
#endif /* !defined HAVE_LONG_DOUBLE */
|
||||
|
||||
double
|
||||
difftime(time1, time0)
|
||||
const time_t time1;
|
||||
const time_t time0;
|
||||
{
|
||||
time_t delta;
|
||||
time_t hibit;
|
||||
|
||||
if (sizeof(time_t) < sizeof(double))
|
||||
return (double) time1 - (double) time0;
|
||||
if (sizeof(time_t) < sizeof(long_double))
|
||||
return (long_double) time1 - (long_double) time0;
|
||||
if (time1 < time0)
|
||||
return -difftime(time0, time1);
|
||||
/*
|
||||
** As much as possible, avoid loss of precision
|
||||
** by computing the difference before converting to double.
|
||||
*/
|
||||
delta = time1 - time0;
|
||||
if (delta >= 0)
|
||||
return delta;
|
||||
/*
|
||||
** Repair delta overflow.
|
||||
*/
|
||||
hibit = 1;
|
||||
while ((hibit <<= 1) > 0)
|
||||
continue;
|
||||
/*
|
||||
** The following expression rounds twice, which means
|
||||
** the result may not be the closest to the true answer.
|
||||
** For example, suppose time_t is 64-bit signed int,
|
||||
** long_double is IEEE 754 double with default rounding,
|
||||
** time1 = 9223372036854775807 and time0 = -1536.
|
||||
** Then the true difference is 9223372036854777343,
|
||||
** which rounds to 9223372036854777856
|
||||
** with a total error of 513.
|
||||
** But delta overflows to -9223372036854774273,
|
||||
** which rounds to -9223372036854774784, and correcting
|
||||
** this by subtracting 2 * (long_double) hibit
|
||||
** (i.e. by adding 2**64 = 18446744073709551616)
|
||||
** yields 9223372036854776832, which
|
||||
** rounds to 9223372036854775808
|
||||
** with a total error of 1535 instead.
|
||||
** This problem occurs only with very large differences.
|
||||
** It's too painful to fix this portably.
|
||||
** We are not alone in this problem;
|
||||
** many C compilers round twice when converting
|
||||
** large unsigned types to small floating types,
|
||||
** so if time_t is unsigned the "return delta" above
|
||||
** has the same double-rounding problem.
|
||||
*/
|
||||
return delta - 2 * (long_double) hibit;
|
||||
}
|
1530
lib/libc/stdtime/localtime.c
Normal file
1530
lib/libc/stdtime/localtime.c
Normal file
File diff suppressed because it is too large
Load Diff
1530
lib/libc/stdtime/localtime.c.ORIG
Normal file
1530
lib/libc/stdtime/localtime.c.ORIG
Normal file
File diff suppressed because it is too large
Load Diff
185
lib/libc/stdtime/private.h
Normal file
185
lib/libc/stdtime/private.h
Normal file
@ -0,0 +1,185 @@
|
||||
#ifndef PRIVATE_H
|
||||
|
||||
#define PRIVATE_H
|
||||
|
||||
/*
|
||||
** This header is for use ONLY with the time conversion code.
|
||||
** There is no guarantee that it will remain unchanged,
|
||||
** or that it will remain at all.
|
||||
** Do NOT copy it to any system include directory.
|
||||
** Thank you!
|
||||
*/
|
||||
|
||||
/*
|
||||
** ID
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char privatehid[] = "@(#)private.h 7.5";
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
||||
/*
|
||||
** const
|
||||
*/
|
||||
|
||||
#ifndef const
|
||||
#ifndef __STDC__
|
||||
#define const
|
||||
#endif /* !defined __STDC__ */
|
||||
#endif /* !defined const */
|
||||
|
||||
/*
|
||||
** void
|
||||
*/
|
||||
|
||||
#ifndef void
|
||||
#ifndef __STDC__
|
||||
#ifndef vax
|
||||
#ifndef sun
|
||||
#define void char
|
||||
#endif /* !defined sun */
|
||||
#endif /* !defined vax */
|
||||
#endif /* !defined __STDC__ */
|
||||
#endif /* !defined void */
|
||||
|
||||
/*
|
||||
** P((args))
|
||||
*/
|
||||
|
||||
#ifndef P
|
||||
#ifdef __STDC__
|
||||
#define P(x) x
|
||||
#endif /* defined __STDC__ */
|
||||
#ifndef __STDC__
|
||||
#define ASTERISK *
|
||||
#define P(x) ( /ASTERISK x ASTERISK/ )
|
||||
#endif /* !defined __STDC__ */
|
||||
#endif /* !defined P */
|
||||
|
||||
/*
|
||||
** genericptr_t
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
typedef void * genericptr_t;
|
||||
#endif /* defined __STDC__ */
|
||||
#ifndef __STDC__
|
||||
typedef char * genericptr_t;
|
||||
#endif /* !defined __STDC__ */
|
||||
|
||||
#include "sys/types.h" /* for time_t */
|
||||
#include "stdio.h"
|
||||
#include "ctype.h"
|
||||
#include "errno.h"
|
||||
#include "string.h"
|
||||
#include "limits.h" /* for CHAR_BIT */
|
||||
#ifndef _TIME_
|
||||
#include "time.h"
|
||||
#endif /* !defined _TIME_ */
|
||||
|
||||
#ifndef remove
|
||||
extern int unlink P((const char * filename));
|
||||
#define remove unlink
|
||||
#endif /* !defined remove */
|
||||
|
||||
#ifndef FILENAME_MAX
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
#ifdef unix
|
||||
#include "sys/param.h"
|
||||
#endif /* defined unix */
|
||||
#endif /* !defined MAXPATHLEN */
|
||||
|
||||
#ifdef MAXPATHLEN
|
||||
#define FILENAME_MAX MAXPATHLEN
|
||||
#endif /* defined MAXPATHLEN */
|
||||
#ifndef MAXPATHLEN
|
||||
#define FILENAME_MAX 1024 /* Pure guesswork */
|
||||
#endif /* !defined MAXPATHLEN */
|
||||
|
||||
#endif /* !defined FILENAME_MAX */
|
||||
|
||||
#ifndef EXIT_SUCCESS
|
||||
#define EXIT_SUCCESS 0
|
||||
#endif /* !defined EXIT_SUCCESS */
|
||||
|
||||
#ifndef EXIT_FAILURE
|
||||
#define EXIT_FAILURE 1
|
||||
#endif /* !defined EXIT_FAILURE */
|
||||
|
||||
#ifdef __STDC__
|
||||
|
||||
#define alloc_size_t size_t
|
||||
#define qsort_size_t size_t
|
||||
#define fwrite_size_t size_t
|
||||
|
||||
#endif /* defined __STDC__ */
|
||||
#ifndef __STDC__
|
||||
|
||||
#ifndef alloc_size_t
|
||||
#define alloc_size_t unsigned
|
||||
#endif /* !defined alloc_size_t */
|
||||
|
||||
#ifndef qsort_size_t
|
||||
#ifdef USG
|
||||
#define qsort_size_t unsigned
|
||||
#endif /* defined USG */
|
||||
#ifndef USG
|
||||
#define qsort_size_t int
|
||||
#endif /* !defined USG */
|
||||
#endif /* !defined qsort_size_t */
|
||||
|
||||
#ifndef fwrite_size_t
|
||||
#define fwrite_size_t int
|
||||
#endif /* !defined fwrite_size_t */
|
||||
|
||||
#ifndef USG
|
||||
extern char * sprintf P((char * buf, const char * format, ...));
|
||||
#endif /* !defined USG */
|
||||
|
||||
#endif /* !defined __STDC__ */
|
||||
|
||||
/*
|
||||
** Ensure that these are declared--redundantly declaring them shouldn't hurt.
|
||||
*/
|
||||
|
||||
extern char * getenv P((const char * name));
|
||||
extern genericptr_t malloc P((alloc_size_t size));
|
||||
extern genericptr_t calloc P((alloc_size_t nelem, alloc_size_t elsize));
|
||||
extern genericptr_t realloc P((genericptr_t oldptr, alloc_size_t newsize));
|
||||
|
||||
#ifdef USG
|
||||
extern void exit P((int s));
|
||||
extern void qsort P((genericptr_t base, qsort_size_t nelem,
|
||||
qsort_size_t elsize, int (*comp)()));
|
||||
extern void perror P((const char * string));
|
||||
extern void free P((char * buf));
|
||||
#endif /* defined USG */
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif /* !defined TRUE */
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif /* !defined FALSE */
|
||||
|
||||
#ifndef INT_STRLEN_MAXIMUM
|
||||
/*
|
||||
** 302 / 1000 is log10(2.0) rounded up.
|
||||
** Subtract one for the sign bit;
|
||||
** add one for integer division truncation;
|
||||
** add one more for a minus sign.
|
||||
*/
|
||||
#define INT_STRLEN_MAXIMUM(type) \
|
||||
((sizeof(type) * CHAR_BIT - 1) * 302 / 1000 + 2)
|
||||
#endif /* !defined INT_STRLEN_MAXIMUM */
|
||||
|
||||
/*
|
||||
** UNIX is a registered trademark of AT&T.
|
||||
** VAX is a trademark of Digital Equipment Corporation.
|
||||
*/
|
||||
|
||||
#endif /* !defined PRIVATE_H */
|
393
lib/libc/stdtime/strftime.c
Normal file
393
lib/libc/stdtime/strftime.c
Normal file
@ -0,0 +1,393 @@
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char elsieid[] = "@(#)strftime.c 7.19";
|
||||
/*
|
||||
** Based on the UCB version with the ID appearing below.
|
||||
** This is ANSIish only when time is treated identically in all locales and
|
||||
** when "multibyte character == plain character".
|
||||
*/
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
||||
#include "private.h"
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef LIBC_SCCS
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
|
||||
#endif /* !defined lint */
|
||||
#endif /* !defined LIBC_SCCS */
|
||||
|
||||
#include "tzfile.h"
|
||||
|
||||
static const char afmt[][4] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
};
|
||||
static const char Afmt[][10] = {
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
|
||||
"Saturday"
|
||||
};
|
||||
static const char bfmt[][4] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
|
||||
"Oct", "Nov", "Dec"
|
||||
};
|
||||
static const char Bfmt[][10] = {
|
||||
"January", "February", "March", "April", "May", "June", "July",
|
||||
"August", "September", "October", "November", "December"
|
||||
};
|
||||
|
||||
static char *_add P((const char *, char *, const char *));
|
||||
static char *_conv P((int, const char *, char *, const char *));
|
||||
static char *_fmt P((const char *, const struct tm *, char *, const char *));
|
||||
|
||||
size_t strftime P((char *, size_t, const char *, const struct tm *));
|
||||
|
||||
extern char *tzname[];
|
||||
|
||||
size_t
|
||||
strftime(s, maxsize, format, t)
|
||||
char *s;
|
||||
size_t maxsize;
|
||||
const char *format;
|
||||
const struct tm *t;
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = _fmt(format, t, s, s + maxsize);
|
||||
if (p == s + maxsize)
|
||||
return 0;
|
||||
*p = '\0';
|
||||
return p - s;
|
||||
}
|
||||
|
||||
static char *
|
||||
_fmt(format, t, pt, ptlim)
|
||||
const char *format;
|
||||
const struct tm *t;
|
||||
char *pt;
|
||||
const char *ptlim;
|
||||
{
|
||||
for (; *format; ++format) {
|
||||
if (*format == '%') {
|
||||
label:
|
||||
switch(*++format) {
|
||||
case '\0':
|
||||
--format;
|
||||
break;
|
||||
case 'A':
|
||||
pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ?
|
||||
"?" : Afmt[t->tm_wday], pt, ptlim);
|
||||
continue;
|
||||
case 'a':
|
||||
pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ?
|
||||
"?" : afmt[t->tm_wday], pt, ptlim);
|
||||
continue;
|
||||
case 'B':
|
||||
pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ?
|
||||
"?" : Bfmt[t->tm_mon], pt, ptlim);
|
||||
continue;
|
||||
case 'b':
|
||||
case 'h':
|
||||
pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ?
|
||||
"?" : bfmt[t->tm_mon], pt, ptlim);
|
||||
continue;
|
||||
case 'c':
|
||||
pt = _fmt("%D %X", t, pt, ptlim);
|
||||
continue;
|
||||
case 'C':
|
||||
/*
|
||||
** %C used to do a...
|
||||
** _fmt("%a %b %e %X %Y", t);
|
||||
** ...whereas now POSIX 1003.2 calls for
|
||||
** something completely different.
|
||||
** (ado, 5/24/93)
|
||||
*/
|
||||
pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,
|
||||
"%02d", pt, ptlim);
|
||||
continue;
|
||||
case 'D':
|
||||
pt = _fmt("%m/%d/%y", t, pt, ptlim);
|
||||
continue;
|
||||
case 'x':
|
||||
/*
|
||||
** Version 3.0 of strftime from Arnold Robbins
|
||||
** (arnold@skeeve.atl.ga.us) does the
|
||||
** equivalent of...
|
||||
** _fmt("%a %b %e %Y");
|
||||
** ...for %x; since the X3J11 C language
|
||||
** standard calls for "date, using locale's
|
||||
** date format," anything goes. Using just
|
||||
** numbers (as here) makes Quakers happier.
|
||||
** Word from Paul Eggert (eggert@twinsun.com)
|
||||
** is that %Y-%m-%d is the ISO standard date
|
||||
** format, specified in ISO 2014 and later
|
||||
** ISO 8601:1988, with a summary available in
|
||||
** pub/doc/ISO/english/ISO8601.ps.Z on
|
||||
** ftp.uni-erlangen.de.
|
||||
** (ado, 5/30/93)
|
||||
*/
|
||||
pt = _fmt("%m/%d/%y", t, pt, ptlim);
|
||||
continue;
|
||||
case 'd':
|
||||
pt = _conv(t->tm_mday, "%02d", pt, ptlim);
|
||||
continue;
|
||||
case 'E':
|
||||
case 'O':
|
||||
/*
|
||||
** POSIX locale extensions, a la
|
||||
** Arnold Robbins' strftime version 3.0.
|
||||
** The sequences
|
||||
** %Ec %EC %Ex %Ey %EY
|
||||
** %Od %oe %OH %OI %Om %OM
|
||||
** %OS %Ou %OU %OV %Ow %OW %Oy
|
||||
** are supposed to provide alternate
|
||||
** representations.
|
||||
** (ado, 5/24/93)
|
||||
*/
|
||||
goto label;
|
||||
case 'e':
|
||||
pt = _conv(t->tm_mday, "%2d", pt, ptlim);
|
||||
continue;
|
||||
case 'H':
|
||||
pt = _conv(t->tm_hour, "%02d", pt, ptlim);
|
||||
continue;
|
||||
case 'I':
|
||||
pt = _conv((t->tm_hour % 12) ?
|
||||
(t->tm_hour % 12) : 12,
|
||||
"%02d", pt, ptlim);
|
||||
continue;
|
||||
case 'j':
|
||||
pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);
|
||||
continue;
|
||||
case 'k':
|
||||
/*
|
||||
** This used to be...
|
||||
** _conv(t->tm_hour % 12 ?
|
||||
** t->tm_hour % 12 : 12, 2, ' ');
|
||||
** ...and has been changed to the below to
|
||||
** match SunOS 4.1.1 and Arnold Robbins'
|
||||
** strftime version 3.0. That is, "%k" and
|
||||
** "%l" have been swapped.
|
||||
** (ado, 5/24/93)
|
||||
*/
|
||||
pt = _conv(t->tm_hour, "%2d", pt, ptlim);
|
||||
continue;
|
||||
#ifdef KITCHEN_SINK
|
||||
case 'K':
|
||||
/*
|
||||
** After all this time, still unclaimed!
|
||||
*/
|
||||
pt = _add("kitchen sink", pt, ptlim);
|
||||
continue;
|
||||
#endif /* defined KITCHEN_SINK */
|
||||
case 'l':
|
||||
/*
|
||||
** This used to be...
|
||||
** _conv(t->tm_hour, 2, ' ');
|
||||
** ...and has been changed to the below to
|
||||
** match SunOS 4.1.1 and Arnold Robbin's
|
||||
** strftime version 3.0. That is, "%k" and
|
||||
** "%l" have been swapped.
|
||||
** (ado, 5/24/93)
|
||||
*/
|
||||
pt = _conv((t->tm_hour % 12) ?
|
||||
(t->tm_hour % 12) : 12,
|
||||
"%2d", pt, ptlim);
|
||||
continue;
|
||||
case 'M':
|
||||
pt = _conv(t->tm_min, "%02d", pt, ptlim);
|
||||
continue;
|
||||
case 'm':
|
||||
pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);
|
||||
continue;
|
||||
case 'n':
|
||||
pt = _add("\n", pt, ptlim);
|
||||
continue;
|
||||
case 'p':
|
||||
pt = _add(t->tm_hour >= 12 ? "PM" : "AM",
|
||||
pt, ptlim);
|
||||
continue;
|
||||
case 'R':
|
||||
pt = _fmt("%H:%M", t, pt, ptlim);
|
||||
continue;
|
||||
case 'r':
|
||||
pt = _fmt("%I:%M:%S %p", t, pt, ptlim);
|
||||
continue;
|
||||
case 'S':
|
||||
pt = _conv(t->tm_sec, "%02d", pt, ptlim);
|
||||
continue;
|
||||
case 'T':
|
||||
case 'X':
|
||||
pt = _fmt("%H:%M:%S", t, pt, ptlim);
|
||||
continue;
|
||||
case 't':
|
||||
pt = _add("\t", pt, ptlim);
|
||||
continue;
|
||||
case 'U':
|
||||
pt = _conv((t->tm_yday + 7 - t->tm_wday) / 7,
|
||||
"%02d", pt, ptlim);
|
||||
continue;
|
||||
case 'u':
|
||||
/*
|
||||
** From Arnold Robbins' strftime version 3.0:
|
||||
** "ISO 8601: Weekday as a decimal number
|
||||
** [1 (Monday) - 7]"
|
||||
** (ado, 5/24/93)
|
||||
*/
|
||||
pt = _conv((t->tm_wday == 0) ? 7 : t->tm_wday,
|
||||
"%d", pt, ptlim);
|
||||
continue;
|
||||
case 'V':
|
||||
/*
|
||||
** From Arnold Robbins' strftime version 3.0:
|
||||
** "the week number of the year (the first
|
||||
** Monday as the first day of week 1) as a
|
||||
** decimal number (01-53). The method for
|
||||
** determining the week number is as specified
|
||||
** by ISO 8601 (to wit: if the week containing
|
||||
** January 1 has four or more days in the new
|
||||
** year, then it is week 1, otherwise it is
|
||||
** week 53 of the previous year and the next
|
||||
** week is week 1)."
|
||||
** (ado, 5/24/93)
|
||||
*/
|
||||
/*
|
||||
** XXX--If January 1 falls on a Friday,
|
||||
** January 1-3 are part of week 53 of the
|
||||
** previous year. By analogy, if January
|
||||
** 1 falls on a Thursday, are December 29-31
|
||||
** of the PREVIOUS year part of week 1???
|
||||
** (ado 5/24/93)
|
||||
**
|
||||
** You are understood not to expect this.
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
|
||||
i = (t->tm_yday + 10 - (t->tm_wday ?
|
||||
(t->tm_wday - 1) : 6)) / 7;
|
||||
if (i == 0) {
|
||||
/*
|
||||
** What day of the week does
|
||||
** January 1 fall on?
|
||||
*/
|
||||
i = t->tm_wday -
|
||||
(t->tm_yday - 1);
|
||||
/*
|
||||
** Fri Jan 1: 53
|
||||
** Sun Jan 1: 52
|
||||
** Sat Jan 1: 53 if previous
|
||||
** year a leap
|
||||
** year, else 52
|
||||
*/
|
||||
if (i == TM_FRIDAY)
|
||||
i = 53;
|
||||
else if (i == TM_SUNDAY)
|
||||
i = 52;
|
||||
else i = isleap(t->tm_year +
|
||||
TM_YEAR_BASE) ?
|
||||
53 : 52;
|
||||
#ifdef XPG4_1994_04_09
|
||||
/*
|
||||
** As of 4/9/94, though,
|
||||
** XPG4 calls for 53
|
||||
** unconditionally.
|
||||
*/
|
||||
i = 53;
|
||||
#endif /* defined XPG4_1994_04_09 */
|
||||
}
|
||||
pt = _conv(i, "%02d", pt, ptlim);
|
||||
}
|
||||
continue;
|
||||
case 'v':
|
||||
/*
|
||||
** From Arnold Robbins' strftime version 3.0:
|
||||
** "date as dd-bbb-YYYY"
|
||||
** (ado, 5/24/93)
|
||||
*/
|
||||
pt = _fmt("%e-%b-%Y", t, pt, ptlim);
|
||||
continue;
|
||||
case 'W':
|
||||
pt = _conv((t->tm_yday + 7 -
|
||||
(t->tm_wday ?
|
||||
(t->tm_wday - 1) : 6)) / 7,
|
||||
"%02d", pt, ptlim);
|
||||
continue;
|
||||
case 'w':
|
||||
pt = _conv(t->tm_wday, "%d", pt, ptlim);
|
||||
continue;
|
||||
case 'y':
|
||||
pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
|
||||
"%02d", pt, ptlim);
|
||||
continue;
|
||||
case 'Y':
|
||||
pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d",
|
||||
pt, ptlim);
|
||||
continue;
|
||||
case 'Z':
|
||||
#ifdef TM_ZONE
|
||||
if (t->TM_ZONE)
|
||||
pt = _add(t->TM_ZONE, pt, ptlim);
|
||||
else
|
||||
#endif /* defined TM_ZONE */
|
||||
if (t->tm_isdst == 0 || t->tm_isdst == 1) {
|
||||
pt = _add(tzname[t->tm_isdst],
|
||||
pt, ptlim);
|
||||
} else pt = _add("?", pt, ptlim);
|
||||
continue;
|
||||
case '%':
|
||||
/*
|
||||
* X311J/88-090 (4.12.3.5): if conversion char is
|
||||
* undefined, behavior is undefined. Print out the
|
||||
* character itself as printf(3) also does.
|
||||
*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pt == ptlim)
|
||||
break;
|
||||
*pt++ = *format;
|
||||
}
|
||||
return pt;
|
||||
}
|
||||
|
||||
static char *
|
||||
_conv(n, format, pt, ptlim)
|
||||
int n;
|
||||
const char *format;
|
||||
char *pt;
|
||||
const char *ptlim;
|
||||
{
|
||||
char buf[INT_STRLEN_MAXIMUM(int) + 1];
|
||||
|
||||
(void) sprintf(buf, format, n);
|
||||
return _add(buf, pt, ptlim);
|
||||
}
|
||||
|
||||
static char *
|
||||
_add(str, pt, ptlim)
|
||||
const char *str;
|
||||
char *pt;
|
||||
const char *ptlim;
|
||||
{
|
||||
while (pt < ptlim && (*pt = *str++) != '\0')
|
||||
++pt;
|
||||
return pt;
|
||||
}
|
119
lib/libc/stdtime/time2posix.3
Normal file
119
lib/libc/stdtime/time2posix.3
Normal file
@ -0,0 +1,119 @@
|
||||
.TH TIME2POSIX 3
|
||||
.SH NAME
|
||||
time2posix, posix2time \- convert seconds since the Epoch
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.B #include <sys/types.h>
|
||||
.B #include <time.h>
|
||||
.PP
|
||||
.B time_t time2posix(t)
|
||||
.B time_t t
|
||||
.PP
|
||||
.B time_t posix2time(t)
|
||||
.B time_t t
|
||||
.PP
|
||||
.B cc ... -lz
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
IEEE Standard 1003.1
|
||||
(POSIX)
|
||||
legislates that a time_t value of
|
||||
536457599 shall correspond to "Wed Dec 31 23:59:59 GMT 1986."
|
||||
This effectively implies that POSIX time_t's cannot include leap
|
||||
seconds and,
|
||||
therefore,
|
||||
that the system time must be adjusted as each leap occurs.
|
||||
.PP
|
||||
If the time package is configured with leap-second support
|
||||
enabled,
|
||||
however,
|
||||
no such adjustment is needed and
|
||||
time_t values continue to increase over leap events
|
||||
(as a true `seconds since...' value).
|
||||
This means that these values will differ from those required by POSIX
|
||||
by the net number of leap seconds inserted since the Epoch.
|
||||
.PP
|
||||
Typically this is not a problem as the type time_t is intended
|
||||
to be
|
||||
(mostly)
|
||||
opaque\(emtime_t values should only be obtained-from and
|
||||
passed-to functions such as
|
||||
.IR time(2) ,
|
||||
.IR localtime(3) ,
|
||||
.IR mktime(3) ,
|
||||
and
|
||||
.IR difftime(3) .
|
||||
However,
|
||||
POSIX gives an arithmetic
|
||||
expression for directly computing a time_t value from a given date/time,
|
||||
and the same relationship is assumed by some
|
||||
(usually older)
|
||||
applications.
|
||||
Any programs creating/dissecting time_t's
|
||||
using such a relationship will typically not handle intervals
|
||||
over leap seconds correctly.
|
||||
.PP
|
||||
The
|
||||
.I time2posix
|
||||
and
|
||||
.I posix2time
|
||||
functions are provided to address this time_t mismatch by converting
|
||||
between local time_t values and their POSIX equivalents.
|
||||
This is done by accounting for the number of time-base changes that
|
||||
would have taken place on a POSIX system as leap seconds were inserted
|
||||
or deleted.
|
||||
These converted values can then be used in lieu of correcting the older
|
||||
applications,
|
||||
or when communicating with POSIX-compliant systems.
|
||||
.PP
|
||||
.I Time2posix
|
||||
is single-valued.
|
||||
That is,
|
||||
every local time_t
|
||||
corresponds to a single POSIX time_t.
|
||||
.I Posix2time
|
||||
is less well-behaved:
|
||||
for a positive leap second hit the result is not unique,
|
||||
and for a negative leap second hit the corresponding
|
||||
POSIX time_t doesn't exist so an adjacent value is returned.
|
||||
Both of these are good indicators of the inferiority of the
|
||||
POSIX representation.
|
||||
.PP
|
||||
The following table summarizes the relationship between a time
|
||||
T and it's conversion to,
|
||||
and back from,
|
||||
the POSIX representation over the leap second inserted at the end of June,
|
||||
1993.
|
||||
.nf
|
||||
.ta \w'93/06/30 'u +\w'23:59:59 'u +\w'A+0 'u +\w'X=time2posix(T) 'u
|
||||
DATE TIME T X=time2posix(T) posix2time(X)
|
||||
93/06/30 23:59:59 A+0 B+0 A+0
|
||||
93/06/30 23:59:60 A+1 B+1 A+1 or A+2
|
||||
93/07/01 00:00:00 A+2 B+1 A+1 or A+2
|
||||
93/07/01 00:00:01 A+3 B+2 A+3
|
||||
|
||||
A leap second deletion would look like...
|
||||
|
||||
DATE TIME T X=time2posix(T) posix2time(X)
|
||||
??/06/30 23:59:58 A+0 B+0 A+0
|
||||
??/07/01 00:00:00 A+1 B+2 A+1
|
||||
??/07/01 00:00:01 A+2 B+3 A+2
|
||||
.sp
|
||||
.ce
|
||||
[Note: posix2time(B+1) => A+0 or A+1]
|
||||
.fi
|
||||
.PP
|
||||
If leap-second support is not enabled,
|
||||
local time_t's and
|
||||
POSIX time_t's are equivalent,
|
||||
and both
|
||||
.I time2posix
|
||||
and
|
||||
.I posix2time
|
||||
degenerate to the identity function.
|
||||
.SH SEE ALSO
|
||||
difftime(3),
|
||||
localtime(3),
|
||||
mktime(3),
|
||||
time(2)
|
||||
.\" @(#)time2posix.3 7.3
|
123
lib/libc/stdtime/tzfile.5
Normal file
123
lib/libc/stdtime/tzfile.5
Normal file
@ -0,0 +1,123 @@
|
||||
.TH TZFILE 5
|
||||
.SH NAME
|
||||
tzfile \- time zone information
|
||||
.SH SYNOPSIS
|
||||
.B
|
||||
#include <tzfile.h>
|
||||
.SH DESCRIPTION
|
||||
The time zone information files used by
|
||||
.IR tzset (3)
|
||||
begin with bytes reserved for future use,
|
||||
followed by four four-byte values of type
|
||||
.BR long ,
|
||||
written in a ``standard'' byte order
|
||||
(the high-order byte of the value is written first).
|
||||
These values are,
|
||||
in order:
|
||||
.TP
|
||||
.I tzh_ttisstdcnt
|
||||
The number of standard/wall indicators stored in the file.
|
||||
.TP
|
||||
.I tzh_leapcnt
|
||||
The number of leap seconds for which data is stored in the file.
|
||||
.TP
|
||||
.I tzh_timecnt
|
||||
The number of "transition times" for which data is stored
|
||||
in the file.
|
||||
.TP
|
||||
.I tzh_typecnt
|
||||
The number of "local time types" for which data is stored
|
||||
in the file (must not be zero).
|
||||
.TP
|
||||
.I tzh_charcnt
|
||||
The number of characters of "time zone abbreviation strings"
|
||||
stored in the file.
|
||||
.PP
|
||||
The above header is followed by
|
||||
.I tzh_timecnt
|
||||
four-byte values of type
|
||||
.BR long ,
|
||||
sorted in ascending order.
|
||||
These values are written in ``standard'' byte order.
|
||||
Each is used as a transition time (as returned by
|
||||
.IR time (2))
|
||||
at which the rules for computing local time change.
|
||||
Next come
|
||||
.I tzh_timecnt
|
||||
one-byte values of type
|
||||
.BR "unsigned char" ;
|
||||
each one tells which of the different types of ``local time'' types
|
||||
described in the file is associated with the same-indexed transition time.
|
||||
These values serve as indices into an array of
|
||||
.I ttinfo
|
||||
structures that appears next in the file;
|
||||
these structures are defined as follows:
|
||||
.in +.5i
|
||||
.sp
|
||||
.nf
|
||||
.ta .5i +\w'unsigned int\0\0'u
|
||||
struct ttinfo {
|
||||
long tt_gmtoff;
|
||||
int tt_isdst;
|
||||
unsigned int tt_abbrind;
|
||||
};
|
||||
.in -.5i
|
||||
.fi
|
||||
.sp
|
||||
Each structure is written as a four-byte value for
|
||||
.I tt_gmtoff
|
||||
of type
|
||||
.BR long ,
|
||||
in a standard byte order, followed by a one-byte value for
|
||||
.I tt_isdst
|
||||
and a one-byte value for
|
||||
.IR tt_abbrind .
|
||||
In each structure,
|
||||
.I tt_gmtoff
|
||||
gives the number of seconds to be added to GMT,
|
||||
.I tt_isdst
|
||||
tells whether
|
||||
.I tm_isdst
|
||||
should be set by
|
||||
.I localtime (3)
|
||||
and
|
||||
.I tt_abbrind
|
||||
serves as an index into the array of time zone abbreviation characters
|
||||
that follow the
|
||||
.I ttinfo
|
||||
structure(s) in the file.
|
||||
.PP
|
||||
Then there are
|
||||
.I tzh_leapcnt
|
||||
pairs of four-byte values, written in standard byte order;
|
||||
the first value of each pair gives the time
|
||||
(as returned by
|
||||
.IR time(2))
|
||||
at which a leap second occurs;
|
||||
the second gives the
|
||||
.I total
|
||||
number of leap seconds to be applied after the given time.
|
||||
The pairs of values are sorted in ascending order by time.
|
||||
.PP
|
||||
Finally there are
|
||||
.I tzh_ttisstdcnt
|
||||
standard/wall indicators, each stored as a one-byte value;
|
||||
they tell whether the transition times associated with local time types
|
||||
were specified as standard time or wall clock time,
|
||||
and are used when a time zone file is used in handling POSIX-style
|
||||
time zone environment variables.
|
||||
.PP
|
||||
.I Localtime
|
||||
uses the first standard-time
|
||||
.I ttinfo
|
||||
structure in the file
|
||||
(or simply the first
|
||||
.I ttinfo
|
||||
structure in the absence of a standard-time structure)
|
||||
if either
|
||||
.I tzh_timecnt
|
||||
is zero or the time argument is less than the first transition time recorded
|
||||
in the file.
|
||||
.SH SEE ALSO
|
||||
newctime(3)
|
||||
.\" @(#)tzfile.5 7.2
|
170
lib/libc/stdtime/tzfile.h
Normal file
170
lib/libc/stdtime/tzfile.h
Normal file
@ -0,0 +1,170 @@
|
||||
#ifndef TZFILE_H
|
||||
|
||||
#define TZFILE_H
|
||||
|
||||
/*
|
||||
** This header is for use ONLY with the time conversion code.
|
||||
** There is no guarantee that it will remain unchanged,
|
||||
** or that it will remain at all.
|
||||
** Do NOT copy it to any system include directory.
|
||||
** Thank you!
|
||||
*/
|
||||
|
||||
/*
|
||||
** ID
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char tzfilehid[] = "@(#)tzfile.h 7.4";
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
||||
/*
|
||||
** Information about time zone files.
|
||||
*/
|
||||
|
||||
#ifndef TZDIR
|
||||
#define TZDIR "/usr/local/etc/zoneinfo" /* Time zone object file directory */
|
||||
#endif /* !defined TZDIR */
|
||||
|
||||
#ifndef TZDEFAULT
|
||||
#define TZDEFAULT "localtime"
|
||||
#endif /* !defined TZDEFAULT */
|
||||
|
||||
#ifndef TZDEFRULES
|
||||
#define TZDEFRULES "posixrules"
|
||||
#endif /* !defined TZDEFRULES */
|
||||
|
||||
/*
|
||||
** Each file begins with. . .
|
||||
*/
|
||||
|
||||
struct tzhead {
|
||||
char tzh_reserved[24]; /* reserved for future use */
|
||||
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
|
||||
char tzh_leapcnt[4]; /* coded number of leap seconds */
|
||||
char tzh_timecnt[4]; /* coded number of transition times */
|
||||
char tzh_typecnt[4]; /* coded number of local time types */
|
||||
char tzh_charcnt[4]; /* coded number of abbr. chars */
|
||||
};
|
||||
|
||||
/*
|
||||
** . . .followed by. . .
|
||||
**
|
||||
** tzh_timecnt (char [4])s coded transition times a la time(2)
|
||||
** tzh_timecnt (unsigned char)s types of local time starting at above
|
||||
** tzh_typecnt repetitions of
|
||||
** one (char [4]) coded GMT offset in seconds
|
||||
** one (unsigned char) used to set tm_isdst
|
||||
** one (unsigned char) that's an abbreviation list index
|
||||
** tzh_charcnt (char)s '\0'-terminated zone abbreviations
|
||||
** tzh_leapcnt repetitions of
|
||||
** one (char [4]) coded leap second transition times
|
||||
** one (char [4]) total correction after above
|
||||
** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
|
||||
** time is standard time, if FALSE,
|
||||
** transition time is wall clock time
|
||||
** if absent, transition times are
|
||||
** assumed to be wall clock time
|
||||
*/
|
||||
|
||||
/*
|
||||
** In the current implementation, "tzset()" refuses to deal with files that
|
||||
** exceed any of the limits below.
|
||||
*/
|
||||
|
||||
#ifndef TZ_MAX_TIMES
|
||||
/*
|
||||
** The TZ_MAX_TIMES value below is enough to handle a bit more than a
|
||||
** year's worth of solar time (corrected daily to the nearest second) or
|
||||
** 138 years of Pacific Presidential Election time
|
||||
** (where there are three time zone transitions every fourth year).
|
||||
*/
|
||||
#define TZ_MAX_TIMES 370
|
||||
#endif /* !defined TZ_MAX_TIMES */
|
||||
|
||||
#ifndef TZ_MAX_TYPES
|
||||
#ifndef NOSOLAR
|
||||
#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
|
||||
#endif /* !defined NOSOLAR */
|
||||
#ifdef NOSOLAR
|
||||
#define TZ_MAX_TYPES 10 /* Maximum number of local time types */
|
||||
#endif /* !defined NOSOLAR */
|
||||
#endif /* !defined TZ_MAX_TYPES */
|
||||
|
||||
#ifndef TZ_MAX_CHARS
|
||||
#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
|
||||
/* (limited by what unsigned chars can hold) */
|
||||
#endif /* !defined TZ_MAX_CHARS */
|
||||
|
||||
#ifndef TZ_MAX_LEAPS
|
||||
#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
|
||||
#endif /* !defined TZ_MAX_LEAPS */
|
||||
|
||||
#define SECSPERMIN 60
|
||||
#define MINSPERHOUR 60
|
||||
#define HOURSPERDAY 24
|
||||
#define DAYSPERWEEK 7
|
||||
#define DAYSPERNYEAR 365
|
||||
#define DAYSPERLYEAR 366
|
||||
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
|
||||
#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
|
||||
#define MONSPERYEAR 12
|
||||
|
||||
#define TM_SUNDAY 0
|
||||
#define TM_MONDAY 1
|
||||
#define TM_TUESDAY 2
|
||||
#define TM_WEDNESDAY 3
|
||||
#define TM_THURSDAY 4
|
||||
#define TM_FRIDAY 5
|
||||
#define TM_SATURDAY 6
|
||||
|
||||
#define TM_JANUARY 0
|
||||
#define TM_FEBRUARY 1
|
||||
#define TM_MARCH 2
|
||||
#define TM_APRIL 3
|
||||
#define TM_MAY 4
|
||||
#define TM_JUNE 5
|
||||
#define TM_JULY 6
|
||||
#define TM_AUGUST 7
|
||||
#define TM_SEPTEMBER 8
|
||||
#define TM_OCTOBER 9
|
||||
#define TM_NOVEMBER 10
|
||||
#define TM_DECEMBER 11
|
||||
|
||||
#define TM_YEAR_BASE 1900
|
||||
|
||||
#define EPOCH_YEAR 1970
|
||||
#define EPOCH_WDAY TM_THURSDAY
|
||||
|
||||
/*
|
||||
** Accurate only for the past couple of centuries;
|
||||
** that will probably do.
|
||||
*/
|
||||
|
||||
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
|
||||
|
||||
#ifndef USG
|
||||
|
||||
/*
|
||||
** Use of the underscored variants may cause problems if you move your code to
|
||||
** certain System-V-based systems; for maximum portability, use the
|
||||
** underscore-free variants. The underscored variants are provided for
|
||||
** backward compatibility only; they may disappear from future versions of
|
||||
** this file.
|
||||
*/
|
||||
|
||||
#define SECS_PER_MIN SECSPERMIN
|
||||
#define MINS_PER_HOUR MINSPERHOUR
|
||||
#define HOURS_PER_DAY HOURSPERDAY
|
||||
#define DAYS_PER_WEEK DAYSPERWEEK
|
||||
#define DAYS_PER_NYEAR DAYSPERNYEAR
|
||||
#define DAYS_PER_LYEAR DAYSPERLYEAR
|
||||
#define SECS_PER_HOUR SECSPERHOUR
|
||||
#define SECS_PER_DAY SECSPERDAY
|
||||
#define MONS_PER_YEAR MONSPERYEAR
|
||||
|
||||
#endif /* !defined USG */
|
||||
|
||||
#endif /* !defined TZFILE_H */
|
Loading…
Reference in New Issue
Block a user