mirror of https://github.com/postgres/postgres
and should do now that we control our own destiny for timezone handling, but this commit gets the bulk of the picayune diffs in place. Magnus Hagander and Tom Lane.REL8_0_STABLE
parent
260b513fc3
commit
63bd0db121
@ -0,0 +1,73 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* pgtime.h |
||||
* PostgreSQL internal timezone library |
||||
* |
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group |
||||
* |
||||
* IDENTIFICATION |
||||
* $PostgreSQL: pgsql/src/include/pgtime.h,v 1.1 2004/05/21 05:08:03 tgl Exp $ |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef _PGTIME_H |
||||
#define _PGTIME_H |
||||
|
||||
#ifdef FRONTEND |
||||
|
||||
/* Don't mess with anything for the frontends */ |
||||
#include <time.h> |
||||
|
||||
#else |
||||
|
||||
/*
|
||||
* Redefine functions and defines we implement, so we cause an |
||||
* error if someone tries to use the "base functions"
|
||||
*/ |
||||
#ifndef NO_REDEFINE_TIMEFUNCS |
||||
#define localtime DONOTUSETHIS_localtime |
||||
#define gmtime DONOTUSETHIS_gmtime |
||||
#define asctime DONOTUSETHIS_asctime |
||||
#define ctime DONOTUSETHIS_ctime |
||||
#define tzset DONOTUSETHIS_tzset |
||||
#define mktime DONOTUSETHIS_mktime |
||||
#define tzname DONOTUSETHIS_tzname |
||||
#define daylight DONOTUSETHIS_daylight |
||||
#define strftime DONOTUSETHIS_strftime |
||||
#endif |
||||
|
||||
/* Then pull in default declarations, particularly time_t */ |
||||
#include <time.h> |
||||
|
||||
/*
|
||||
* Now define prototype for our own timezone implementation |
||||
* structs and functions. |
||||
*/ |
||||
struct pg_tm { |
||||
int tm_sec; |
||||
int tm_min; |
||||
int tm_hour; |
||||
int tm_mday; |
||||
int tm_mon; |
||||
int tm_year; |
||||
int tm_wday; |
||||
int tm_yday; |
||||
int tm_isdst; |
||||
long int tm_gmtoff; |
||||
const char *tm_zone; |
||||
}; |
||||
|
||||
extern struct pg_tm *pg_localtime(const time_t *); |
||||
extern struct pg_tm *pg_gmtime(const time_t *); |
||||
extern time_t pg_mktime(struct pg_tm *); |
||||
extern bool pg_tzset(const char *tzname); |
||||
extern size_t pg_strftime(char *s, size_t max, const char *format, |
||||
const struct pg_tm *tm); |
||||
extern void pg_timezone_initialize(void); |
||||
extern bool tz_acceptable(void); |
||||
extern const char *select_default_timezone(void); |
||||
extern const char *pg_get_current_timezone(void); |
||||
|
||||
#endif /* FRONTEND */ |
||||
|
||||
#endif /* _PGTIME_H */ |
@ -1,130 +0,0 @@ |
||||
-- |
||||
-- ABSTIME |
||||
-- testing built-in time type abstime |
||||
-- uses reltime and tinterval |
||||
-- |
||||
-- |
||||
-- timezones may vary based not only on location but the operating |
||||
-- system. the main correctness issue is that the OS may not get |
||||
-- daylight savings time right for times prior to Unix epoch (jan 1 1970). |
||||
-- |
||||
CREATE TABLE ABSTIME_TBL (f1 abstime); |
||||
BEGIN; |
||||
INSERT INTO ABSTIME_TBL (f1) VALUES (abstime 'now'); |
||||
INSERT INTO ABSTIME_TBL (f1) VALUES (abstime 'now'); |
||||
SELECT count(*) AS two FROM ABSTIME_TBL WHERE f1 = 'now' ; |
||||
two |
||||
----- |
||||
2 |
||||
(1 row) |
||||
|
||||
END; |
||||
DELETE FROM ABSTIME_TBL; |
||||
INSERT INTO ABSTIME_TBL (f1) VALUES ('Jan 14, 1973 03:14:21'); |
||||
INSERT INTO ABSTIME_TBL (f1) VALUES (abstime 'Mon May 1 00:30:30 1995'); |
||||
INSERT INTO ABSTIME_TBL (f1) VALUES (abstime 'epoch'); |
||||
INSERT INTO ABSTIME_TBL (f1) VALUES (abstime 'infinity'); |
||||
INSERT INTO ABSTIME_TBL (f1) VALUES (abstime '-infinity'); |
||||
INSERT INTO ABSTIME_TBL (f1) VALUES (abstime 'May 10, 1947 23:59:12'); |
||||
-- what happens if we specify slightly misformatted abstime? |
||||
INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 35, 1946 10:00:00'); |
||||
ERROR: date/time field value out of range: "Feb 35, 1946 10:00:00" |
||||
HINT: Perhaps you need a different "datestyle" setting. |
||||
INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 28, 1984 25:08:10'); |
||||
ERROR: date/time field value out of range: "Feb 28, 1984 25:08:10" |
||||
-- badly formatted abstimes: these should result in invalid abstimes |
||||
INSERT INTO ABSTIME_TBL (f1) VALUES ('bad date format'); |
||||
ERROR: invalid input syntax for type abstime: "bad date format" |
||||
INSERT INTO ABSTIME_TBL (f1) VALUES ('Jun 10, 1843'); |
||||
-- test abstime operators |
||||
SELECT '' AS eight, ABSTIME_TBL.*; |
||||
eight | f1 |
||||
-------+------------------------------ |
||||
| Sun Jan 14 03:14:21 1973 PST |
||||
| Mon May 01 00:30:30 1995 PDT |
||||
| Wed Dec 31 16:00:00 1969 PST |
||||
| infinity |
||||
| -infinity |
||||
| Sat May 10 23:59:12 1947 PDT |
||||
| invalid |
||||
(7 rows) |
||||
|
||||
SELECT '' AS six, ABSTIME_TBL.* |
||||
WHERE ABSTIME_TBL.f1 < abstime 'Jun 30, 2001'; |
||||
six | f1 |
||||
-----+------------------------------ |
||||
| Sun Jan 14 03:14:21 1973 PST |
||||
| Mon May 01 00:30:30 1995 PDT |
||||
| Wed Dec 31 16:00:00 1969 PST |
||||
| -infinity |
||||
| Sat May 10 23:59:12 1947 PDT |
||||
(5 rows) |
||||
|
||||
SELECT '' AS six, ABSTIME_TBL.* |
||||
WHERE ABSTIME_TBL.f1 > abstime '-infinity'; |
||||
six | f1 |
||||
-----+------------------------------ |
||||
| Sun Jan 14 03:14:21 1973 PST |
||||
| Mon May 01 00:30:30 1995 PDT |
||||
| Wed Dec 31 16:00:00 1969 PST |
||||
| infinity |
||||
| Sat May 10 23:59:12 1947 PDT |
||||
| invalid |
||||
(6 rows) |
||||
|
||||
SELECT '' AS six, ABSTIME_TBL.* |
||||
WHERE abstime 'May 10, 1947 23:59:12' <> ABSTIME_TBL.f1; |
||||
six | f1 |
||||
-----+------------------------------ |
||||
| Sun Jan 14 03:14:21 1973 PST |
||||
| Mon May 01 00:30:30 1995 PDT |
||||
| Wed Dec 31 16:00:00 1969 PST |
||||
| infinity |
||||
| -infinity |
||||
| invalid |
||||
(6 rows) |
||||
|
||||
SELECT '' AS three, ABSTIME_TBL.* |
||||
WHERE abstime 'epoch' >= ABSTIME_TBL.f1; |
||||
three | f1 |
||||
-------+------------------------------ |
||||
| Wed Dec 31 16:00:00 1969 PST |
||||
| -infinity |
||||
| Sat May 10 23:59:12 1947 PDT |
||||
(3 rows) |
||||
|
||||
SELECT '' AS four, ABSTIME_TBL.* |
||||
WHERE ABSTIME_TBL.f1 <= abstime 'Jan 14, 1973 03:14:21'; |
||||
four | f1 |
||||
------+------------------------------ |
||||
| Sun Jan 14 03:14:21 1973 PST |
||||
| Wed Dec 31 16:00:00 1969 PST |
||||
| -infinity |
||||
| Sat May 10 23:59:12 1947 PDT |
||||
(4 rows) |
||||
|
||||
SELECT '' AS four, ABSTIME_TBL.* |
||||
WHERE ABSTIME_TBL.f1 <?> |
||||
tinterval '["Apr 1 1950 00:00:00" "Dec 30 1999 23:00:00"]'; |
||||
four | f1 |
||||
------+------------------------------ |
||||
| Sun Jan 14 03:14:21 1973 PST |
||||
| Mon May 01 00:30:30 1995 PDT |
||||
| Wed Dec 31 16:00:00 1969 PST |
||||
(3 rows) |
||||
|
||||
SELECT '' AS four, f1 AS abstime, |
||||
date_part('year', f1) AS year, date_part('month', f1) AS month, |
||||
date_part('day',f1) AS day, date_part('hour', f1) AS hour, |
||||
date_part('minute', f1) AS minute, date_part('second', f1) AS second |
||||
FROM ABSTIME_TBL |
||||
WHERE isfinite(f1) |
||||
ORDER BY abstime; |
||||
four | abstime | year | month | day | hour | minute | second |
||||
------+------------------------------+------+-------+-----+------+--------+-------- |
||||
| Sat May 10 23:59:12 1947 PDT | 1947 | 5 | 10 | 23 | 59 | 12 |
||||
| Wed Dec 31 16:00:00 1969 PST | 1969 | 12 | 31 | 16 | 0 | 0 |
||||
| Sun Jan 14 03:14:21 1973 PST | 1973 | 1 | 14 | 3 | 14 | 21 |
||||
| Mon May 01 00:30:30 1995 PDT | 1995 | 5 | 1 | 0 | 30 | 30 |
||||
(4 rows) |
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,170 +0,0 @@ |
||||
-- |
||||
-- TINTERVAL |
||||
-- |
||||
CREATE TABLE TINTERVAL_TBL (f1 tinterval); |
||||
-- Should accept any abstime, |
||||
-- so do not bother with extensive testing of values |
||||
INSERT INTO TINTERVAL_TBL (f1) |
||||
VALUES ('["-infinity" "infinity"]'); |
||||
INSERT INTO TINTERVAL_TBL (f1) |
||||
VALUES ('["May 10, 1947 23:59:12" "Jan 14, 1973 03:14:21"]'); |
||||
INSERT INTO TINTERVAL_TBL (f1) |
||||
VALUES ('["Sep 4, 1983 23:59:12" "Oct 4, 1983 23:59:12"]'); |
||||
INSERT INTO TINTERVAL_TBL (f1) |
||||
VALUES ('["epoch" "Mon May 1 00:30:30 1995"]'); |
||||
INSERT INTO TINTERVAL_TBL (f1) |
||||
VALUES ('["Feb 15 1990 12:15:03" "2001-09-23 11:12:13"]'); |
||||
-- badly formatted tintervals |
||||
INSERT INTO TINTERVAL_TBL (f1) |
||||
VALUES ('["bad time specifications" ""]'); |
||||
ERROR: invalid input syntax for type abstime: "bad time specifications" |
||||
INSERT INTO TINTERVAL_TBL (f1) |
||||
VALUES ('["" "infinity"]'); |
||||
ERROR: invalid input syntax for type abstime: "" |
||||
-- test tinterval operators |
||||
SELECT '' AS five, TINTERVAL_TBL.*; |
||||
five | f1 |
||||
------+----------------------------------------------------------------- |
||||
| ["-infinity" "infinity"] |
||||
| ["Sat May 10 23:59:12 1947 PDT" "Sun Jan 14 03:14:21 1973 PST"] |
||||
| ["Sun Sep 04 23:59:12 1983 PDT" "Tue Oct 04 23:59:12 1983 PDT"] |
||||
| ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] |
||||
| ["Thu Feb 15 12:15:03 1990 PST" "Sun Sep 23 11:12:13 2001 PDT"] |
||||
(5 rows) |
||||
|
||||
-- length == |
||||
SELECT '' AS one, t.* |
||||
FROM TINTERVAL_TBL t |
||||
WHERE t.f1 #= '@ 1 months'; |
||||
one | f1 |
||||
-----+----------------------------------------------------------------- |
||||
| ["Sun Sep 04 23:59:12 1983 PDT" "Tue Oct 04 23:59:12 1983 PDT"] |
||||
(1 row) |
||||
|
||||
-- length <> |
||||
SELECT '' AS three, t.* |
||||
FROM TINTERVAL_TBL t |
||||
WHERE t.f1 #<> '@ 1 months'; |
||||
three | f1 |
||||
-------+----------------------------------------------------------------- |
||||
| ["Sat May 10 23:59:12 1947 PDT" "Sun Jan 14 03:14:21 1973 PST"] |
||||
| ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] |
||||
| ["Thu Feb 15 12:15:03 1990 PST" "Sun Sep 23 11:12:13 2001 PDT"] |
||||
(3 rows) |
||||
|
||||
-- length < |
||||
SELECT '' AS zero, t.* |
||||
FROM TINTERVAL_TBL t |
||||
WHERE t.f1 #< '@ 1 month'; |
||||
zero | f1 |
||||
------+---- |
||||
(0 rows) |
||||
|
||||
-- length <= |
||||
SELECT '' AS one, t.* |
||||
FROM TINTERVAL_TBL t |
||||
WHERE t.f1 #<= '@ 1 month'; |
||||
one | f1 |
||||
-----+----------------------------------------------------------------- |
||||
| ["Sun Sep 04 23:59:12 1983 PDT" "Tue Oct 04 23:59:12 1983 PDT"] |
||||
(1 row) |
||||
|
||||
-- length > |
||||
SELECT '' AS three, t.* |
||||
FROM TINTERVAL_TBL t |
||||
WHERE t.f1 #> '@ 1 year'; |
||||
three | f1 |
||||
-------+----------------------------------------------------------------- |
||||
| ["Sat May 10 23:59:12 1947 PDT" "Sun Jan 14 03:14:21 1973 PST"] |
||||
| ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] |
||||
| ["Thu Feb 15 12:15:03 1990 PST" "Sun Sep 23 11:12:13 2001 PDT"] |
||||
(3 rows) |
||||
|
||||
-- length >= |
||||
SELECT '' AS three, t.* |
||||
FROM TINTERVAL_TBL t |
||||
WHERE t.f1 #>= '@ 3 years'; |
||||
three | f1 |
||||
-------+----------------------------------------------------------------- |
||||
| ["Sat May 10 23:59:12 1947 PDT" "Sun Jan 14 03:14:21 1973 PST"] |
||||
| ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] |
||||
| ["Thu Feb 15 12:15:03 1990 PST" "Sun Sep 23 11:12:13 2001 PDT"] |
||||
(3 rows) |
||||
|
||||
-- overlaps |
||||
SELECT '' AS three, t1.* |
||||
FROM TINTERVAL_TBL t1 |
||||
WHERE t1.f1 && |
||||
tinterval '["Aug 15 14:23:19 1983" "Sep 16 14:23:19 1983"]'; |
||||
three | f1 |
||||
-------+----------------------------------------------------------------- |
||||
| ["-infinity" "infinity"] |
||||
| ["Sun Sep 04 23:59:12 1983 PDT" "Tue Oct 04 23:59:12 1983 PDT"] |
||||
| ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] |
||||
(3 rows) |
||||
|
||||
SET geqo TO 'off'; |
||||
SELECT '' AS five, t1.f1, t2.f1 |
||||
FROM TINTERVAL_TBL t1, TINTERVAL_TBL t2 |
||||
WHERE t1.f1 && t2.f1 and |
||||
t1.f1 = t2.f1 |
||||
ORDER BY t1.f1, t2.f1; |
||||
five | f1 | f1 |
||||
------+-----------------------------------------------------------------+----------------------------------------------------------------- |
||||
| ["-infinity" "infinity"] | ["-infinity" "infinity"] |
||||
| ["Sun Sep 04 23:59:12 1983 PDT" "Tue Oct 04 23:59:12 1983 PDT"] | ["Sun Sep 04 23:59:12 1983 PDT" "Tue Oct 04 23:59:12 1983 PDT"] |
||||
| ["Thu Feb 15 12:15:03 1990 PST" "Sun Sep 23 11:12:13 2001 PDT"] | ["Thu Feb 15 12:15:03 1990 PST" "Sun Sep 23 11:12:13 2001 PDT"] |
||||
| ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] | ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] |
||||
| ["Sat May 10 23:59:12 1947 PDT" "Sun Jan 14 03:14:21 1973 PST"] | ["Sat May 10 23:59:12 1947 PDT" "Sun Jan 14 03:14:21 1973 PST"] |
||||
(5 rows) |
||||
|
||||
SELECT '' AS fourteen, t1.f1 AS interval1, t2.f1 AS interval2 |
||||
FROM TINTERVAL_TBL t1, TINTERVAL_TBL t2 |
||||
WHERE t1.f1 && t2.f1 and not t1.f1 = t2.f1 |
||||
ORDER BY interval1, interval2; |
||||
fourteen | interval1 | interval2 |
||||
----------+-----------------------------------------------------------------+----------------------------------------------------------------- |
||||
| ["-infinity" "infinity"] | ["Sun Sep 04 23:59:12 1983 PDT" "Tue Oct 04 23:59:12 1983 PDT"] |
||||
| ["-infinity" "infinity"] | ["Thu Feb 15 12:15:03 1990 PST" "Sun Sep 23 11:12:13 2001 PDT"] |
||||
| ["-infinity" "infinity"] | ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] |
||||
| ["-infinity" "infinity"] | ["Sat May 10 23:59:12 1947 PDT" "Sun Jan 14 03:14:21 1973 PST"] |
||||
| ["Sun Sep 04 23:59:12 1983 PDT" "Tue Oct 04 23:59:12 1983 PDT"] | ["-infinity" "infinity"] |
||||
| ["Sun Sep 04 23:59:12 1983 PDT" "Tue Oct 04 23:59:12 1983 PDT"] | ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] |
||||
| ["Thu Feb 15 12:15:03 1990 PST" "Sun Sep 23 11:12:13 2001 PDT"] | ["-infinity" "infinity"] |
||||
| ["Thu Feb 15 12:15:03 1990 PST" "Sun Sep 23 11:12:13 2001 PDT"] | ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] |
||||
| ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] | ["-infinity" "infinity"] |
||||
| ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] | ["Sun Sep 04 23:59:12 1983 PDT" "Tue Oct 04 23:59:12 1983 PDT"] |
||||
| ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] | ["Thu Feb 15 12:15:03 1990 PST" "Sun Sep 23 11:12:13 2001 PDT"] |
||||
| ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] | ["Sat May 10 23:59:12 1947 PDT" "Sun Jan 14 03:14:21 1973 PST"] |
||||
| ["Sat May 10 23:59:12 1947 PDT" "Sun Jan 14 03:14:21 1973 PST"] | ["-infinity" "infinity"] |
||||
| ["Sat May 10 23:59:12 1947 PDT" "Sun Jan 14 03:14:21 1973 PST"] | ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] |
||||
(14 rows) |
||||
|
||||
-- contains |
||||
SELECT '' AS five, t1.f1 |
||||
FROM TINTERVAL_TBL t1 |
||||
WHERE not t1.f1 << |
||||
tinterval '["Aug 15 14:23:19 1980" "Sep 16 14:23:19 1990"]' |
||||
ORDER BY t1.f1; |
||||
five | f1 |
||||
------+----------------------------------------------------------------- |
||||
| ["Sun Sep 04 23:59:12 1983 PDT" "Tue Oct 04 23:59:12 1983 PDT"] |
||||
| ["Thu Feb 15 12:15:03 1990 PST" "Sun Sep 23 11:12:13 2001 PDT"] |
||||
| ["Sat May 10 23:59:12 1947 PDT" "Sun Jan 14 03:14:21 1973 PST"] |
||||
(3 rows) |
||||
|
||||
-- make time interval |
||||
SELECT '' AS three, t1.f1 |
||||
FROM TINTERVAL_TBL t1 |
||||
WHERE t1.f1 && |
||||
(abstime 'Aug 15 14:23:19 1983' <#> |
||||
abstime 'Sep 16 14:23:19 1983') |
||||
ORDER BY t1.f1; |
||||
three | f1 |
||||
-------+----------------------------------------------------------------- |
||||
| ["-infinity" "infinity"] |
||||
| ["Sun Sep 04 23:59:12 1983 PDT" "Tue Oct 04 23:59:12 1983 PDT"] |
||||
| ["Wed Dec 31 16:00:00 1969 PST" "Mon May 01 00:30:30 1995 PDT"] |
||||
(3 rows) |
||||
|
||||
RESET geqo; |
@ -1,75 +0,0 @@ |
||||
#include "pgtz.h" |
||||
/*
|
||||
** This file is in the public domain, so clarified as of |
||||
** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). |
||||
*/ |
||||
|
||||
#ifndef lint |
||||
#ifndef NOID |
||||
static char elsieid[] = "@(#)asctime.c 7.9"; |
||||
#endif /* !defined NOID */ |
||||
#endif /* !defined lint */ |
||||
|
||||
/*LINTLIBRARY*/ |
||||
|
||||
#include "private.h" |
||||
#include "tzfile.h" |
||||
|
||||
/*
|
||||
** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, Second Edition, 1996-07-12. |
||||
*/ |
||||
|
||||
char * |
||||
asctime_r(timeptr, buf) |
||||
register const struct tm * timeptr; |
||||
char * buf; |
||||
{ |
||||
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" |
||||
}; |
||||
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(buf, "%.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 buf; |
||||
} |
||||
|
||||
/*
|
||||
** A la X3J11, with core dump avoidance. |
||||
*/ |
||||
|
||||
char * |
||||
asctime(timeptr) |
||||
register const struct tm * timeptr; |
||||
{ |
||||
/*
|
||||
** 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]; |
||||
|
||||
return asctime_r(timeptr, result); |
||||
} |
@ -1,84 +0,0 @@ |
||||
#include "pgtz.h" |
||||
/*
|
||||
** This file is in the public domain, so clarified as of |
||||
** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov). |
||||
*/ |
||||
|
||||
#ifndef lint |
||||
#ifndef NOID |
||||
static char elsieid[] = "@(#)difftime.c 7.9"; |
||||
#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; |
||||
|
||||
{ |
||||
time_t tt; |
||||
double d; |
||||
long_double ld; |
||||
|
||||
if (sizeof tt < sizeof d) |
||||
return (double) time1 - (double) time0; |
||||
if (sizeof tt < sizeof ld) |
||||
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 = (~ (time_t) 0) << (TYPE_BIT(time_t) - 1); |
||||
/*
|
||||
** 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; |
||||
** some 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 with those compilers. |
||||
*/ |
||||
return delta - 2 * (long_double) hibit; |
||||
} |
@ -1,12 +1,23 @@ |
||||
#include "postgres.h" |
||||
#include "miscadmin.h" |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* pgtz.h |
||||
* Timezone Library Integration Functions |
||||
* |
||||
* Note: this file contains only definitions that are private to the |
||||
* timezone library. Public definitions are in pgtime.h. |
||||
* |
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group |
||||
* |
||||
* IDENTIFICATION |
||||
* $PostgreSQL: pgsql/src/timezone/pgtz.h,v 1.7 2004/05/21 05:08:06 tgl Exp $ |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef _PGTZ_H |
||||
#define _PGTZ_H |
||||
|
||||
#ifndef HAVE_SYMLINK |
||||
#define HAVE_SYMLINK 0 |
||||
#endif |
||||
#define TZ_STRLEN_MAX 255 |
||||
|
||||
extern char *pg_TZDIR(void); |
||||
|
||||
#define NOID |
||||
#define TZDIR pg_TZDIR() |
||||
|
||||
char *pg_TZDIR(void); |
||||
#endif /* _PGTZ_H */ |
||||
|
@ -0,0 +1,480 @@ |
||||
/*
|
||||
** 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. |
||||
*/ |
||||
|
||||
#include "postgres.h" |
||||
|
||||
#include <fcntl.h> |
||||
#include <locale.h> |
||||
|
||||
#include "pgtz.h" |
||||
#include "private.h" |
||||
#include "tzfile.h" |
||||
|
||||
|
||||
struct lc_time_T { |
||||
const char * mon[MONSPERYEAR]; |
||||
const char * month[MONSPERYEAR]; |
||||
const char * wday[DAYSPERWEEK]; |
||||
const char * weekday[DAYSPERWEEK]; |
||||
const char * X_fmt; |
||||
const char * x_fmt; |
||||
const char * c_fmt; |
||||
const char * am; |
||||
const char * pm; |
||||
const char * date_fmt; |
||||
}; |
||||
|
||||
#define Locale (&C_time_locale) |
||||
|
||||
static const struct lc_time_T C_time_locale = { |
||||
{ |
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", |
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" |
||||
}, { |
||||
"January", "February", "March", "April", "May", "June", |
||||
"July", "August", "September", "October", "November", "December" |
||||
}, { |
||||
"Sun", "Mon", "Tue", "Wed", |
||||
"Thu", "Fri", "Sat" |
||||
}, { |
||||
"Sunday", "Monday", "Tuesday", "Wednesday", |
||||
"Thursday", "Friday", "Saturday" |
||||
}, |
||||
|
||||
/* X_fmt */ |
||||
"%H:%M:%S", |
||||
|
||||
/*
|
||||
** x_fmt |
||||
** C99 requires this format. |
||||
** Using just numbers (as here) makes Quakers happier; |
||||
** it's also compatible with SVR4. |
||||
*/ |
||||
"%m/%d/%y", |
||||
|
||||
/*
|
||||
** c_fmt |
||||
** C99 requires this format. |
||||
** Previously this code used "%D %X", but we now conform to C99. |
||||
** Note that |
||||
** "%a %b %d %H:%M:%S %Y" |
||||
** is used by Solaris 2.3. |
||||
*/ |
||||
"%a %b %e %T %Y", |
||||
|
||||
/* am */ |
||||
"AM", |
||||
|
||||
/* pm */ |
||||
"PM", |
||||
|
||||
/* date_fmt */ |
||||
"%a %b %e %H:%M:%S %Z %Y" |
||||
}; |
||||
|
||||
static char * _add (const char *, char *, const char *); |
||||
static char * _conv (int, const char *, char *, const char *); |
||||
static char * _fmt (const char *, const struct pg_tm *, char *, const char *, int *); |
||||
|
||||
#define IN_NONE 0 |
||||
#define IN_SOME 1 |
||||
#define IN_THIS 2 |
||||
#define IN_ALL 3 |
||||
|
||||
|
||||
size_t pg_strftime(char *s, size_t maxsize, const char *format, const struct pg_tm *t) |
||||
{ |
||||
char * p; |
||||
int warn; |
||||
|
||||
warn = IN_NONE; |
||||
p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn); |
||||
if (p == s + maxsize) |
||||
return 0; |
||||
*p = '\0'; |
||||
return p - s; |
||||
} |
||||
|
||||
static char * _fmt(const char *format, const struct pg_tm *t, char *pt, const char *ptlim, int *warnp) |
||||
{ |
||||
for ( ; *format; ++format) { |
||||
if (*format == '%') { |
||||
label: |
||||
switch (*++format) { |
||||
case '\0': |
||||
--format; |
||||
break; |
||||
case 'A': |
||||
pt = _add((t->tm_wday < 0 || |
||||
t->tm_wday >= DAYSPERWEEK) ? |
||||
"?" : Locale->weekday[t->tm_wday], |
||||
pt, ptlim); |
||||
continue; |
||||
case 'a': |
||||
pt = _add((t->tm_wday < 0 || |
||||
t->tm_wday >= DAYSPERWEEK) ? |
||||
"?" : Locale->wday[t->tm_wday], |
||||
pt, ptlim); |
||||
continue; |
||||
case 'B': |
||||
pt = _add((t->tm_mon < 0 || |
||||
t->tm_mon >= MONSPERYEAR) ? |
||||
"?" : Locale->month[t->tm_mon], |
||||
pt, ptlim); |
||||
continue; |
||||
case 'b': |
||||
case 'h': |
||||
pt = _add((t->tm_mon < 0 || |
||||
t->tm_mon >= MONSPERYEAR) ? |
||||
"?" : Locale->mon[t->tm_mon], |
||||
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, 1993-05-24) |
||||
*/ |
||||
pt = _conv((t->tm_year + TM_YEAR_BASE) / 100, |
||||
"%02d", pt, ptlim); |
||||
continue; |
||||
case 'c': |
||||
{ |
||||
int warn2 = IN_SOME; |
||||
|
||||
pt = _fmt(Locale->c_fmt, t, pt, ptlim, warnp); |
||||
if (warn2 == IN_ALL) |
||||
warn2 = IN_THIS; |
||||
if (warn2 > *warnp) |
||||
*warnp = warn2; |
||||
} |
||||
continue; |
||||
case 'D': |
||||
pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp); |
||||
continue; |
||||
case 'd': |
||||
pt = _conv(t->tm_mday, "%02d", pt, ptlim); |
||||
continue; |
||||
case 'E': |
||||
case 'O': |
||||
/*
|
||||
** C99 locale modifiers. |
||||
** The sequences |
||||
** %Ec %EC %Ex %EX %Ey %EY |
||||
** %Od %oe %OH %OI %Om %OM |
||||
** %OS %Ou %OU %OV %Ow %OW %Oy |
||||
** are supposed to provide alternate |
||||
** representations. |
||||
*/ |
||||
goto label; |
||||
case 'e': |
||||
pt = _conv(t->tm_mday, "%2d", pt, ptlim); |
||||
continue; |
||||
case 'F': |
||||
pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp); |
||||
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, 1993-05-24) |
||||
*/ |
||||
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, 1993-05-24) |
||||
*/ |
||||
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 >= (HOURSPERDAY / 2)) ? |
||||
Locale->pm : |
||||
Locale->am, |
||||
pt, ptlim); |
||||
continue; |
||||
case 'R': |
||||
pt = _fmt("%H:%M", t, pt, ptlim, warnp); |
||||
continue; |
||||
case 'r': |
||||
pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp); |
||||
continue; |
||||
case 'S': |
||||
pt = _conv(t->tm_sec, "%02d", pt, ptlim); |
||||
continue; |
||||
case 's': |
||||
{ |
||||
struct pg_tm tm; |
||||
char buf[INT_STRLEN_MAXIMUM(time_t) + 1]; |
||||
time_t mkt; |
||||
|
||||
tm = *t; |
||||
mkt = pg_mktime(&tm); |
||||
if (TYPE_SIGNED(time_t)) |
||||
(void) sprintf(buf, "%ld", (long) mkt); |
||||
else |
||||
(void) sprintf(buf, "%lu", (unsigned long) mkt); |
||||
pt = _add(buf, pt, ptlim); |
||||
} |
||||
continue; |
||||
case 'T': |
||||
pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp); |
||||
continue; |
||||
case 't': |
||||
pt = _add("\t", pt, ptlim); |
||||
continue; |
||||
case 'U': |
||||
pt = _conv((t->tm_yday + DAYSPERWEEK - |
||||
t->tm_wday) / DAYSPERWEEK, |
||||
"%02d", pt, ptlim); |
||||
continue; |
||||
case 'u': |
||||
/*
|
||||
** From Arnold Robbins' strftime version 3.0: |
||||
** "ISO 8601: Weekday as a decimal number |
||||
** [1 (Monday) - 7]" |
||||
** (ado, 1993-05-24) |
||||
*/ |
||||
pt = _conv((t->tm_wday == 0) ? |
||||
DAYSPERWEEK : t->tm_wday, |
||||
"%d", pt, ptlim); |
||||
continue; |
||||
case 'V': /* ISO 8601 week number */ |
||||
case 'G': /* ISO 8601 year (four digits) */ |
||||
case 'g': /* ISO 8601 year (two digits) */ |
||||
/*
|
||||
** 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)." |
||||
** (ado, 1993-05-24) |
||||
** |
||||
** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn: |
||||
** "Week 01 of a year is per definition the first week which has the |
||||
** Thursday in this year, which is equivalent to the week which contains |
||||
** the fourth day of January. In other words, the first week of a new year |
||||
** is the week which has the majority of its days in the new year. Week 01 |
||||
** might also contain days from the previous year and the week before week |
||||
** 01 of a year is the last week (52 or 53) of the previous year even if |
||||
** it contains days from the new year. A week starts with Monday (day 1) |
||||
** and ends with Sunday (day 7). For example, the first week of the year |
||||
** 1997 lasts from 1996-12-30 to 1997-01-05..." |
||||
** (ado, 1996-01-02) |
||||
*/ |
||||
{ |
||||
int year; |
||||
int yday; |
||||
int wday; |
||||
int w; |
||||
|
||||
year = t->tm_year + TM_YEAR_BASE; |
||||
yday = t->tm_yday; |
||||
wday = t->tm_wday; |
||||
for ( ; ; ) { |
||||
int len; |
||||
int bot; |
||||
int top; |
||||
|
||||
len = isleap(year) ? |
||||
DAYSPERLYEAR : |
||||
DAYSPERNYEAR; |
||||
/*
|
||||
** What yday (-3 ... 3) does |
||||
** the ISO year begin on? |
||||
*/ |
||||
bot = ((yday + 11 - wday) % |
||||
DAYSPERWEEK) - 3; |
||||
/*
|
||||
** What yday does the NEXT |
||||
** ISO year begin on? |
||||
*/ |
||||
top = bot - |
||||
(len % DAYSPERWEEK); |
||||
if (top < -3) |
||||
top += DAYSPERWEEK; |
||||
top += len; |
||||
if (yday >= top) { |
||||
++year; |
||||
w = 1; |
||||
break; |
||||
} |
||||
if (yday >= bot) { |
||||
w = 1 + ((yday - bot) / |
||||
DAYSPERWEEK); |
||||
break; |
||||
} |
||||
--year; |
||||
yday += isleap(year) ? |
||||
DAYSPERLYEAR : |
||||
DAYSPERNYEAR; |
||||
} |
||||
if (*format == 'V') |
||||
pt = _conv(w, "%02d", |
||||
pt, ptlim); |
||||
else if (*format == 'g') { |
||||
*warnp = IN_ALL; |
||||
pt = _conv(year % 100, "%02d", |
||||
pt, ptlim); |
||||
} else pt = _conv(year, "%04d", |
||||
pt, ptlim); |
||||
} |
||||
continue; |
||||
case 'v': |
||||
/*
|
||||
** From Arnold Robbins' strftime version 3.0: |
||||
** "date as dd-bbb-YYYY" |
||||
** (ado, 1993-05-24) |
||||
*/ |
||||
pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp); |
||||
continue; |
||||
case 'W': |
||||
pt = _conv((t->tm_yday + DAYSPERWEEK - |
||||
(t->tm_wday ? |
||||
(t->tm_wday - 1) : |
||||
(DAYSPERWEEK - 1))) / DAYSPERWEEK, |
||||
"%02d", pt, ptlim); |
||||
continue; |
||||
case 'w': |
||||
pt = _conv(t->tm_wday, "%d", pt, ptlim); |
||||
continue; |
||||
case 'X': |
||||
pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp); |
||||
continue; |
||||
case 'x': |
||||
{ |
||||
int warn2 = IN_SOME; |
||||
|
||||
pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2); |
||||
if (warn2 == IN_ALL) |
||||
warn2 = IN_THIS; |
||||
if (warn2 > *warnp) |
||||
*warnp = warn2; |
||||
} |
||||
continue; |
||||
case 'y': |
||||
*warnp = IN_ALL; |
||||
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': |
||||
if (t->tm_zone != NULL) |
||||
pt = _add(t->tm_zone, pt, ptlim); |
||||
/*
|
||||
** C99 says that %Z must be replaced by the |
||||
** empty string if the time zone is not |
||||
** determinable. |
||||
*/ |
||||
continue; |
||||
case 'z': |
||||
{ |
||||
int diff; |
||||
char const * sign; |
||||
|
||||
if (t->tm_isdst < 0) |
||||
continue; |
||||
diff = t->tm_gmtoff; |
||||
if (diff < 0) { |
||||
sign = "-"; |
||||
diff = -diff; |
||||
} else sign = "+"; |
||||
pt = _add(sign, pt, ptlim); |
||||
diff /= 60; |
||||
pt = _conv((diff/60)*100 + diff%60, |
||||
"%04d", pt, ptlim); |
||||
} |
||||
continue; |
||||
case '+': |
||||
pt = _fmt(Locale->date_fmt, t, pt, ptlim, |
||||
warnp); |
||||
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(const 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(const char *str, char *pt, const char *ptlim) |
||||
{ |
||||
while (pt < ptlim && (*pt = *str++) != '\0') |
||||
++pt; |
||||
return pt; |
||||
} |
Loading…
Reference in new issue