1997-03-15 00:21:12 +01:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* datetime.c
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
* Support functions for date/time types.
|
1997-03-15 00:21:12 +01:00
|
|
|
*
|
2019-01-02 18:44:25 +01:00
|
|
|
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1997-03-15 00:21:12 +01:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/utils/adt/datetime.c
|
1997-03-15 00:21:12 +01:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
2000-07-13 00:59:15 +02:00
|
|
|
#include "postgres.h"
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <limits.h>
|
2003-01-16 01:26:49 +01:00
|
|
|
#include <math.h>
|
2000-07-13 00:59:15 +02:00
|
|
|
|
2012-08-30 22:15:44 +02:00
|
|
|
#include "access/htup_details.h"
|
2005-06-30 00:51:57 +02:00
|
|
|
#include "access/xact.h"
|
2006-07-25 05:51:23 +02:00
|
|
|
#include "catalog/pg_type.h"
|
2018-03-13 15:21:09 +01:00
|
|
|
#include "common/string.h"
|
2006-07-25 05:51:23 +02:00
|
|
|
#include "funcapi.h"
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
#include "miscadmin.h"
|
2012-02-08 15:33:02 +01:00
|
|
|
#include "nodes/nodeFuncs.h"
|
2006-06-08 00:32:31 +02:00
|
|
|
#include "utils/builtins.h"
|
2008-11-12 02:36:20 +01:00
|
|
|
#include "utils/date.h"
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
#include "utils/datetime.h"
|
2006-07-25 05:51:23 +02:00
|
|
|
#include "utils/memutils.h"
|
|
|
|
#include "utils/tzparser.h"
|
1997-03-15 00:21:12 +01:00
|
|
|
|
2019-05-22 19:04:48 +02:00
|
|
|
static int DecodeNumber(int flen, char *field, bool haveTextMonth,
|
|
|
|
int fmask, int *tmask,
|
|
|
|
struct pg_tm *tm, fsec_t *fsec, bool *is2digits);
|
|
|
|
static int DecodeNumberField(int len, char *str,
|
|
|
|
int fmask, int *tmask,
|
|
|
|
struct pg_tm *tm, fsec_t *fsec, bool *is2digits);
|
|
|
|
static int DecodeTime(char *str, int fmask, int range,
|
|
|
|
int *tmask, struct pg_tm *tm, fsec_t *fsec);
|
2006-07-25 05:51:23 +02:00
|
|
|
static const datetkn *datebsearch(const char *key, const datetkn *base, int nel);
|
2019-05-22 19:04:48 +02:00
|
|
|
static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
|
|
|
|
struct pg_tm *tm);
|
2016-02-07 05:11:28 +01:00
|
|
|
static char *AppendSeconds(char *cp, int sec, fsec_t fsec,
|
2019-05-22 19:04:48 +02:00
|
|
|
int precision, bool fillzeros);
|
2017-06-21 20:39:04 +02:00
|
|
|
static void AdjustFractSeconds(double frac, struct pg_tm *tm, fsec_t *fsec,
|
2019-05-22 19:04:48 +02:00
|
|
|
int scale);
|
2017-06-21 20:39:04 +02:00
|
|
|
static void AdjustFractDays(double frac, struct pg_tm *tm, fsec_t *fsec,
|
2019-05-22 19:04:48 +02:00
|
|
|
int scale);
|
|
|
|
static int DetermineTimeZoneOffsetInternal(struct pg_tm *tm, pg_tz *tzp,
|
|
|
|
pg_time_t *tp);
|
Don't require dynamic timezone abbreviations to match underlying time zone.
Previously, we threw an error if a dynamic timezone abbreviation did not
match any abbreviation recorded in the referenced IANA time zone entry.
That seemed like a good consistency check at the time, but it turns out
that a number of the abbreviations in the IANA database are things that
Olson and crew made up out of whole cloth. Their current policy is to
remove such names in favor of using simple numeric offsets. Perhaps
unsurprisingly, a lot of these made-up abbreviations have varied in meaning
over time, which meant that our commit b2cbced9e and later changes made
them into dynamic abbreviations. So with newer IANA database versions
that don't mention these abbreviations at all, we fail, as reported in bug
#14307 from Neil Anderson. It's worse than just a few unused-in-the-wild
abbreviations not working, because the pg_timezone_abbrevs view stops
working altogether (since its underlying function tries to compute the
whole view result in one call).
We considered deleting these abbreviations from our abbreviations list, but
the problem with that is that we can't stay ahead of possible future IANA
changes. Instead, let's leave the abbreviations list alone, and treat any
"orphaned" dynamic abbreviation as just meaning the referenced time zone.
It will behave a bit differently than it used to, in that you can't any
longer override the zone's standard vs. daylight rule by using the "wrong"
abbreviation of a pair, but that's better than failing entirely. (Also,
this solution can be interpreted as adding a small new feature, which is
that any abbreviation a user wants can be defined as referencing a time
zone name.)
Back-patch to all supported branches, since this problem affects all
of them when using tzdata 2016f or newer.
Report: <20160902031551.15674.67337@wrigleys.postgresql.org>
Discussion: <6189.1472820913@sss.pgh.pa.us>
2016-09-02 23:29:31 +02:00
|
|
|
static bool DetermineTimeZoneAbbrevOffsetInternal(pg_time_t t,
|
2019-05-22 19:04:48 +02:00
|
|
|
const char *abbr, pg_tz *tzp,
|
|
|
|
int *offset, int *isdst);
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
static pg_tz *FetchDynamicTimeZone(TimeZoneAbbrevTable *tbl, const datetkn *tp);
|
2000-03-16 15:38:42 +01:00
|
|
|
|
2001-07-10 03:41:47 +02:00
|
|
|
|
2004-06-03 04:08:07 +02:00
|
|
|
const int day_tab[2][13] =
|
|
|
|
{
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0},
|
2004-06-03 04:08:07 +02:00
|
|
|
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}
|
|
|
|
};
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2014-01-18 22:04:11 +01:00
|
|
|
const char *const months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
2002-09-04 22:31:48 +02:00
|
|
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};
|
1997-03-15 00:21:12 +01:00
|
|
|
|
2014-01-18 22:04:11 +01:00
|
|
|
const char *const days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
|
2002-09-04 22:31:48 +02:00
|
|
|
"Thursday", "Friday", "Saturday", NULL};
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/*****************************************************************************
|
|
|
|
* PRIVATE ROUTINES *
|
|
|
|
*****************************************************************************/
|
1997-03-15 00:21:12 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/*
|
2003-01-16 01:26:49 +01:00
|
|
|
* datetktbl holds date/time keywords.
|
|
|
|
*
|
|
|
|
* Note that this table must be strictly alphabetically ordered to allow an
|
|
|
|
* O(ln(N)) search algorithm to be used.
|
2001-12-29 19:31:48 +01:00
|
|
|
*
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
* The token field must be NUL-terminated; we truncate entries to TOKMAXLEN
|
|
|
|
* characters to fit.
|
2001-12-29 19:31:48 +01:00
|
|
|
*
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
* The static table contains no TZ, DTZ, or DYNTZ entries; rather those
|
|
|
|
* are loaded from configuration files and stored in zoneabbrevtbl, whose
|
|
|
|
* abbrevs[] field has the same format as the static datetktbl.
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
2006-07-25 05:51:23 +02:00
|
|
|
static const datetkn datetktbl[] = {
|
2014-02-17 17:20:21 +01:00
|
|
|
/* token, type, value */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{EARLY, RESERV, DTK_EARLY}, /* "-infinity" reserved for "early time" */
|
2004-03-30 17:53:18 +02:00
|
|
|
{DA_D, ADBC, AD}, /* "ad" for years > 0 */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
{"allballs", RESERV, DTK_ZULU}, /* 00:00:00 */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{"am", AMPM, AM},
|
2003-01-16 01:26:49 +01:00
|
|
|
{"apr", MONTH, 4},
|
|
|
|
{"april", MONTH, 4},
|
2002-08-04 08:44:47 +02:00
|
|
|
{"at", IGNORE_DTF, 0}, /* "at" (throwaway) */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{"aug", MONTH, 8},
|
|
|
|
{"august", MONTH, 8},
|
2004-03-30 17:53:18 +02:00
|
|
|
{DB_C, ADBC, BC}, /* "bc" for years <= 0 */
|
2001-12-29 19:31:48 +01:00
|
|
|
{"d", UNITS, DTK_DAY}, /* "day of month" for ISO input */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{"dec", MONTH, 12},
|
|
|
|
{"december", MONTH, 12},
|
2015-09-06 03:04:37 +02:00
|
|
|
{"dow", UNITS, DTK_DOW}, /* day of week */
|
|
|
|
{"doy", UNITS, DTK_DOY}, /* day of year */
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
{"dst", DTZMOD, SECS_PER_HOUR},
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{EPOCH, RESERV, DTK_EPOCH}, /* "epoch" reserved for system epoch time */
|
|
|
|
{"feb", MONTH, 2},
|
|
|
|
{"february", MONTH, 2},
|
|
|
|
{"fri", DOW, 5},
|
|
|
|
{"friday", DOW, 5},
|
2001-12-29 19:31:48 +01:00
|
|
|
{"h", UNITS, DTK_HOUR}, /* "hour" */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{LATE, RESERV, DTK_LATE}, /* "infinity" reserved for "late time" */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
{"isodow", UNITS, DTK_ISODOW}, /* ISO day of week, Sunday == 7 */
|
2007-02-16 04:39:46 +01:00
|
|
|
{"isoyear", UNITS, DTK_ISOYEAR}, /* year in terms of the ISO week date */
|
2001-12-29 19:31:48 +01:00
|
|
|
{"j", UNITS, DTK_JULIAN},
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{"jan", MONTH, 1},
|
|
|
|
{"january", MONTH, 1},
|
2001-12-29 19:31:48 +01:00
|
|
|
{"jd", UNITS, DTK_JULIAN},
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{"jul", MONTH, 7},
|
2001-12-29 19:31:48 +01:00
|
|
|
{"julian", UNITS, DTK_JULIAN},
|
2001-12-21 07:03:27 +01:00
|
|
|
{"july", MONTH, 7},
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{"jun", MONTH, 6},
|
|
|
|
{"june", MONTH, 6},
|
2001-12-29 19:31:48 +01:00
|
|
|
{"m", UNITS, DTK_MONTH}, /* "month" for ISO input */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{"mar", MONTH, 3},
|
|
|
|
{"march", MONTH, 3},
|
|
|
|
{"may", MONTH, 5},
|
2001-12-29 19:31:48 +01:00
|
|
|
{"mm", UNITS, DTK_MINUTE}, /* "minute" for ISO input */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{"mon", DOW, 1},
|
|
|
|
{"monday", DOW, 1},
|
|
|
|
{"nov", MONTH, 11},
|
|
|
|
{"november", MONTH, 11},
|
|
|
|
{NOW, RESERV, DTK_NOW}, /* current transaction time */
|
|
|
|
{"oct", MONTH, 10},
|
|
|
|
{"october", MONTH, 10},
|
2002-08-04 08:44:47 +02:00
|
|
|
{"on", IGNORE_DTF, 0}, /* "on" (throwaway) */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{"pm", AMPM, PM},
|
2001-12-29 19:31:48 +01:00
|
|
|
{"s", UNITS, DTK_SECOND}, /* "seconds" for ISO input */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{"sat", DOW, 6},
|
|
|
|
{"saturday", DOW, 6},
|
|
|
|
{"sep", MONTH, 9},
|
|
|
|
{"sept", MONTH, 9},
|
|
|
|
{"september", MONTH, 9},
|
|
|
|
{"sun", DOW, 0},
|
|
|
|
{"sunday", DOW, 0},
|
2002-02-25 17:17:04 +01:00
|
|
|
{"t", ISOTIME, DTK_TIME}, /* Filler for ISO time fields */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{"thu", DOW, 4},
|
|
|
|
{"thur", DOW, 4},
|
|
|
|
{"thurs", DOW, 4},
|
|
|
|
{"thursday", DOW, 4},
|
|
|
|
{TODAY, RESERV, DTK_TODAY}, /* midnight */
|
|
|
|
{TOMORROW, RESERV, DTK_TOMORROW}, /* tomorrow midnight */
|
|
|
|
{"tue", DOW, 2},
|
|
|
|
{"tues", DOW, 2},
|
|
|
|
{"tuesday", DOW, 2},
|
|
|
|
{"wed", DOW, 3},
|
|
|
|
{"wednesday", DOW, 3},
|
|
|
|
{"weds", DOW, 3},
|
2001-12-29 19:31:48 +01:00
|
|
|
{"y", UNITS, DTK_YEAR}, /* "year" for ISO input */
|
2006-10-17 23:03:21 +02:00
|
|
|
{YESTERDAY, RESERV, DTK_YESTERDAY} /* yesterday midnight */
|
2001-06-18 18:14:44 +02:00
|
|
|
};
|
|
|
|
|
2018-10-17 21:32:47 +02:00
|
|
|
static const int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0];
|
2001-06-18 18:14:44 +02:00
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/*
|
|
|
|
* deltatktbl: same format as datetktbl, but holds keywords used to represent
|
|
|
|
* time units (eg, for intervals, and for EXTRACT).
|
|
|
|
*/
|
2014-01-18 22:04:11 +01:00
|
|
|
static const datetkn deltatktbl[] = {
|
2014-02-17 17:20:21 +01:00
|
|
|
/* token, type, value */
|
2002-08-04 08:44:47 +02:00
|
|
|
{"@", IGNORE_DTF, 0}, /* postgres relative prefix */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{DAGO, AGO, 0}, /* "ago" indicates negative time offset */
|
2001-10-18 19:30:21 +02:00
|
|
|
{"c", UNITS, DTK_CENTURY}, /* "century" relative */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
{"cent", UNITS, DTK_CENTURY}, /* "century" relative */
|
2001-10-18 19:30:21 +02:00
|
|
|
{"centuries", UNITS, DTK_CENTURY}, /* "centuries" relative */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
{DCENTURY, UNITS, DTK_CENTURY}, /* "century" relative */
|
2001-10-25 07:50:21 +02:00
|
|
|
{"d", UNITS, DTK_DAY}, /* "day" relative */
|
|
|
|
{DDAY, UNITS, DTK_DAY}, /* "day" relative */
|
|
|
|
{"days", UNITS, DTK_DAY}, /* "days" relative */
|
|
|
|
{"dec", UNITS, DTK_DECADE}, /* "decade" relative */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
{DDECADE, UNITS, DTK_DECADE}, /* "decade" relative */
|
|
|
|
{"decades", UNITS, DTK_DECADE}, /* "decades" relative */
|
2003-01-16 01:26:49 +01:00
|
|
|
{"decs", UNITS, DTK_DECADE}, /* "decades" relative */
|
2001-10-25 07:50:21 +02:00
|
|
|
{"h", UNITS, DTK_HOUR}, /* "hour" relative */
|
|
|
|
{DHOUR, UNITS, DTK_HOUR}, /* "hour" relative */
|
|
|
|
{"hours", UNITS, DTK_HOUR}, /* "hours" relative */
|
|
|
|
{"hr", UNITS, DTK_HOUR}, /* "hour" relative */
|
|
|
|
{"hrs", UNITS, DTK_HOUR}, /* "hours" relative */
|
|
|
|
{"m", UNITS, DTK_MINUTE}, /* "minute" relative */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
{"microsecon", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
|
|
|
|
{"mil", UNITS, DTK_MILLENNIUM}, /* "millennium" relative */
|
|
|
|
{"millennia", UNITS, DTK_MILLENNIUM}, /* "millennia" relative */
|
|
|
|
{DMILLENNIUM, UNITS, DTK_MILLENNIUM}, /* "millennium" relative */
|
|
|
|
{"millisecon", UNITS, DTK_MILLISEC}, /* relative */
|
2002-09-04 22:31:48 +02:00
|
|
|
{"mils", UNITS, DTK_MILLENNIUM}, /* "millennia" relative */
|
|
|
|
{"min", UNITS, DTK_MINUTE}, /* "minute" relative */
|
2001-10-28 07:26:15 +01:00
|
|
|
{"mins", UNITS, DTK_MINUTE}, /* "minutes" relative */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
{DMINUTE, UNITS, DTK_MINUTE}, /* "minute" relative */
|
|
|
|
{"minutes", UNITS, DTK_MINUTE}, /* "minutes" relative */
|
2001-10-25 07:50:21 +02:00
|
|
|
{"mon", UNITS, DTK_MONTH}, /* "months" relative */
|
|
|
|
{"mons", UNITS, DTK_MONTH}, /* "months" relative */
|
|
|
|
{DMONTH, UNITS, DTK_MONTH}, /* "month" relative */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{"months", UNITS, DTK_MONTH},
|
|
|
|
{"ms", UNITS, DTK_MILLISEC},
|
|
|
|
{"msec", UNITS, DTK_MILLISEC},
|
|
|
|
{DMILLISEC, UNITS, DTK_MILLISEC},
|
|
|
|
{"mseconds", UNITS, DTK_MILLISEC},
|
|
|
|
{"msecs", UNITS, DTK_MILLISEC},
|
2001-10-28 07:26:15 +01:00
|
|
|
{"qtr", UNITS, DTK_QUARTER}, /* "quarter" relative */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
{DQUARTER, UNITS, DTK_QUARTER}, /* "quarter" relative */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{"s", UNITS, DTK_SECOND},
|
|
|
|
{"sec", UNITS, DTK_SECOND},
|
|
|
|
{DSECOND, UNITS, DTK_SECOND},
|
|
|
|
{"seconds", UNITS, DTK_SECOND},
|
|
|
|
{"secs", UNITS, DTK_SECOND},
|
2002-09-04 22:31:48 +02:00
|
|
|
{DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
|
2001-10-25 07:50:21 +02:00
|
|
|
{"timezone_h", UNITS, DTK_TZ_HOUR}, /* timezone hour units */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
{"timezone_m", UNITS, DTK_TZ_MINUTE}, /* timezone minutes units */
|
2002-09-04 22:31:48 +02:00
|
|
|
{"us", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
{"usec", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
|
2001-10-18 19:30:21 +02:00
|
|
|
{DMICROSEC, UNITS, DTK_MICROSEC}, /* "microsecond" relative */
|
|
|
|
{"useconds", UNITS, DTK_MICROSEC}, /* "microseconds" relative */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
{"usecs", UNITS, DTK_MICROSEC}, /* "microseconds" relative */
|
2001-10-18 19:30:21 +02:00
|
|
|
{"w", UNITS, DTK_WEEK}, /* "week" relative */
|
|
|
|
{DWEEK, UNITS, DTK_WEEK}, /* "week" relative */
|
|
|
|
{"weeks", UNITS, DTK_WEEK}, /* "weeks" relative */
|
|
|
|
{"y", UNITS, DTK_YEAR}, /* "year" relative */
|
|
|
|
{DYEAR, UNITS, DTK_YEAR}, /* "year" relative */
|
|
|
|
{"years", UNITS, DTK_YEAR}, /* "years" relative */
|
|
|
|
{"yr", UNITS, DTK_YEAR}, /* "year" relative */
|
2006-10-17 23:03:21 +02:00
|
|
|
{"yrs", UNITS, DTK_YEAR} /* "years" relative */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
};
|
|
|
|
|
2018-10-17 21:32:47 +02:00
|
|
|
static const int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
static TimeZoneAbbrevTable *zoneabbrevtbl = NULL;
|
|
|
|
|
|
|
|
/* Caches of recent lookup results in the above tables */
|
|
|
|
|
2006-07-25 05:51:23 +02:00
|
|
|
static const datetkn *datecache[MAXDATEFIELDS] = {NULL};
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2006-07-25 05:51:23 +02:00
|
|
|
static const datetkn *deltacache[MAXDATEFIELDS] = {NULL};
|
1997-03-15 00:21:12 +01:00
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
static const datetkn *abbrevcache[MAXDATEFIELDS] = {NULL};
|
|
|
|
|
1997-03-15 00:21:12 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/*
|
|
|
|
* Calendar time to Julian date conversions.
|
|
|
|
* Julian date is commonly used in astronomical applications,
|
|
|
|
* since it is numerically accurate and computationally simple.
|
|
|
|
* The algorithms here will accurately convert between Julian day
|
|
|
|
* and calendar date for all non-negative Julian days
|
2003-02-19 04:48:11 +01:00
|
|
|
* (i.e. from Nov 24, -4713 on).
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*
|
2003-02-19 04:48:11 +01:00
|
|
|
* Rewritten to eliminate overflow problems. This now allows the
|
|
|
|
* routines to work correctly for all Julian day counts from
|
2003-08-04 02:43:34 +02:00
|
|
|
* 0 to 2147483647 (Nov 24, -4713 to Jun 3, 5874898) assuming
|
2003-02-19 04:48:11 +01:00
|
|
|
* a 32-bit integer. Longer types should also work to the limits
|
|
|
|
* of their precision.
|
2016-03-17 00:09:04 +01:00
|
|
|
*
|
|
|
|
* Actually, date2j() will work sanely, in the sense of producing
|
|
|
|
* valid negative Julian dates, significantly before Nov 24, -4713.
|
|
|
|
* We rely on it to do so back to Nov 1, -4713; see IS_VALID_JULIAN()
|
|
|
|
* and associated commentary in timestamp.h.
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
1997-03-15 00:21:12 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
int
|
|
|
|
date2j(int y, int m, int d)
|
1997-03-15 00:21:12 +01:00
|
|
|
{
|
2003-02-19 04:48:11 +01:00
|
|
|
int julian;
|
|
|
|
int century;
|
|
|
|
|
2003-08-04 02:43:34 +02:00
|
|
|
if (m > 2)
|
|
|
|
{
|
2003-02-19 04:48:11 +01:00
|
|
|
m += 1;
|
|
|
|
y += 4800;
|
2003-08-04 02:43:34 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-02-19 04:48:11 +01:00
|
|
|
m += 13;
|
|
|
|
y += 4799;
|
|
|
|
}
|
|
|
|
|
2003-08-04 02:43:34 +02:00
|
|
|
century = y / 100;
|
|
|
|
julian = y * 365 - 32167;
|
|
|
|
julian += y / 4 - century + century / 4;
|
|
|
|
julian += 7834 * m / 256 + d;
|
1997-03-15 00:21:12 +01:00
|
|
|
|
2003-02-19 04:48:11 +01:00
|
|
|
return julian;
|
2017-06-21 20:39:04 +02:00
|
|
|
} /* date2j() */
|
1997-03-15 00:21:12 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
void
|
|
|
|
j2date(int jd, int *year, int *month, int *day)
|
1997-03-15 00:21:12 +01:00
|
|
|
{
|
2003-08-04 02:43:34 +02:00
|
|
|
unsigned int julian;
|
|
|
|
unsigned int quad;
|
|
|
|
unsigned int extra;
|
2003-02-19 04:48:11 +01:00
|
|
|
int y;
|
|
|
|
|
|
|
|
julian = jd;
|
|
|
|
julian += 32044;
|
2003-08-04 02:43:34 +02:00
|
|
|
quad = julian / 146097;
|
|
|
|
extra = (julian - quad * 146097) * 4 + 3;
|
|
|
|
julian += 60 + quad * 3 + extra / 146097;
|
|
|
|
quad = julian / 1461;
|
|
|
|
julian -= quad * 1461;
|
2003-02-19 04:48:11 +01:00
|
|
|
y = julian * 4 / 1461;
|
|
|
|
julian = ((y != 0) ? ((julian + 305) % 365) : ((julian + 306) % 366))
|
|
|
|
+ 123;
|
2003-08-04 02:43:34 +02:00
|
|
|
y += quad * 4;
|
2003-02-19 04:48:11 +01:00
|
|
|
*year = y - 4800;
|
|
|
|
quad = julian * 2141 / 65536;
|
2003-08-04 02:43:34 +02:00
|
|
|
*day = julian - 7834 * quad / 256;
|
2011-03-12 15:31:18 +01:00
|
|
|
*month = (quad + 10) % MONTHS_PER_YEAR + 1;
|
2017-06-21 20:39:04 +02:00
|
|
|
} /* j2date() */
|
1997-03-15 00:21:12 +01:00
|
|
|
|
2003-04-04 06:50:44 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* j2day - convert Julian date to day-of-week (0..6 == Sun..Sat)
|
|
|
|
*
|
|
|
|
* Note: various places use the locution j2day(date - 1) to produce a
|
2014-05-06 18:12:18 +02:00
|
|
|
* result according to the convention 0..6 = Mon..Sun. This is a bit of
|
2003-04-04 06:50:44 +02:00
|
|
|
* a crock, but will work as long as the computation here is just a modulo.
|
|
|
|
*/
|
1997-03-15 00:21:12 +01:00
|
|
|
int
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
j2day(int date)
|
1997-03-15 00:21:12 +01:00
|
|
|
{
|
2016-03-17 01:57:45 +01:00
|
|
|
date += 1;
|
|
|
|
date %= 7;
|
|
|
|
/* Cope if division truncates towards zero, as it probably does */
|
|
|
|
if (date < 0)
|
|
|
|
date += 7;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2016-03-17 01:57:45 +01:00
|
|
|
return date;
|
2017-06-21 20:39:04 +02:00
|
|
|
} /* j2day() */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
|
2005-06-30 00:51:57 +02:00
|
|
|
/*
|
|
|
|
* GetCurrentDateTime()
|
|
|
|
*
|
|
|
|
* Get the transaction start time ("now()") broken down as a struct pg_tm.
|
|
|
|
*/
|
|
|
|
void
|
2017-06-21 20:39:04 +02:00
|
|
|
GetCurrentDateTime(struct pg_tm *tm)
|
2005-06-30 00:51:57 +02:00
|
|
|
{
|
|
|
|
int tz;
|
|
|
|
fsec_t fsec;
|
|
|
|
|
|
|
|
timestamp2tm(GetCurrentTransactionStartTimestamp(), &tz, tm, &fsec,
|
|
|
|
NULL, NULL);
|
|
|
|
/* Note: don't pass NULL tzp to timestamp2tm; affects behavior */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* GetCurrentTimeUsec()
|
|
|
|
*
|
|
|
|
* Get the transaction start time ("now()") broken down as a struct pg_tm,
|
|
|
|
* including fractional seconds and timezone offset.
|
|
|
|
*/
|
|
|
|
void
|
2017-06-21 20:39:04 +02:00
|
|
|
GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp)
|
2005-06-30 00:51:57 +02:00
|
|
|
{
|
|
|
|
int tz;
|
|
|
|
|
|
|
|
timestamp2tm(GetCurrentTransactionStartTimestamp(), &tz, tm, fsec,
|
|
|
|
NULL, NULL);
|
|
|
|
/* Note: don't pass NULL tzp to timestamp2tm; affects behavior */
|
|
|
|
if (tzp != NULL)
|
|
|
|
*tzp = tz;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-12 02:36:20 +01:00
|
|
|
/*
|
2016-02-07 05:11:28 +01:00
|
|
|
* Append seconds and fractional seconds (if any) at *cp.
|
|
|
|
*
|
2008-11-12 02:36:20 +01:00
|
|
|
* precision is the max number of fraction digits, fillzeros says to
|
|
|
|
* pad to two integral-seconds digits.
|
2016-02-07 05:11:28 +01:00
|
|
|
*
|
|
|
|
* Returns a pointer to the new end of string. No NUL terminator is put
|
|
|
|
* there; callers are responsible for NUL terminating str themselves.
|
|
|
|
*
|
2008-11-12 02:36:20 +01:00
|
|
|
* Note that any sign is stripped from the input seconds values.
|
|
|
|
*/
|
2016-02-07 05:11:28 +01:00
|
|
|
static char *
|
2008-11-12 02:36:20 +01:00
|
|
|
AppendSeconds(char *cp, int sec, fsec_t fsec, int precision, bool fillzeros)
|
|
|
|
{
|
2016-02-07 05:11:28 +01:00
|
|
|
Assert(precision >= 0);
|
|
|
|
|
|
|
|
if (fillzeros)
|
|
|
|
cp = pg_ltostr_zeropad(cp, Abs(sec), 2);
|
|
|
|
else
|
|
|
|
cp = pg_ltostr(cp, Abs(sec));
|
|
|
|
|
2017-02-23 20:04:43 +01:00
|
|
|
/* fsec_t is just an int32 */
|
2016-02-07 05:11:28 +01:00
|
|
|
if (fsec != 0)
|
|
|
|
{
|
|
|
|
int32 value = Abs(fsec);
|
|
|
|
char *end = &cp[precision + 1];
|
|
|
|
bool gotnonzero = false;
|
|
|
|
|
|
|
|
*cp++ = '.';
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Append the fractional seconds part. Note that we don't want any
|
|
|
|
* trailing zeros here, so since we're building the number in reverse
|
|
|
|
* we'll skip appending zeros until we've output a non-zero digit.
|
|
|
|
*/
|
|
|
|
while (precision--)
|
|
|
|
{
|
|
|
|
int32 oldval = value;
|
|
|
|
int32 remainder;
|
|
|
|
|
|
|
|
value /= 10;
|
|
|
|
remainder = oldval - value * 10;
|
|
|
|
|
|
|
|
/* check if we got a non-zero */
|
|
|
|
if (remainder)
|
|
|
|
gotnonzero = true;
|
|
|
|
|
|
|
|
if (gotnonzero)
|
|
|
|
cp[precision] = '0' + remainder;
|
|
|
|
else
|
|
|
|
end = &cp[precision];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we still have a non-zero value then precision must have not been
|
|
|
|
* enough to print the number. We punt the problem to pg_ltostr(),
|
|
|
|
* which will generate a correct answer in the minimum valid width.
|
|
|
|
*/
|
|
|
|
if (value)
|
|
|
|
return pg_ltostr(cp, Abs(fsec));
|
|
|
|
|
|
|
|
return end;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return cp;
|
2001-10-18 19:30:21 +02:00
|
|
|
}
|
|
|
|
|
2016-02-07 05:11:28 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Variant of above that's specialized to timestamp case.
|
|
|
|
*
|
|
|
|
* Returns a pointer to the new end of string. No NUL terminator is put
|
|
|
|
* there; callers are responsible for NUL terminating str themselves.
|
|
|
|
*/
|
|
|
|
static char *
|
2017-06-21 20:39:04 +02:00
|
|
|
AppendTimestampSeconds(char *cp, struct pg_tm *tm, fsec_t fsec)
|
2008-11-12 02:36:20 +01:00
|
|
|
{
|
2016-02-07 05:11:28 +01:00
|
|
|
return AppendSeconds(cp, tm->tm_sec, fsec, MAX_TIMESTAMP_PRECISION, true);
|
2008-11-12 02:36:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Multiply frac by scale (to produce seconds) and add to *tm & *fsec.
|
|
|
|
* We assume the input frac is less than 1 so overflow is not an issue.
|
|
|
|
*/
|
|
|
|
static void
|
2017-06-21 20:39:04 +02:00
|
|
|
AdjustFractSeconds(double frac, struct pg_tm *tm, fsec_t *fsec, int scale)
|
2008-11-12 02:36:20 +01:00
|
|
|
{
|
2009-06-11 16:49:15 +02:00
|
|
|
int sec;
|
2008-11-12 02:36:20 +01:00
|
|
|
|
|
|
|
if (frac == 0)
|
|
|
|
return;
|
2009-06-11 16:49:15 +02:00
|
|
|
frac *= scale;
|
|
|
|
sec = (int) frac;
|
2008-11-12 02:36:20 +01:00
|
|
|
tm->tm_sec += sec;
|
2009-06-11 16:49:15 +02:00
|
|
|
frac -= sec;
|
|
|
|
*fsec += rint(frac * 1000000);
|
2008-11-12 02:36:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* As above, but initial scale produces days */
|
|
|
|
static void
|
2017-06-21 20:39:04 +02:00
|
|
|
AdjustFractDays(double frac, struct pg_tm *tm, fsec_t *fsec, int scale)
|
2008-11-12 02:36:20 +01:00
|
|
|
{
|
2009-06-11 16:49:15 +02:00
|
|
|
int extra_days;
|
2008-11-12 02:36:20 +01:00
|
|
|
|
|
|
|
if (frac == 0)
|
|
|
|
return;
|
2009-06-11 16:49:15 +02:00
|
|
|
frac *= scale;
|
|
|
|
extra_days = (int) frac;
|
2008-11-12 02:36:20 +01:00
|
|
|
tm->tm_mday += extra_days;
|
2009-06-11 16:49:15 +02:00
|
|
|
frac -= extra_days;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(frac, tm, fsec, SECS_PER_DAY);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fetch a fractional-second value with suitable error checking */
|
|
|
|
static int
|
|
|
|
ParseFractionalSecond(char *cp, fsec_t *fsec)
|
|
|
|
{
|
|
|
|
double frac;
|
|
|
|
|
|
|
|
/* Caller should always pass the start of the fraction part */
|
|
|
|
Assert(*cp == '.');
|
|
|
|
errno = 0;
|
|
|
|
frac = strtod(cp, &cp);
|
|
|
|
/* check for parse failure */
|
|
|
|
if (*cp != '\0' || errno != 0)
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
*fsec = rint(frac * 1000000);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* ParseDateTime()
|
2003-08-05 20:30:21 +02:00
|
|
|
* Break string into tokens based on a date/time context.
|
2003-08-28 01:29:29 +02:00
|
|
|
* Returns 0 if successful, DTERR code if bogus input detected.
|
2003-08-05 20:30:21 +02:00
|
|
|
*
|
|
|
|
* timestr - the input string
|
2005-05-26 04:04:14 +02:00
|
|
|
* workbuf - workspace for field string storage. This must be
|
2005-10-15 04:49:52 +02:00
|
|
|
* larger than the largest legal input for this datetime type --
|
|
|
|
* some additional space will be needed to NUL terminate fields.
|
2005-05-26 04:04:14 +02:00
|
|
|
* buflen - the size of workbuf
|
2003-08-05 20:30:21 +02:00
|
|
|
* field[] - pointers to field strings are returned in this array
|
|
|
|
* ftype[] - field type indicators are returned in this array
|
|
|
|
* maxfields - dimensions of the above two arrays
|
|
|
|
* *numfields - set to the actual number of fields detected
|
|
|
|
*
|
2005-05-26 04:04:14 +02:00
|
|
|
* The fields extracted from the input are stored as separate,
|
|
|
|
* null-terminated strings in the workspace at workbuf. Any text is
|
|
|
|
* converted to lower case.
|
2003-08-05 20:30:21 +02:00
|
|
|
*
|
2001-12-29 19:31:48 +01:00
|
|
|
* Several field types are assigned:
|
2002-09-04 22:31:48 +02:00
|
|
|
* DTK_NUMBER - digits and (possibly) a decimal point
|
|
|
|
* DTK_DATE - digits and two delimiters, or digits and text
|
|
|
|
* DTK_TIME - digits, colon delimiters, and possibly a decimal point
|
2006-10-17 23:03:21 +02:00
|
|
|
* DTK_STRING - text (no digits or punctuation)
|
2002-09-04 22:31:48 +02:00
|
|
|
* DTK_SPECIAL - leading "+" or "-" followed by text
|
2008-09-17 00:31:21 +02:00
|
|
|
* DTK_TZ - leading "+" or "-" followed by digits (also eats ':', '.', '-')
|
2003-08-05 20:30:21 +02:00
|
|
|
*
|
2001-12-29 19:31:48 +01:00
|
|
|
* Note that some field types can hold unexpected items:
|
2002-09-04 22:31:48 +02:00
|
|
|
* DTK_NUMBER can hold date fields (yy.ddd)
|
|
|
|
* DTK_STRING can hold months (January) and time zones (PST)
|
2006-10-17 23:03:21 +02:00
|
|
|
* DTK_DATE can hold time zone names (America/New_York, GMT-8)
|
1997-10-25 07:16:09 +02:00
|
|
|
*/
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
int
|
2005-05-26 04:04:14 +02:00
|
|
|
ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
char **field, int *ftype, int maxfields, int *numfields)
|
1997-03-15 00:21:12 +01:00
|
|
|
{
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
int nf = 0;
|
2003-08-05 20:30:21 +02:00
|
|
|
const char *cp = timestr;
|
2005-05-26 04:04:14 +02:00
|
|
|
char *bufp = workbuf;
|
|
|
|
const char *bufend = workbuf + buflen;
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Set the character pointed-to by "bufptr" to "newchar", and increment
|
|
|
|
* "bufptr". "end" gives the end of the buffer -- we return an error if
|
|
|
|
* there is no space left to append a character to the buffer. Note that
|
|
|
|
* "bufptr" is evaluated twice.
|
2005-05-26 04:04:14 +02:00
|
|
|
*/
|
|
|
|
#define APPEND_CHAR(bufptr, end, newchar) \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
if (((bufptr) + 1) >= (end)) \
|
|
|
|
return DTERR_BAD_FORMAT; \
|
|
|
|
*(bufptr)++ = newchar; \
|
|
|
|
} while (0)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
/* outer loop through fields */
|
|
|
|
while (*cp != '\0')
|
|
|
|
{
|
2003-08-05 20:30:21 +02:00
|
|
|
/* Ignore spaces between fields */
|
|
|
|
if (isspace((unsigned char) *cp))
|
|
|
|
{
|
|
|
|
cp++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Record start of current field */
|
|
|
|
if (nf >= maxfields)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2005-05-26 04:04:14 +02:00
|
|
|
field[nf] = bufp;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
/* leading digit? then date or time */
|
2001-12-29 19:31:48 +01:00
|
|
|
if (isdigit((unsigned char) *cp))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, *cp++);
|
2000-12-03 21:45:40 +01:00
|
|
|
while (isdigit((unsigned char) *cp))
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, *cp++);
|
2001-12-29 19:31:48 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* time field? */
|
|
|
|
if (*cp == ':')
|
|
|
|
{
|
|
|
|
ftype[nf] = DTK_TIME;
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, *cp++);
|
2000-12-03 21:45:40 +01:00
|
|
|
while (isdigit((unsigned char) *cp) ||
|
|
|
|
(*cp == ':') || (*cp == '.'))
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, *cp++);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
/* date field? allow embedded text month */
|
2005-05-23 19:13:14 +02:00
|
|
|
else if (*cp == '-' || *cp == '/' || *cp == '.')
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2001-12-29 19:31:48 +01:00
|
|
|
/* save delimiting character to use later */
|
2003-08-08 23:42:59 +02:00
|
|
|
char delim = *cp;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, *cp++);
|
2001-09-28 10:09:14 +02:00
|
|
|
/* second field is all digits? then no embedded text month */
|
|
|
|
if (isdigit((unsigned char) *cp))
|
|
|
|
{
|
2003-08-05 20:30:21 +02:00
|
|
|
ftype[nf] = ((delim == '.') ? DTK_NUMBER : DTK_DATE);
|
2001-12-29 19:31:48 +01:00
|
|
|
while (isdigit((unsigned char) *cp))
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, *cp++);
|
2001-12-29 19:31:48 +01:00
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* insist that the delimiters match to get a three-field
|
|
|
|
* date.
|
2002-09-04 22:31:48 +02:00
|
|
|
*/
|
2003-08-05 20:30:21 +02:00
|
|
|
if (*cp == delim)
|
2001-12-29 19:31:48 +01:00
|
|
|
{
|
|
|
|
ftype[nf] = DTK_DATE;
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, *cp++);
|
2005-05-23 19:13:14 +02:00
|
|
|
while (isdigit((unsigned char) *cp) || *cp == delim)
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, *cp++);
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
2001-09-28 10:09:14 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-12-29 19:31:48 +01:00
|
|
|
ftype[nf] = DTK_DATE;
|
2005-05-23 19:13:14 +02:00
|
|
|
while (isalnum((unsigned char) *cp) || *cp == delim)
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
|
2001-09-28 10:09:14 +02:00
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
2002-09-04 22:31:48 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* otherwise, number only and will determine year, month, day, or
|
|
|
|
* concatenated fields later...
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
|
|
|
else
|
|
|
|
ftype[nf] = DTK_NUMBER;
|
|
|
|
}
|
2001-12-29 19:31:48 +01:00
|
|
|
/* Leading decimal point? Then fractional seconds... */
|
|
|
|
else if (*cp == '.')
|
|
|
|
{
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, *cp++);
|
2001-12-29 19:31:48 +01:00
|
|
|
while (isdigit((unsigned char) *cp))
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, *cp++);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
ftype[nf] = DTK_NUMBER;
|
|
|
|
}
|
2002-09-04 22:31:48 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* text? then date string, month, day of week, special, or timezone
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
2000-12-03 21:45:40 +01:00
|
|
|
else if (isalpha((unsigned char) *cp))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2007-11-15 22:14:46 +01:00
|
|
|
bool is_date;
|
2006-10-17 23:03:21 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
ftype[nf] = DTK_STRING;
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
|
2000-12-03 21:45:40 +01:00
|
|
|
while (isalpha((unsigned char) *cp))
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
/*
|
2006-10-17 23:03:21 +02:00
|
|
|
* Dates can have embedded '-', '/', or '.' separators. It could
|
2007-11-15 22:14:46 +01:00
|
|
|
* also be a timezone name containing embedded '/', '+', '-', '_',
|
|
|
|
* or ':' (but '_' or ':' can't be the first punctuation). If the
|
|
|
|
* next character is a digit or '+', we need to check whether what
|
|
|
|
* we have so far is a recognized non-timezone keyword --- if so,
|
|
|
|
* don't believe that this is the start of a timezone.
|
2000-03-16 15:38:42 +01:00
|
|
|
*/
|
2006-10-17 23:03:21 +02:00
|
|
|
is_date = false;
|
2005-05-23 19:13:14 +02:00
|
|
|
if (*cp == '-' || *cp == '/' || *cp == '.')
|
2006-10-17 23:03:21 +02:00
|
|
|
is_date = true;
|
|
|
|
else if (*cp == '+' || isdigit((unsigned char) *cp))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2006-10-17 23:03:21 +02:00
|
|
|
*bufp = '\0'; /* null-terminate current field value */
|
|
|
|
/* we need search only the core token table, not TZ names */
|
|
|
|
if (datebsearch(field[nf], datetktbl, szdatetktbl) == NULL)
|
|
|
|
is_date = true;
|
|
|
|
}
|
|
|
|
if (is_date)
|
|
|
|
{
|
|
|
|
ftype[nf] = DTK_DATE;
|
|
|
|
do
|
2006-06-08 00:32:31 +02:00
|
|
|
{
|
2006-10-17 23:03:21 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
|
|
|
|
} while (*cp == '+' || *cp == '-' ||
|
|
|
|
*cp == '/' || *cp == '_' ||
|
|
|
|
*cp == '.' || *cp == ':' ||
|
|
|
|
isalnum((unsigned char) *cp));
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
}
|
2001-12-29 19:31:48 +01:00
|
|
|
/* sign? then special or numeric timezone */
|
2005-05-23 19:13:14 +02:00
|
|
|
else if (*cp == '+' || *cp == '-')
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, *cp++);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* soak up leading whitespace */
|
2000-12-03 21:45:40 +01:00
|
|
|
while (isspace((unsigned char) *cp))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
cp++;
|
|
|
|
/* numeric timezone? */
|
2008-09-17 00:31:21 +02:00
|
|
|
/* note that "DTK_TZ" could also be a signed float or yyyy-mm */
|
2000-12-03 21:45:40 +01:00
|
|
|
if (isdigit((unsigned char) *cp))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
|
|
|
ftype[nf] = DTK_TZ;
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, *cp++);
|
2000-12-03 21:45:40 +01:00
|
|
|
while (isdigit((unsigned char) *cp) ||
|
2008-09-17 00:31:21 +02:00
|
|
|
*cp == ':' || *cp == '.' || *cp == '-')
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, *cp++);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
2001-12-29 19:31:48 +01:00
|
|
|
/* special? */
|
2000-12-03 21:45:40 +01:00
|
|
|
else if (isalpha((unsigned char) *cp))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
|
|
|
ftype[nf] = DTK_SPECIAL;
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
|
2000-12-03 21:45:40 +01:00
|
|
|
while (isalpha((unsigned char) *cp))
|
2005-05-26 04:04:14 +02:00
|
|
|
APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
2001-12-29 19:31:48 +01:00
|
|
|
/* otherwise something wrong... */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
else
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
2003-08-05 20:30:21 +02:00
|
|
|
/* ignore other punctuation but use as delimiter */
|
2000-12-03 21:45:40 +01:00
|
|
|
else if (ispunct((unsigned char) *cp))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
|
|
|
cp++;
|
|
|
|
continue;
|
|
|
|
}
|
2001-12-29 19:31:48 +01:00
|
|
|
/* otherwise, something is not right... */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
else
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
/* force in a delimiter after each field */
|
2005-05-26 04:04:14 +02:00
|
|
|
*bufp++ = '\0';
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
nf++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*numfields = nf;
|
1997-03-15 00:21:12 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
return 0;
|
2003-08-05 20:30:21 +02:00
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
|
|
|
|
/* DecodeDateTime()
|
|
|
|
* Interpret previously parsed fields for general date and time.
|
2003-08-28 01:29:29 +02:00
|
|
|
* Return 0 if full date, 1 if only time, and negative DTERR code if problems.
|
|
|
|
* (Currently, all callers treat 1 as an error return too.)
|
|
|
|
*
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
* External format(s):
|
|
|
|
* "<weekday> <month>-<day>-<year> <hour>:<minute>:<second>"
|
|
|
|
* "Fri Feb-7-1997 15:23:27"
|
|
|
|
* "Feb-7-1997 15:23:27"
|
|
|
|
* "2-7-1997 15:23:27"
|
|
|
|
* "1997-2-7 15:23:27"
|
|
|
|
* "1997.038 15:23:27" (day of year 1-366)
|
|
|
|
* Also supports input in compact time:
|
|
|
|
* "970207 152327"
|
|
|
|
* "97038 152327"
|
2001-12-29 19:31:48 +01:00
|
|
|
* "20011225T040506.789-07"
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*
|
|
|
|
* Use the system-provided functions to get the current time zone
|
2008-02-17 03:09:32 +01:00
|
|
|
* if not specified in the input string.
|
|
|
|
*
|
|
|
|
* If the date is outside the range of pg_time_t (in practice that could only
|
|
|
|
* happen if pg_time_t is just 32 bits), then assume UTC time zone - thomas
|
|
|
|
* 1997-05-27
|
1997-10-25 07:16:09 +02:00
|
|
|
*/
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
int
|
|
|
|
DecodeDateTime(char **field, int *ftype, int nf,
|
2017-06-21 20:39:04 +02:00
|
|
|
int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp)
|
1997-03-15 00:21:12 +01:00
|
|
|
{
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
int fmask = 0,
|
|
|
|
tmask,
|
|
|
|
type;
|
2005-10-15 04:49:52 +02:00
|
|
|
int ptype = 0; /* "prefix type" for ISO y2001m02d04 format */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
int i;
|
2001-12-29 19:31:48 +01:00
|
|
|
int val;
|
2003-08-28 01:29:29 +02:00
|
|
|
int dterr;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
int mer = HR24;
|
2017-08-16 06:22:32 +02:00
|
|
|
bool haveTextMonth = false;
|
|
|
|
bool isjulian = false;
|
|
|
|
bool is2digits = false;
|
|
|
|
bool bc = false;
|
2006-10-17 23:03:21 +02:00
|
|
|
pg_tz *namedTz = NULL;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
pg_tz *abbrevTz = NULL;
|
|
|
|
pg_tz *valtz;
|
|
|
|
char *abbrev = NULL;
|
2011-08-30 17:34:29 +02:00
|
|
|
struct pg_tm cur_tm;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2003-08-28 01:29:29 +02:00
|
|
|
/*
|
2001-10-25 07:50:21 +02:00
|
|
|
* We'll insist on at least all of the date fields, but initialize the
|
|
|
|
* remaining fields in case they are not set later...
|
2003-08-28 01:29:29 +02:00
|
|
|
*/
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*dtype = DTK_DATE;
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
tm->tm_min = 0;
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
*fsec = 0;
|
2001-12-29 19:31:48 +01:00
|
|
|
/* don't know daylight savings time status apriori */
|
|
|
|
tm->tm_isdst = -1;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
if (tzp != NULL)
|
|
|
|
*tzp = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < nf; i++)
|
|
|
|
{
|
|
|
|
switch (ftype[i])
|
|
|
|
{
|
|
|
|
case DTK_DATE:
|
2014-05-06 18:12:18 +02:00
|
|
|
|
2013-10-02 01:44:53 +02:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Integral julian day with attached time zone? All other
|
|
|
|
* forms with JD will be separated into distinct fields, so we
|
|
|
|
* handle just this case here.
|
2013-10-02 01:44:53 +02:00
|
|
|
*/
|
2001-12-29 19:31:48 +01:00
|
|
|
if (ptype == DTK_JULIAN)
|
2001-09-28 10:09:14 +02:00
|
|
|
{
|
2001-10-25 07:50:21 +02:00
|
|
|
char *cp;
|
2001-12-29 19:31:48 +01:00
|
|
|
int val;
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
if (tzp == NULL)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-09-28 10:09:14 +02:00
|
|
|
|
2005-12-02 03:49:11 +01:00
|
|
|
errno = 0;
|
2016-04-23 22:53:15 +02:00
|
|
|
val = strtoint(field[i], &cp, 10);
|
2010-09-23 05:48:07 +02:00
|
|
|
if (errno == ERANGE || val < 0)
|
2005-12-01 18:56:34 +01:00
|
|
|
return DTERR_FIELD_OVERFLOW;
|
2001-09-28 10:09:14 +02:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
2017-08-16 06:22:32 +02:00
|
|
|
isjulian = true;
|
2010-09-23 05:48:07 +02:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
/* Get the time zone from the end of the string */
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeTimezone(cp, tzp);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2001-09-28 10:09:14 +02:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
tmask = DTK_DATE_M | DTK_TIME_M | DTK_M(TZ);
|
|
|
|
ptype = 0;
|
|
|
|
break;
|
|
|
|
}
|
2014-05-06 18:12:18 +02:00
|
|
|
|
2013-10-02 01:44:53 +02:00
|
|
|
/*
|
2006-10-17 23:03:21 +02:00
|
|
|
* Already have a date? Then this might be a time zone name
|
2007-06-12 17:58:32 +02:00
|
|
|
* with embedded punctuation (e.g. "America/New_York") or a
|
|
|
|
* run-together time with trailing time zone (e.g. hhmmss-zz).
|
2001-12-29 19:31:48 +01:00
|
|
|
* - thomas 2001-12-25
|
2007-06-12 17:58:32 +02:00
|
|
|
*
|
|
|
|
* We consider it a time zone if we already have month & day.
|
|
|
|
* This is to allow the form "mmm dd hhmmss tz year", which
|
|
|
|
* we've historically accepted.
|
2013-10-02 01:44:53 +02:00
|
|
|
*/
|
2007-06-12 17:58:32 +02:00
|
|
|
else if (ptype != 0 ||
|
|
|
|
((fmask & (DTK_M(MONTH) | DTK_M(DAY))) ==
|
|
|
|
(DTK_M(MONTH) | DTK_M(DAY))))
|
2000-03-16 15:38:42 +01:00
|
|
|
{
|
2001-12-29 19:31:48 +01:00
|
|
|
/* No time zone accepted? Then quit... */
|
|
|
|
if (tzp == NULL)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2000-03-16 15:38:42 +01:00
|
|
|
|
2001-12-31 00:09:42 +01:00
|
|
|
if (isdigit((unsigned char) *field[i]) || ptype != 0)
|
2001-12-29 19:31:48 +01:00
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
char *cp;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
2001-12-29 19:40:58 +01:00
|
|
|
if (ptype != 0)
|
|
|
|
{
|
|
|
|
/* Sanity check; should not fail this test */
|
|
|
|
if (ptype != DTK_TIME)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:40:58 +01:00
|
|
|
ptype = 0;
|
|
|
|
}
|
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
|
|
|
* Starts with a digit but we already have a time
|
2005-10-15 04:49:52 +02:00
|
|
|
* field? Then we are in trouble with a date and time
|
|
|
|
* already...
|
2001-12-29 19:31:48 +01:00
|
|
|
*/
|
|
|
|
if ((fmask & DTK_TIME_M) == DTK_TIME_M)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
if ((cp = strchr(field[i], '-')) == NULL)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
/* Get the time zone from the end of the string */
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeTimezone(cp, tzp);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
*cp = '\0';
|
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Then read the rest of the field as a concatenated
|
|
|
|
* time
|
2002-09-04 22:31:48 +02:00
|
|
|
*/
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeNumberField(strlen(field[i]), field[i],
|
|
|
|
fmask,
|
|
|
|
&tmask, tm,
|
|
|
|
fsec, &is2digits);
|
|
|
|
if (dterr < 0)
|
|
|
|
return dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
|
|
|
* modify tmask after returning from
|
|
|
|
* DecodeNumberField()
|
|
|
|
*/
|
2001-12-29 19:31:48 +01:00
|
|
|
tmask |= DTK_M(TZ);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-10-17 23:03:21 +02:00
|
|
|
namedTz = pg_tzset(field[i]);
|
|
|
|
if (!namedTz)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We should return an error code instead of
|
2007-11-15 22:14:46 +01:00
|
|
|
* ereport'ing directly, but then there is no way
|
|
|
|
* to report the bad time zone name.
|
2006-10-17 23:03:21 +02:00
|
|
|
*/
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("time zone \"%s\" not recognized",
|
|
|
|
field[i])));
|
|
|
|
}
|
|
|
|
/* we'll apply the zone setting below */
|
2001-12-29 19:31:48 +01:00
|
|
|
tmask = DTK_M(TZ);
|
|
|
|
}
|
2000-03-16 15:38:42 +01:00
|
|
|
}
|
2003-08-28 01:29:29 +02:00
|
|
|
else
|
|
|
|
{
|
2008-02-26 00:21:01 +01:00
|
|
|
dterr = DecodeDate(field[i], fmask,
|
|
|
|
&tmask, &is2digits, tm);
|
2003-08-28 01:29:29 +02:00
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_TIME:
|
2013-05-29 22:58:43 +02:00
|
|
|
|
2012-08-25 23:44:53 +02:00
|
|
|
/*
|
|
|
|
* This might be an ISO time following a "t" field.
|
|
|
|
*/
|
|
|
|
if (ptype != 0)
|
|
|
|
{
|
|
|
|
/* Sanity check; should not fail this test */
|
|
|
|
if (ptype != DTK_TIME)
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
ptype = 0;
|
|
|
|
}
|
2008-09-10 20:29:41 +02:00
|
|
|
dterr = DecodeTime(field[i], fmask, INTERVAL_FULL_RANGE,
|
|
|
|
&tmask, tm, fsec);
|
2003-08-28 01:29:29 +02:00
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2001-10-25 07:50:21 +02:00
|
|
|
/*
|
|
|
|
* Check upper limit on hours; other limits checked in
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
* DecodeTime()
|
|
|
|
*/
|
2005-10-14 13:47:57 +02:00
|
|
|
/* test for > 24:00:00 */
|
2011-03-12 15:31:18 +01:00
|
|
|
if (tm->tm_hour > HOURS_PER_DAY ||
|
|
|
|
(tm->tm_hour == HOURS_PER_DAY &&
|
2009-05-01 21:29:07 +02:00
|
|
|
(tm->tm_min > 0 || tm->tm_sec > 0 || *fsec > 0)))
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_FIELD_OVERFLOW;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_TZ:
|
2000-03-16 15:38:42 +01:00
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
int tz;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
if (tzp == NULL)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2000-03-16 15:38:42 +01:00
|
|
|
|
2006-10-17 23:03:21 +02:00
|
|
|
dterr = DecodeTimezone(field[i], &tz);
|
2003-08-28 01:29:29 +02:00
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2006-10-17 23:03:21 +02:00
|
|
|
*tzp = tz;
|
|
|
|
tmask = DTK_M(TZ);
|
2000-03-16 15:38:42 +01:00
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_NUMBER:
|
2002-09-04 22:31:48 +02:00
|
|
|
|
2001-10-25 07:50:21 +02:00
|
|
|
/*
|
|
|
|
* Was this an "ISO date" with embedded field labels? An
|
|
|
|
* example is "y2001m02d04" - thomas 2001-02-04
|
2001-09-28 10:09:14 +02:00
|
|
|
*/
|
|
|
|
if (ptype != 0)
|
|
|
|
{
|
2001-10-25 07:50:21 +02:00
|
|
|
char *cp;
|
|
|
|
int val;
|
2001-09-28 10:09:14 +02:00
|
|
|
|
2005-12-02 03:49:11 +01:00
|
|
|
errno = 0;
|
2016-04-23 22:53:15 +02:00
|
|
|
val = strtoint(field[i], &cp, 10);
|
2005-12-01 18:56:34 +01:00
|
|
|
if (errno == ERANGE)
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
2002-09-04 22:31:48 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* only a few kinds are allowed to have an embedded
|
|
|
|
* decimal
|
|
|
|
*/
|
2001-12-29 19:31:48 +01:00
|
|
|
if (*cp == '.')
|
|
|
|
switch (ptype)
|
|
|
|
{
|
|
|
|
case DTK_JULIAN:
|
|
|
|
case DTK_TIME:
|
|
|
|
case DTK_SECOND:
|
|
|
|
break;
|
|
|
|
default:
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (*cp != '\0')
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-09-28 10:09:14 +02:00
|
|
|
|
2001-10-25 07:50:21 +02:00
|
|
|
switch (ptype)
|
|
|
|
{
|
2001-12-29 19:31:48 +01:00
|
|
|
case DTK_YEAR:
|
2001-09-28 10:09:14 +02:00
|
|
|
tm->tm_year = val;
|
2001-12-29 19:31:48 +01:00
|
|
|
tmask = DTK_M(YEAR);
|
2001-09-28 10:09:14 +02:00
|
|
|
break;
|
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
case DTK_MONTH:
|
2002-09-04 22:31:48 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* already have a month and hour? then assume
|
|
|
|
* minutes
|
|
|
|
*/
|
2005-05-23 19:13:14 +02:00
|
|
|
if ((fmask & DTK_M(MONTH)) != 0 &&
|
|
|
|
(fmask & DTK_M(HOUR)) != 0)
|
2001-12-29 19:31:48 +01:00
|
|
|
{
|
|
|
|
tm->tm_min = val;
|
|
|
|
tmask = DTK_M(MINUTE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tm->tm_mon = val;
|
|
|
|
tmask = DTK_M(MONTH);
|
|
|
|
}
|
2001-09-28 10:09:14 +02:00
|
|
|
break;
|
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
case DTK_DAY:
|
2001-09-28 10:09:14 +02:00
|
|
|
tm->tm_mday = val;
|
2001-12-29 19:31:48 +01:00
|
|
|
tmask = DTK_M(DAY);
|
2001-09-28 10:09:14 +02:00
|
|
|
break;
|
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
case DTK_HOUR:
|
2001-09-28 10:09:14 +02:00
|
|
|
tm->tm_hour = val;
|
2001-12-29 19:31:48 +01:00
|
|
|
tmask = DTK_M(HOUR);
|
2001-09-28 10:09:14 +02:00
|
|
|
break;
|
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
case DTK_MINUTE:
|
2001-09-28 10:09:14 +02:00
|
|
|
tm->tm_min = val;
|
2001-12-29 19:31:48 +01:00
|
|
|
tmask = DTK_M(MINUTE);
|
2001-09-28 10:09:14 +02:00
|
|
|
break;
|
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
case DTK_SECOND:
|
2001-09-28 10:09:14 +02:00
|
|
|
tm->tm_sec = val;
|
2001-12-29 19:31:48 +01:00
|
|
|
tmask = DTK_M(SECOND);
|
|
|
|
if (*cp == '.')
|
|
|
|
{
|
2008-11-12 02:36:20 +01:00
|
|
|
dterr = ParseFractionalSecond(cp, fsec);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2007-05-29 06:58:43 +02:00
|
|
|
tmask = DTK_ALL_SECS_M;
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
2001-09-28 10:09:14 +02:00
|
|
|
break;
|
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
case DTK_TZ:
|
|
|
|
tmask = DTK_M(TZ);
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeTimezone(field[i], tzp);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
break;
|
2001-10-25 07:50:21 +02:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
case DTK_JULIAN:
|
2010-09-23 05:48:07 +02:00
|
|
|
/* previous field was a label for "julian date" */
|
|
|
|
if (val < 0)
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
2001-12-29 19:31:48 +01:00
|
|
|
tmask = DTK_DATE_M;
|
2001-09-28 10:09:14 +02:00
|
|
|
j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
2017-08-16 06:22:32 +02:00
|
|
|
isjulian = true;
|
2010-09-23 05:48:07 +02:00
|
|
|
|
2002-04-21 21:52:18 +02:00
|
|
|
/* fractional Julian Day? */
|
2001-12-29 19:31:48 +01:00
|
|
|
if (*cp == '.')
|
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
double time;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
2008-11-12 02:36:20 +01:00
|
|
|
errno = 0;
|
2001-12-29 19:31:48 +01:00
|
|
|
time = strtod(cp, &cp);
|
2008-11-12 02:36:20 +01:00
|
|
|
if (*cp != '\0' || errno != 0)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2008-11-12 02:36:20 +01:00
|
|
|
time *= USECS_PER_DAY;
|
|
|
|
dt2time(time,
|
|
|
|
&tm->tm_hour, &tm->tm_min,
|
|
|
|
&tm->tm_sec, fsec);
|
|
|
|
tmask |= DTK_TIME_M;
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
|
|
|
break;
|
2001-09-28 10:09:14 +02:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
case DTK_TIME:
|
|
|
|
/* previous field was "t" for ISO time */
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeNumberField(strlen(field[i]), field[i],
|
2005-10-15 04:49:52 +02:00
|
|
|
(fmask | DTK_DATE_M),
|
2003-08-28 01:29:29 +02:00
|
|
|
&tmask, tm,
|
|
|
|
fsec, &is2digits);
|
|
|
|
if (dterr < 0)
|
|
|
|
return dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
if (tmask != DTK_TIME_M)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-09-28 10:09:14 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-09-28 10:09:14 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptype = 0;
|
|
|
|
*dtype = DTK_DATE;
|
|
|
|
}
|
2001-12-29 19:31:48 +01:00
|
|
|
else
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
char *cp;
|
|
|
|
int flen;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
flen = strlen(field[i]);
|
|
|
|
cp = strchr(field[i], '.');
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
/* Embedded decimal and no date yet? */
|
2005-05-23 19:13:14 +02:00
|
|
|
if (cp != NULL && !(fmask & DTK_DATE_M))
|
2001-12-29 19:31:48 +01:00
|
|
|
{
|
2008-02-26 00:21:01 +01:00
|
|
|
dterr = DecodeDate(field[i], fmask,
|
|
|
|
&tmask, &is2digits, tm);
|
2003-08-28 01:29:29 +02:00
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
|
|
|
/* embedded decimal and several digits before? */
|
2005-05-23 19:13:14 +02:00
|
|
|
else if (cp != NULL && flen - strlen(cp) > 2)
|
2001-12-29 19:31:48 +01:00
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Interpret as a concatenated date or time Set the
|
|
|
|
* type field to allow decoding other fields later.
|
|
|
|
* Example: 20011223 or 040506
|
2001-12-29 19:31:48 +01:00
|
|
|
*/
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeNumberField(flen, field[i], fmask,
|
|
|
|
&tmask, tm,
|
|
|
|
fsec, &is2digits);
|
|
|
|
if (dterr < 0)
|
|
|
|
return dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
2014-05-06 18:12:18 +02:00
|
|
|
|
2013-10-16 19:22:55 +02:00
|
|
|
/*
|
|
|
|
* Is this a YMD or HMS specification, or a year number?
|
|
|
|
* YMD and HMS are required to be six digits or more, so
|
|
|
|
* if it is 5 digits, it is a year. If it is six or more
|
2018-09-08 21:24:19 +02:00
|
|
|
* digits, we assume it is YMD or HMS unless no date and
|
|
|
|
* no time values have been specified. This forces 6+
|
2014-05-06 18:12:18 +02:00
|
|
|
* digit years to be at the end of the string, or to use
|
2013-10-16 19:22:55 +02:00
|
|
|
* the ISO date specification.
|
|
|
|
*/
|
|
|
|
else if (flen >= 6 && (!(fmask & DTK_DATE_M) ||
|
2014-05-06 18:12:18 +02:00
|
|
|
!(fmask & DTK_TIME_M)))
|
2001-12-29 19:31:48 +01:00
|
|
|
{
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeNumberField(flen, field[i], fmask,
|
|
|
|
&tmask, tm,
|
|
|
|
fsec, &is2digits);
|
|
|
|
if (dterr < 0)
|
|
|
|
return dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
|
|
|
/* otherwise it is a single date/time field... */
|
2003-08-28 01:29:29 +02:00
|
|
|
else
|
|
|
|
{
|
2003-11-16 21:29:16 +01:00
|
|
|
dterr = DecodeNumber(flen, field[i],
|
|
|
|
haveTextMonth, fmask,
|
2003-08-28 01:29:29 +02:00
|
|
|
&tmask, tm,
|
|
|
|
fsec, &is2digits);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_STRING:
|
|
|
|
case DTK_SPECIAL:
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/* timezone abbrevs take precedence over built-in tokens */
|
|
|
|
type = DecodeTimezoneAbbrev(i, field[i], &val, &valtz);
|
|
|
|
if (type == UNKNOWN_FIELD)
|
|
|
|
type = DecodeSpecial(i, field[i], &val);
|
2002-06-11 15:40:53 +02:00
|
|
|
if (type == IGNORE_DTF)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
tmask = DTK_M(type);
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case RESERV:
|
|
|
|
switch (val)
|
|
|
|
{
|
|
|
|
case DTK_NOW:
|
|
|
|
tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ));
|
|
|
|
*dtype = DTK_DATE;
|
2003-02-20 06:24:55 +01:00
|
|
|
GetCurrentTimeUsec(tm, fsec, tzp);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_YESTERDAY:
|
|
|
|
tmask = DTK_DATE_M;
|
|
|
|
*dtype = DTK_DATE;
|
2011-08-30 17:34:29 +02:00
|
|
|
GetCurrentDateTime(&cur_tm);
|
|
|
|
j2date(date2j(cur_tm.tm_year, cur_tm.tm_mon, cur_tm.tm_mday) - 1,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
&tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_TODAY:
|
|
|
|
tmask = DTK_DATE_M;
|
|
|
|
*dtype = DTK_DATE;
|
2011-08-30 17:34:29 +02:00
|
|
|
GetCurrentDateTime(&cur_tm);
|
|
|
|
tm->tm_year = cur_tm.tm_year;
|
|
|
|
tm->tm_mon = cur_tm.tm_mon;
|
|
|
|
tm->tm_mday = cur_tm.tm_mday;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_TOMORROW:
|
|
|
|
tmask = DTK_DATE_M;
|
|
|
|
*dtype = DTK_DATE;
|
2011-08-30 17:34:29 +02:00
|
|
|
GetCurrentDateTime(&cur_tm);
|
|
|
|
j2date(date2j(cur_tm.tm_year, cur_tm.tm_mon, cur_tm.tm_mday) + 1,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
&tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_ZULU:
|
|
|
|
tmask = (DTK_TIME_M | DTK_M(TZ));
|
|
|
|
*dtype = DTK_DATE;
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
tm->tm_min = 0;
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
if (tzp != NULL)
|
|
|
|
*tzp = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
*dtype = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MONTH:
|
2000-04-12 19:17:23 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* already have a (numeric) month? then see if we can
|
|
|
|
* substitute...
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
2005-05-23 19:13:14 +02:00
|
|
|
if ((fmask & DTK_M(MONTH)) && !haveTextMonth &&
|
|
|
|
!(fmask & DTK_M(DAY)) && tm->tm_mon >= 1 &&
|
|
|
|
tm->tm_mon <= 31)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
|
|
|
tm->tm_mday = tm->tm_mon;
|
|
|
|
tmask = DTK_M(DAY);
|
|
|
|
}
|
2017-08-16 06:22:32 +02:00
|
|
|
haveTextMonth = true;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
tm->tm_mon = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTZMOD:
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* daylight savings time modifier (solves "MET DST"
|
|
|
|
* syntax)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
|
|
|
tmask |= DTK_M(DTZ);
|
|
|
|
tm->tm_isdst = 1;
|
|
|
|
if (tzp == NULL)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*tzp -= val;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTZ:
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* set mask for TZ here _or_ check for DTZ later when
|
|
|
|
* getting default timezone
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
|
|
|
tmask |= DTK_M(TZ);
|
|
|
|
tm->tm_isdst = 1;
|
|
|
|
if (tzp == NULL)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*tzp = -val;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TZ:
|
|
|
|
tm->tm_isdst = 0;
|
|
|
|
if (tzp == NULL)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*tzp = -val;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
case DYNTZ:
|
|
|
|
tmask |= DTK_M(TZ);
|
|
|
|
if (tzp == NULL)
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
/* we'll determine the actual offset later */
|
|
|
|
abbrevTz = valtz;
|
|
|
|
abbrev = field[i];
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AMPM:
|
|
|
|
mer = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ADBC:
|
|
|
|
bc = (val == BC);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DOW:
|
|
|
|
tm->tm_wday = val;
|
|
|
|
break;
|
|
|
|
|
2001-09-28 10:09:14 +02:00
|
|
|
case UNITS:
|
|
|
|
tmask = 0;
|
2001-10-20 03:02:22 +02:00
|
|
|
ptype = val;
|
2001-09-28 10:09:14 +02:00
|
|
|
break;
|
|
|
|
|
2002-01-01 03:54:33 +01:00
|
|
|
case ISOTIME:
|
2002-09-04 22:31:48 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* This is a filler field "t" indicating that the next
|
|
|
|
* field is time. Try to verify that this is sensible.
|
2001-12-29 19:31:48 +01:00
|
|
|
*/
|
2001-10-20 03:02:22 +02:00
|
|
|
tmask = 0;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
2003-08-28 01:29:29 +02:00
|
|
|
/* No preceding date? Then quit... */
|
2001-12-29 19:31:48 +01:00
|
|
|
if ((fmask & DTK_DATE_M) != DTK_DATE_M)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
/***
|
|
|
|
* We will need one of the following fields:
|
2002-09-04 22:31:48 +02:00
|
|
|
* DTK_NUMBER should be hhmmss.fff
|
|
|
|
* DTK_TIME should be hh:mm:ss.fff
|
|
|
|
* DTK_DATE should be hhmmss-zz
|
2001-12-29 19:31:48 +01:00
|
|
|
***/
|
2005-05-23 19:13:14 +02:00
|
|
|
if (i >= nf - 1 ||
|
|
|
|
(ftype[i + 1] != DTK_NUMBER &&
|
|
|
|
ftype[i + 1] != DTK_TIME &&
|
|
|
|
ftype[i + 1] != DTK_DATE))
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
ptype = val;
|
2001-09-28 10:09:14 +02:00
|
|
|
break;
|
|
|
|
|
2006-10-18 18:43:14 +02:00
|
|
|
case UNKNOWN_FIELD:
|
2007-11-15 22:14:46 +01:00
|
|
|
|
2006-10-18 18:43:14 +02:00
|
|
|
/*
|
|
|
|
* Before giving up and declaring error, check to see
|
|
|
|
* if it is an all-alpha timezone name.
|
|
|
|
*/
|
|
|
|
namedTz = pg_tzset(field[i]);
|
|
|
|
if (!namedTz)
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
/* we'll apply the zone setting below */
|
|
|
|
tmask = DTK_M(TZ);
|
|
|
|
break;
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
default:
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (tmask & fmask)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
fmask |= tmask;
|
2009-06-11 16:49:15 +02:00
|
|
|
} /* end loop over fields */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2008-02-26 00:21:01 +01:00
|
|
|
/* do final checking/adjustment of Y/M/D fields */
|
2010-09-23 05:48:07 +02:00
|
|
|
dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
|
2008-02-26 00:21:01 +01:00
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2008-02-26 00:21:01 +01:00
|
|
|
/* handle AM/PM */
|
2011-03-12 15:31:18 +01:00
|
|
|
if (mer != HR24 && tm->tm_hour > HOURS_PER_DAY / 2)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_FIELD_OVERFLOW;
|
2011-03-12 15:31:18 +01:00
|
|
|
if (mer == AM && tm->tm_hour == HOURS_PER_DAY / 2)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
tm->tm_hour = 0;
|
2011-03-12 15:31:18 +01:00
|
|
|
else if (mer == PM && tm->tm_hour != HOURS_PER_DAY / 2)
|
|
|
|
tm->tm_hour += HOURS_PER_DAY / 2;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
/* do additional checking for full date specs... */
|
|
|
|
if (*dtype == DTK_DATE)
|
|
|
|
{
|
|
|
|
if ((fmask & DTK_DATE_M) != DTK_DATE_M)
|
2003-08-28 01:29:29 +02:00
|
|
|
{
|
|
|
|
if ((fmask & DTK_TIME_M) == DTK_TIME_M)
|
|
|
|
return 1;
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2006-10-17 23:03:21 +02:00
|
|
|
/*
|
2007-11-15 22:14:46 +01:00
|
|
|
* If we had a full timezone spec, compute the offset (we could not do
|
|
|
|
* it before, because we need the date to resolve DST status).
|
2006-10-17 23:03:21 +02:00
|
|
|
*/
|
|
|
|
if (namedTz != NULL)
|
2006-06-08 00:32:31 +02:00
|
|
|
{
|
2006-10-17 23:03:21 +02:00
|
|
|
/* daylight savings time modifier disallowed with full TZ */
|
|
|
|
if (fmask & DTK_M(DTZMOD))
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
|
|
|
|
*tzp = DetermineTimeZoneOffset(tm, namedTz);
|
2006-06-08 00:32:31 +02:00
|
|
|
}
|
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/*
|
|
|
|
* Likewise, if we had a dynamic timezone abbreviation, resolve it
|
|
|
|
* now.
|
|
|
|
*/
|
|
|
|
if (abbrevTz != NULL)
|
|
|
|
{
|
|
|
|
/* daylight savings time modifier disallowed with dynamic TZ */
|
|
|
|
if (fmask & DTK_M(DTZMOD))
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
|
|
|
|
*tzp = DetermineTimeZoneAbbrevOffset(tm, abbrev, abbrevTz);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* timezone not specified? then use session timezone */
|
2005-05-21 05:38:05 +02:00
|
|
|
if (tzp != NULL && !(fmask & DTK_M(TZ)))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* daylight savings time modifier but no standard timezone? then
|
|
|
|
* error
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
|
|
|
if (fmask & DTK_M(DTZMOD))
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2007-08-04 03:26:54 +02:00
|
|
|
*tzp = DetermineTimeZoneOffset(tm, session_timezone);
|
2001-05-04 00:53:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2003-08-28 01:29:29 +02:00
|
|
|
}
|
2001-05-04 00:53:07 +02:00
|
|
|
|
|
|
|
|
2005-07-23 16:25:34 +02:00
|
|
|
/* DetermineTimeZoneOffset()
|
2002-09-03 21:46:32 +02:00
|
|
|
*
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
* Given a struct pg_tm in which tm_year, tm_mon, tm_mday, tm_hour, tm_min,
|
|
|
|
* and tm_sec fields are set, and a zic-style time zone definition, determine
|
|
|
|
* the applicable GMT offset and daylight-savings status at that time.
|
|
|
|
* Set the struct pg_tm's tm_isdst field accordingly, and return the GMT
|
|
|
|
* offset as the function result.
|
|
|
|
*
|
|
|
|
* Note: if the date is out of the range we can deal with, we return zero
|
|
|
|
* as the GMT offset and set tm_isdst = 0. We don't throw an error here,
|
|
|
|
* though probably some higher-level code will.
|
|
|
|
*/
|
|
|
|
int
|
2017-06-21 20:39:04 +02:00
|
|
|
DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
{
|
|
|
|
pg_time_t t;
|
|
|
|
|
|
|
|
return DetermineTimeZoneOffsetInternal(tm, tzp, &t);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* DetermineTimeZoneOffsetInternal()
|
|
|
|
*
|
|
|
|
* As above, but also return the actual UTC time imputed to the date/time
|
|
|
|
* into *tp.
|
|
|
|
*
|
|
|
|
* In event of an out-of-range date, we punt by returning zero into *tp.
|
|
|
|
* This is okay for the immediate callers but is a good reason for not
|
|
|
|
* exposing this worker function globally.
|
2001-05-04 00:53:07 +02:00
|
|
|
*
|
2004-06-03 04:08:07 +02:00
|
|
|
* Note: it might seem that we should use mktime() for this, but bitter
|
2004-11-01 22:34:44 +01:00
|
|
|
* experience teaches otherwise. This code is much faster than most versions
|
|
|
|
* of mktime(), anyway.
|
2001-05-04 00:53:07 +02:00
|
|
|
*/
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
static int
|
2017-06-21 20:39:04 +02:00
|
|
|
DetermineTimeZoneOffsetInternal(struct pg_tm *tm, pg_tz *tzp, pg_time_t *tp)
|
2001-05-04 00:53:07 +02:00
|
|
|
{
|
2004-11-01 22:34:44 +01:00
|
|
|
int date,
|
2004-06-03 04:08:07 +02:00
|
|
|
sec;
|
|
|
|
pg_time_t day,
|
2004-11-01 22:34:44 +01:00
|
|
|
mytime,
|
|
|
|
prevtime,
|
|
|
|
boundary,
|
|
|
|
beforetime,
|
|
|
|
aftertime;
|
|
|
|
long int before_gmtoff,
|
|
|
|
after_gmtoff;
|
|
|
|
int before_isdst,
|
|
|
|
after_isdst;
|
|
|
|
int res;
|
2001-05-04 00:53:07 +02:00
|
|
|
|
2004-06-03 04:08:07 +02:00
|
|
|
/*
|
|
|
|
* First, generate the pg_time_t value corresponding to the given
|
2005-10-15 04:49:52 +02:00
|
|
|
* y/m/d/h/m/s taken as GMT time. If this overflows, punt and decide the
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
* timezone is GMT. (For a valid Julian date, integer overflow should be
|
|
|
|
* impossible with 64-bit pg_time_t, but let's check for safety.)
|
2004-06-03 04:08:07 +02:00
|
|
|
*/
|
|
|
|
if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
|
|
|
|
goto overflow;
|
|
|
|
date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - UNIX_EPOCH_JDATE;
|
2004-08-30 04:54:42 +02:00
|
|
|
|
2005-10-15 04:49:52 +02:00
|
|
|
day = ((pg_time_t) date) * SECS_PER_DAY;
|
2005-05-23 23:54:02 +02:00
|
|
|
if (day / SECS_PER_DAY != date)
|
2004-06-03 04:08:07 +02:00
|
|
|
goto overflow;
|
2005-07-21 20:06:13 +02:00
|
|
|
sec = tm->tm_sec + (tm->tm_min + tm->tm_hour * MINS_PER_HOUR) * SECS_PER_MINUTE;
|
2004-11-01 22:34:44 +01:00
|
|
|
mytime = day + sec;
|
|
|
|
/* since sec >= 0, overflow could only be from +day to -mytime */
|
|
|
|
if (mytime < 0 && day > 0)
|
2004-06-03 04:08:07 +02:00
|
|
|
goto overflow;
|
2001-05-04 00:53:07 +02:00
|
|
|
|
2004-06-03 04:08:07 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Find the DST time boundary just before or following the target time. We
|
|
|
|
* assume that all zones have GMT offsets less than 24 hours, and that DST
|
|
|
|
* boundaries can't be closer together than 48 hours, so backing up 24
|
|
|
|
* hours and finding the "next" boundary will work.
|
2004-06-03 04:08:07 +02:00
|
|
|
*/
|
2005-07-21 20:06:13 +02:00
|
|
|
prevtime = mytime - SECS_PER_DAY;
|
2004-11-01 22:34:44 +01:00
|
|
|
if (mytime < 0 && prevtime > 0)
|
|
|
|
goto overflow;
|
2004-06-03 04:08:07 +02:00
|
|
|
|
2004-11-01 22:34:44 +01:00
|
|
|
res = pg_next_dst_boundary(&prevtime,
|
|
|
|
&before_gmtoff, &before_isdst,
|
|
|
|
&boundary,
|
2005-04-19 05:13:59 +02:00
|
|
|
&after_gmtoff, &after_isdst,
|
2005-10-15 04:49:52 +02:00
|
|
|
tzp);
|
2004-11-01 22:34:44 +01:00
|
|
|
if (res < 0)
|
|
|
|
goto overflow; /* failure? */
|
|
|
|
|
|
|
|
if (res == 0)
|
|
|
|
{
|
|
|
|
/* Non-DST zone, life is simple */
|
|
|
|
tm->tm_isdst = before_isdst;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*tp = mytime - before_gmtoff;
|
2005-10-15 04:49:52 +02:00
|
|
|
return -(int) before_gmtoff;
|
2004-11-01 22:34:44 +01:00
|
|
|
}
|
2004-06-03 04:08:07 +02:00
|
|
|
|
|
|
|
/*
|
2004-11-01 22:34:44 +01:00
|
|
|
* Form the candidate pg_time_t values with local-time adjustment
|
2004-06-03 04:08:07 +02:00
|
|
|
*/
|
2004-11-01 22:34:44 +01:00
|
|
|
beforetime = mytime - before_gmtoff;
|
2005-05-23 19:13:14 +02:00
|
|
|
if ((before_gmtoff > 0 &&
|
|
|
|
mytime < 0 && beforetime > 0) ||
|
|
|
|
(before_gmtoff <= 0 &&
|
|
|
|
mytime > 0 && beforetime < 0))
|
2004-11-01 22:34:44 +01:00
|
|
|
goto overflow;
|
|
|
|
aftertime = mytime - after_gmtoff;
|
2005-05-23 19:13:14 +02:00
|
|
|
if ((after_gmtoff > 0 &&
|
|
|
|
mytime < 0 && aftertime > 0) ||
|
|
|
|
(after_gmtoff <= 0 &&
|
|
|
|
mytime > 0 && aftertime < 0))
|
2004-06-03 04:08:07 +02:00
|
|
|
goto overflow;
|
|
|
|
|
|
|
|
/*
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
* If both before or both after the boundary time, we know what to do. The
|
|
|
|
* boundary time itself is considered to be after the transition, which
|
|
|
|
* means we can accept aftertime == boundary in the second case.
|
2004-06-03 04:08:07 +02:00
|
|
|
*/
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
if (beforetime < boundary && aftertime < boundary)
|
2004-06-03 04:08:07 +02:00
|
|
|
{
|
2004-11-01 22:34:44 +01:00
|
|
|
tm->tm_isdst = before_isdst;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*tp = beforetime;
|
2005-10-15 04:49:52 +02:00
|
|
|
return -(int) before_gmtoff;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
2004-11-01 22:34:44 +01:00
|
|
|
if (beforetime > boundary && aftertime >= boundary)
|
|
|
|
{
|
|
|
|
tm->tm_isdst = after_isdst;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*tp = aftertime;
|
2005-10-15 04:49:52 +02:00
|
|
|
return -(int) after_gmtoff;
|
2004-11-01 22:34:44 +01:00
|
|
|
}
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-11-01 22:34:44 +01:00
|
|
|
/*
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
* It's an invalid or ambiguous time due to timezone transition. In a
|
|
|
|
* spring-forward transition, prefer the "before" interpretation; in a
|
|
|
|
* fall-back transition, prefer "after". (We used to define and implement
|
|
|
|
* this test as "prefer the standard-time interpretation", but that rule
|
|
|
|
* does not help to resolve the behavior when both times are reported as
|
Update time zone data files to tzdata release 2018e.
DST law changes in North Korea. Redefinition of "daylight savings" in
Ireland, as well as for some past years in Namibia and Czechoslovakia.
Additional historical corrections for Czechoslovakia.
With this change, the IANA database models Irish timekeeping as following
"standard time" in summer, and "daylight savings" in winter, so that the
daylight savings offset is one hour behind standard time not one hour
ahead. This does not change their UTC offset (+1:00 in summer, 0:00 in
winter) nor their timezone abbreviations (IST in summer, GMT in winter),
though now "IST" is more correctly read as "Irish Standard Time" not "Irish
Summer Time". However, the "is_dst" column in the pg_timezone_names view
will now be true in winter and false in summer for the Europe/Dublin zone.
Similar changes were made for Namibia between 1994 and 2017, and for
Czechoslovakia between 1946 and 1947.
So far as I can find, no Postgres internal logic cares about which way
tm_isdst is reported; in particular, since commit b2cbced9e we do not
rely on it to decide how to interpret ambiguous timestamps during DST
transitions. So I don't think this change will affect any Postgres
behavior other than the timezone-view outputs.
Discussion: https://postgr.es/m/30996.1525445902@sss.pgh.pa.us
2018-05-09 19:55:27 +02:00
|
|
|
* standard time; which does happen, eg Europe/Moscow in Oct 2014. Also,
|
|
|
|
* in some zones such as Europe/Dublin, there is widespread confusion
|
|
|
|
* about which time offset is "standard" time, so it's fortunate that our
|
|
|
|
* behavior doesn't depend on that.)
|
2004-11-01 22:34:44 +01:00
|
|
|
*/
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
if (beforetime > aftertime)
|
2004-11-01 22:34:44 +01:00
|
|
|
{
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
tm->tm_isdst = before_isdst;
|
|
|
|
*tp = beforetime;
|
|
|
|
return -(int) before_gmtoff;
|
2004-11-01 22:34:44 +01:00
|
|
|
}
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
tm->tm_isdst = after_isdst;
|
|
|
|
*tp = aftertime;
|
|
|
|
return -(int) after_gmtoff;
|
2004-06-03 04:08:07 +02:00
|
|
|
|
|
|
|
overflow:
|
|
|
|
/* Given date is out of range, so assume UTC */
|
|
|
|
tm->tm_isdst = 0;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*tp = 0;
|
2004-06-03 04:08:07 +02:00
|
|
|
return 0;
|
2001-05-04 00:53:07 +02:00
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/* DetermineTimeZoneAbbrevOffset()
|
|
|
|
*
|
|
|
|
* Determine the GMT offset and DST flag to be attributed to a dynamic
|
|
|
|
* time zone abbreviation, that is one whose meaning has changed over time.
|
|
|
|
* *tm contains the local time at which the meaning should be determined,
|
|
|
|
* and tm->tm_isdst receives the DST flag.
|
|
|
|
*
|
|
|
|
* This differs from the behavior of DetermineTimeZoneOffset() in that a
|
|
|
|
* standard-time or daylight-time abbreviation forces use of the corresponding
|
|
|
|
* GMT offset even when the zone was then in DS or standard time respectively.
|
Don't require dynamic timezone abbreviations to match underlying time zone.
Previously, we threw an error if a dynamic timezone abbreviation did not
match any abbreviation recorded in the referenced IANA time zone entry.
That seemed like a good consistency check at the time, but it turns out
that a number of the abbreviations in the IANA database are things that
Olson and crew made up out of whole cloth. Their current policy is to
remove such names in favor of using simple numeric offsets. Perhaps
unsurprisingly, a lot of these made-up abbreviations have varied in meaning
over time, which meant that our commit b2cbced9e and later changes made
them into dynamic abbreviations. So with newer IANA database versions
that don't mention these abbreviations at all, we fail, as reported in bug
#14307 from Neil Anderson. It's worse than just a few unused-in-the-wild
abbreviations not working, because the pg_timezone_abbrevs view stops
working altogether (since its underlying function tries to compute the
whole view result in one call).
We considered deleting these abbreviations from our abbreviations list, but
the problem with that is that we can't stay ahead of possible future IANA
changes. Instead, let's leave the abbreviations list alone, and treat any
"orphaned" dynamic abbreviation as just meaning the referenced time zone.
It will behave a bit differently than it used to, in that you can't any
longer override the zone's standard vs. daylight rule by using the "wrong"
abbreviation of a pair, but that's better than failing entirely. (Also,
this solution can be interpreted as adding a small new feature, which is
that any abbreviation a user wants can be defined as referencing a time
zone name.)
Back-patch to all supported branches, since this problem affects all
of them when using tzdata 2016f or newer.
Report: <20160902031551.15674.67337@wrigleys.postgresql.org>
Discussion: <6189.1472820913@sss.pgh.pa.us>
2016-09-02 23:29:31 +02:00
|
|
|
* (However, that happens only if we can match the given abbreviation to some
|
|
|
|
* abbreviation that appears in the IANA timezone data. Otherwise, we fall
|
|
|
|
* back to doing DetermineTimeZoneOffset().)
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*/
|
|
|
|
int
|
2017-06-21 20:39:04 +02:00
|
|
|
DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp)
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
{
|
|
|
|
pg_time_t t;
|
Don't require dynamic timezone abbreviations to match underlying time zone.
Previously, we threw an error if a dynamic timezone abbreviation did not
match any abbreviation recorded in the referenced IANA time zone entry.
That seemed like a good consistency check at the time, but it turns out
that a number of the abbreviations in the IANA database are things that
Olson and crew made up out of whole cloth. Their current policy is to
remove such names in favor of using simple numeric offsets. Perhaps
unsurprisingly, a lot of these made-up abbreviations have varied in meaning
over time, which meant that our commit b2cbced9e and later changes made
them into dynamic abbreviations. So with newer IANA database versions
that don't mention these abbreviations at all, we fail, as reported in bug
#14307 from Neil Anderson. It's worse than just a few unused-in-the-wild
abbreviations not working, because the pg_timezone_abbrevs view stops
working altogether (since its underlying function tries to compute the
whole view result in one call).
We considered deleting these abbreviations from our abbreviations list, but
the problem with that is that we can't stay ahead of possible future IANA
changes. Instead, let's leave the abbreviations list alone, and treat any
"orphaned" dynamic abbreviation as just meaning the referenced time zone.
It will behave a bit differently than it used to, in that you can't any
longer override the zone's standard vs. daylight rule by using the "wrong"
abbreviation of a pair, but that's better than failing entirely. (Also,
this solution can be interpreted as adding a small new feature, which is
that any abbreviation a user wants can be defined as referencing a time
zone name.)
Back-patch to all supported branches, since this problem affects all
of them when using tzdata 2016f or newer.
Report: <20160902031551.15674.67337@wrigleys.postgresql.org>
Discussion: <6189.1472820913@sss.pgh.pa.us>
2016-09-02 23:29:31 +02:00
|
|
|
int zone_offset;
|
|
|
|
int abbr_offset;
|
|
|
|
int abbr_isdst;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Compute the UTC time we want to probe at. (In event of overflow, we'll
|
|
|
|
* probe at the epoch, which is a bit random but probably doesn't matter.)
|
|
|
|
*/
|
Don't require dynamic timezone abbreviations to match underlying time zone.
Previously, we threw an error if a dynamic timezone abbreviation did not
match any abbreviation recorded in the referenced IANA time zone entry.
That seemed like a good consistency check at the time, but it turns out
that a number of the abbreviations in the IANA database are things that
Olson and crew made up out of whole cloth. Their current policy is to
remove such names in favor of using simple numeric offsets. Perhaps
unsurprisingly, a lot of these made-up abbreviations have varied in meaning
over time, which meant that our commit b2cbced9e and later changes made
them into dynamic abbreviations. So with newer IANA database versions
that don't mention these abbreviations at all, we fail, as reported in bug
#14307 from Neil Anderson. It's worse than just a few unused-in-the-wild
abbreviations not working, because the pg_timezone_abbrevs view stops
working altogether (since its underlying function tries to compute the
whole view result in one call).
We considered deleting these abbreviations from our abbreviations list, but
the problem with that is that we can't stay ahead of possible future IANA
changes. Instead, let's leave the abbreviations list alone, and treat any
"orphaned" dynamic abbreviation as just meaning the referenced time zone.
It will behave a bit differently than it used to, in that you can't any
longer override the zone's standard vs. daylight rule by using the "wrong"
abbreviation of a pair, but that's better than failing entirely. (Also,
this solution can be interpreted as adding a small new feature, which is
that any abbreviation a user wants can be defined as referencing a time
zone name.)
Back-patch to all supported branches, since this problem affects all
of them when using tzdata 2016f or newer.
Report: <20160902031551.15674.67337@wrigleys.postgresql.org>
Discussion: <6189.1472820913@sss.pgh.pa.us>
2016-09-02 23:29:31 +02:00
|
|
|
zone_offset = DetermineTimeZoneOffsetInternal(tm, tzp, &t);
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
|
Don't require dynamic timezone abbreviations to match underlying time zone.
Previously, we threw an error if a dynamic timezone abbreviation did not
match any abbreviation recorded in the referenced IANA time zone entry.
That seemed like a good consistency check at the time, but it turns out
that a number of the abbreviations in the IANA database are things that
Olson and crew made up out of whole cloth. Their current policy is to
remove such names in favor of using simple numeric offsets. Perhaps
unsurprisingly, a lot of these made-up abbreviations have varied in meaning
over time, which meant that our commit b2cbced9e and later changes made
them into dynamic abbreviations. So with newer IANA database versions
that don't mention these abbreviations at all, we fail, as reported in bug
#14307 from Neil Anderson. It's worse than just a few unused-in-the-wild
abbreviations not working, because the pg_timezone_abbrevs view stops
working altogether (since its underlying function tries to compute the
whole view result in one call).
We considered deleting these abbreviations from our abbreviations list, but
the problem with that is that we can't stay ahead of possible future IANA
changes. Instead, let's leave the abbreviations list alone, and treat any
"orphaned" dynamic abbreviation as just meaning the referenced time zone.
It will behave a bit differently than it used to, in that you can't any
longer override the zone's standard vs. daylight rule by using the "wrong"
abbreviation of a pair, but that's better than failing entirely. (Also,
this solution can be interpreted as adding a small new feature, which is
that any abbreviation a user wants can be defined as referencing a time
zone name.)
Back-patch to all supported branches, since this problem affects all
of them when using tzdata 2016f or newer.
Report: <20160902031551.15674.67337@wrigleys.postgresql.org>
Discussion: <6189.1472820913@sss.pgh.pa.us>
2016-09-02 23:29:31 +02:00
|
|
|
/*
|
|
|
|
* Try to match the abbreviation to something in the zone definition.
|
|
|
|
*/
|
|
|
|
if (DetermineTimeZoneAbbrevOffsetInternal(t, abbr, tzp,
|
|
|
|
&abbr_offset, &abbr_isdst))
|
|
|
|
{
|
|
|
|
/* Success, so use the abbrev-specific answers. */
|
|
|
|
tm->tm_isdst = abbr_isdst;
|
|
|
|
return abbr_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No match, so use the answers we already got from
|
|
|
|
* DetermineTimeZoneOffsetInternal.
|
|
|
|
*/
|
|
|
|
return zone_offset;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* DetermineTimeZoneAbbrevOffsetTS()
|
|
|
|
*
|
|
|
|
* As above but the probe time is specified as a TimestampTz (hence, UTC time),
|
|
|
|
* and DST status is returned into *isdst rather than into tm->tm_isdst.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
DetermineTimeZoneAbbrevOffsetTS(TimestampTz ts, const char *abbr,
|
|
|
|
pg_tz *tzp, int *isdst)
|
|
|
|
{
|
|
|
|
pg_time_t t = timestamptz_to_time_t(ts);
|
Don't require dynamic timezone abbreviations to match underlying time zone.
Previously, we threw an error if a dynamic timezone abbreviation did not
match any abbreviation recorded in the referenced IANA time zone entry.
That seemed like a good consistency check at the time, but it turns out
that a number of the abbreviations in the IANA database are things that
Olson and crew made up out of whole cloth. Their current policy is to
remove such names in favor of using simple numeric offsets. Perhaps
unsurprisingly, a lot of these made-up abbreviations have varied in meaning
over time, which meant that our commit b2cbced9e and later changes made
them into dynamic abbreviations. So with newer IANA database versions
that don't mention these abbreviations at all, we fail, as reported in bug
#14307 from Neil Anderson. It's worse than just a few unused-in-the-wild
abbreviations not working, because the pg_timezone_abbrevs view stops
working altogether (since its underlying function tries to compute the
whole view result in one call).
We considered deleting these abbreviations from our abbreviations list, but
the problem with that is that we can't stay ahead of possible future IANA
changes. Instead, let's leave the abbreviations list alone, and treat any
"orphaned" dynamic abbreviation as just meaning the referenced time zone.
It will behave a bit differently than it used to, in that you can't any
longer override the zone's standard vs. daylight rule by using the "wrong"
abbreviation of a pair, but that's better than failing entirely. (Also,
this solution can be interpreted as adding a small new feature, which is
that any abbreviation a user wants can be defined as referencing a time
zone name.)
Back-patch to all supported branches, since this problem affects all
of them when using tzdata 2016f or newer.
Report: <20160902031551.15674.67337@wrigleys.postgresql.org>
Discussion: <6189.1472820913@sss.pgh.pa.us>
2016-09-02 23:29:31 +02:00
|
|
|
int zone_offset;
|
|
|
|
int abbr_offset;
|
|
|
|
int tz;
|
|
|
|
struct pg_tm tm;
|
|
|
|
fsec_t fsec;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
|
Don't require dynamic timezone abbreviations to match underlying time zone.
Previously, we threw an error if a dynamic timezone abbreviation did not
match any abbreviation recorded in the referenced IANA time zone entry.
That seemed like a good consistency check at the time, but it turns out
that a number of the abbreviations in the IANA database are things that
Olson and crew made up out of whole cloth. Their current policy is to
remove such names in favor of using simple numeric offsets. Perhaps
unsurprisingly, a lot of these made-up abbreviations have varied in meaning
over time, which meant that our commit b2cbced9e and later changes made
them into dynamic abbreviations. So with newer IANA database versions
that don't mention these abbreviations at all, we fail, as reported in bug
#14307 from Neil Anderson. It's worse than just a few unused-in-the-wild
abbreviations not working, because the pg_timezone_abbrevs view stops
working altogether (since its underlying function tries to compute the
whole view result in one call).
We considered deleting these abbreviations from our abbreviations list, but
the problem with that is that we can't stay ahead of possible future IANA
changes. Instead, let's leave the abbreviations list alone, and treat any
"orphaned" dynamic abbreviation as just meaning the referenced time zone.
It will behave a bit differently than it used to, in that you can't any
longer override the zone's standard vs. daylight rule by using the "wrong"
abbreviation of a pair, but that's better than failing entirely. (Also,
this solution can be interpreted as adding a small new feature, which is
that any abbreviation a user wants can be defined as referencing a time
zone name.)
Back-patch to all supported branches, since this problem affects all
of them when using tzdata 2016f or newer.
Report: <20160902031551.15674.67337@wrigleys.postgresql.org>
Discussion: <6189.1472820913@sss.pgh.pa.us>
2016-09-02 23:29:31 +02:00
|
|
|
/*
|
|
|
|
* If the abbrev matches anything in the zone data, this is pretty easy.
|
|
|
|
*/
|
|
|
|
if (DetermineTimeZoneAbbrevOffsetInternal(t, abbr, tzp,
|
|
|
|
&abbr_offset, isdst))
|
|
|
|
return abbr_offset;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Else, break down the timestamp so we can use DetermineTimeZoneOffset.
|
|
|
|
*/
|
|
|
|
if (timestamp2tm(ts, &tz, &tm, &fsec, NULL, tzp) != 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
|
|
|
errmsg("timestamp out of range")));
|
|
|
|
|
|
|
|
zone_offset = DetermineTimeZoneOffset(&tm, tzp);
|
|
|
|
*isdst = tm.tm_isdst;
|
|
|
|
return zone_offset;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* DetermineTimeZoneAbbrevOffsetInternal()
|
|
|
|
*
|
|
|
|
* Workhorse for above two functions: work from a pg_time_t probe instant.
|
Don't require dynamic timezone abbreviations to match underlying time zone.
Previously, we threw an error if a dynamic timezone abbreviation did not
match any abbreviation recorded in the referenced IANA time zone entry.
That seemed like a good consistency check at the time, but it turns out
that a number of the abbreviations in the IANA database are things that
Olson and crew made up out of whole cloth. Their current policy is to
remove such names in favor of using simple numeric offsets. Perhaps
unsurprisingly, a lot of these made-up abbreviations have varied in meaning
over time, which meant that our commit b2cbced9e and later changes made
them into dynamic abbreviations. So with newer IANA database versions
that don't mention these abbreviations at all, we fail, as reported in bug
#14307 from Neil Anderson. It's worse than just a few unused-in-the-wild
abbreviations not working, because the pg_timezone_abbrevs view stops
working altogether (since its underlying function tries to compute the
whole view result in one call).
We considered deleting these abbreviations from our abbreviations list, but
the problem with that is that we can't stay ahead of possible future IANA
changes. Instead, let's leave the abbreviations list alone, and treat any
"orphaned" dynamic abbreviation as just meaning the referenced time zone.
It will behave a bit differently than it used to, in that you can't any
longer override the zone's standard vs. daylight rule by using the "wrong"
abbreviation of a pair, but that's better than failing entirely. (Also,
this solution can be interpreted as adding a small new feature, which is
that any abbreviation a user wants can be defined as referencing a time
zone name.)
Back-patch to all supported branches, since this problem affects all
of them when using tzdata 2016f or newer.
Report: <20160902031551.15674.67337@wrigleys.postgresql.org>
Discussion: <6189.1472820913@sss.pgh.pa.us>
2016-09-02 23:29:31 +02:00
|
|
|
* On success, return GMT offset and DST status into *offset and *isdst.
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*/
|
Don't require dynamic timezone abbreviations to match underlying time zone.
Previously, we threw an error if a dynamic timezone abbreviation did not
match any abbreviation recorded in the referenced IANA time zone entry.
That seemed like a good consistency check at the time, but it turns out
that a number of the abbreviations in the IANA database are things that
Olson and crew made up out of whole cloth. Their current policy is to
remove such names in favor of using simple numeric offsets. Perhaps
unsurprisingly, a lot of these made-up abbreviations have varied in meaning
over time, which meant that our commit b2cbced9e and later changes made
them into dynamic abbreviations. So with newer IANA database versions
that don't mention these abbreviations at all, we fail, as reported in bug
#14307 from Neil Anderson. It's worse than just a few unused-in-the-wild
abbreviations not working, because the pg_timezone_abbrevs view stops
working altogether (since its underlying function tries to compute the
whole view result in one call).
We considered deleting these abbreviations from our abbreviations list, but
the problem with that is that we can't stay ahead of possible future IANA
changes. Instead, let's leave the abbreviations list alone, and treat any
"orphaned" dynamic abbreviation as just meaning the referenced time zone.
It will behave a bit differently than it used to, in that you can't any
longer override the zone's standard vs. daylight rule by using the "wrong"
abbreviation of a pair, but that's better than failing entirely. (Also,
this solution can be interpreted as adding a small new feature, which is
that any abbreviation a user wants can be defined as referencing a time
zone name.)
Back-patch to all supported branches, since this problem affects all
of them when using tzdata 2016f or newer.
Report: <20160902031551.15674.67337@wrigleys.postgresql.org>
Discussion: <6189.1472820913@sss.pgh.pa.us>
2016-09-02 23:29:31 +02:00
|
|
|
static bool
|
|
|
|
DetermineTimeZoneAbbrevOffsetInternal(pg_time_t t, const char *abbr, pg_tz *tzp,
|
|
|
|
int *offset, int *isdst)
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
{
|
|
|
|
char upabbr[TZ_STRLEN_MAX + 1];
|
|
|
|
unsigned char *p;
|
|
|
|
long int gmtoff;
|
|
|
|
|
|
|
|
/* We need to force the abbrev to upper case */
|
|
|
|
strlcpy(upabbr, abbr, sizeof(upabbr));
|
|
|
|
for (p = (unsigned char *) upabbr; *p; p++)
|
|
|
|
*p = pg_toupper(*p);
|
|
|
|
|
|
|
|
/* Look up the abbrev's meaning at this time in this zone */
|
Don't require dynamic timezone abbreviations to match underlying time zone.
Previously, we threw an error if a dynamic timezone abbreviation did not
match any abbreviation recorded in the referenced IANA time zone entry.
That seemed like a good consistency check at the time, but it turns out
that a number of the abbreviations in the IANA database are things that
Olson and crew made up out of whole cloth. Their current policy is to
remove such names in favor of using simple numeric offsets. Perhaps
unsurprisingly, a lot of these made-up abbreviations have varied in meaning
over time, which meant that our commit b2cbced9e and later changes made
them into dynamic abbreviations. So with newer IANA database versions
that don't mention these abbreviations at all, we fail, as reported in bug
#14307 from Neil Anderson. It's worse than just a few unused-in-the-wild
abbreviations not working, because the pg_timezone_abbrevs view stops
working altogether (since its underlying function tries to compute the
whole view result in one call).
We considered deleting these abbreviations from our abbreviations list, but
the problem with that is that we can't stay ahead of possible future IANA
changes. Instead, let's leave the abbreviations list alone, and treat any
"orphaned" dynamic abbreviation as just meaning the referenced time zone.
It will behave a bit differently than it used to, in that you can't any
longer override the zone's standard vs. daylight rule by using the "wrong"
abbreviation of a pair, but that's better than failing entirely. (Also,
this solution can be interpreted as adding a small new feature, which is
that any abbreviation a user wants can be defined as referencing a time
zone name.)
Back-patch to all supported branches, since this problem affects all
of them when using tzdata 2016f or newer.
Report: <20160902031551.15674.67337@wrigleys.postgresql.org>
Discussion: <6189.1472820913@sss.pgh.pa.us>
2016-09-02 23:29:31 +02:00
|
|
|
if (pg_interpret_timezone_abbrev(upabbr,
|
|
|
|
&t,
|
|
|
|
&gmtoff,
|
|
|
|
isdst,
|
|
|
|
tzp))
|
|
|
|
{
|
|
|
|
/* Change sign to agree with DetermineTimeZoneOffset() */
|
|
|
|
*offset = (int) -gmtoff;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* DecodeTimeOnly()
|
|
|
|
* Interpret parsed string as time fields only.
|
2003-08-28 01:29:29 +02:00
|
|
|
* Returns 0 if successful, DTERR code if bogus input detected.
|
|
|
|
*
|
2000-03-15 00:06:59 +01:00
|
|
|
* Note that support for time zone is here for
|
2013-04-20 17:04:41 +02:00
|
|
|
* SQL TIME WITH TIME ZONE, but it reveals
|
|
|
|
* bogosity with SQL date/time standards, since
|
2000-03-15 00:06:59 +01:00
|
|
|
* we must infer a time zone from current time.
|
|
|
|
* - thomas 2000-03-10
|
2001-12-29 19:31:48 +01:00
|
|
|
* Allow specifying date to get a better time zone,
|
|
|
|
* if time zones are allowed. - thomas 2001-12-26
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
*/
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
int
|
2000-03-15 00:06:59 +01:00
|
|
|
DecodeTimeOnly(char **field, int *ftype, int nf,
|
2017-06-21 20:39:04 +02:00
|
|
|
int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp)
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
{
|
2001-12-29 19:31:48 +01:00
|
|
|
int fmask = 0,
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
tmask,
|
|
|
|
type;
|
2002-09-04 22:31:48 +02:00
|
|
|
int ptype = 0; /* "prefix type" for ISO h04mm05s06 format */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
int i;
|
2001-12-29 19:31:48 +01:00
|
|
|
int val;
|
2003-08-28 01:29:29 +02:00
|
|
|
int dterr;
|
2017-08-16 06:22:32 +02:00
|
|
|
bool isjulian = false;
|
|
|
|
bool is2digits = false;
|
|
|
|
bool bc = false;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
int mer = HR24;
|
2006-10-17 23:03:21 +02:00
|
|
|
pg_tz *namedTz = NULL;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
pg_tz *abbrevTz = NULL;
|
|
|
|
char *abbrev = NULL;
|
|
|
|
pg_tz *valtz;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
*dtype = DTK_TIME;
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
tm->tm_min = 0;
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
*fsec = 0;
|
2001-12-29 19:31:48 +01:00
|
|
|
/* don't know daylight savings time status apriori */
|
|
|
|
tm->tm_isdst = -1;
|
|
|
|
|
2000-03-15 00:06:59 +01:00
|
|
|
if (tzp != NULL)
|
|
|
|
*tzp = 0;
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
for (i = 0; i < nf; i++)
|
|
|
|
{
|
|
|
|
switch (ftype[i])
|
|
|
|
{
|
2000-03-16 15:38:42 +01:00
|
|
|
case DTK_DATE:
|
2002-09-04 22:31:48 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Time zone not allowed? Then should not accept dates or time
|
|
|
|
* zones no matter what else!
|
2000-03-16 15:38:42 +01:00
|
|
|
*/
|
2001-12-29 19:31:48 +01:00
|
|
|
if (tzp == NULL)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2000-03-16 15:38:42 +01:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
/* Under limited circumstances, we will accept a date... */
|
2005-05-23 19:13:14 +02:00
|
|
|
if (i == 0 && nf >= 2 &&
|
|
|
|
(ftype[nf - 1] == DTK_DATE || ftype[1] == DTK_TIME))
|
2001-12-29 19:31:48 +01:00
|
|
|
{
|
2008-02-26 00:21:01 +01:00
|
|
|
dterr = DecodeDate(field[i], fmask,
|
|
|
|
&tmask, &is2digits, tm);
|
2003-08-28 01:29:29 +02:00
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
|
|
|
/* otherwise, this is a time and/or time zone */
|
|
|
|
else
|
|
|
|
{
|
2001-12-31 00:09:42 +01:00
|
|
|
if (isdigit((unsigned char) *field[i]))
|
2001-12-29 19:31:48 +01:00
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
char *cp;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
|
|
|
* Starts with a digit but we already have a time
|
2005-10-15 04:49:52 +02:00
|
|
|
* field? Then we are in trouble with time already...
|
2001-12-29 19:31:48 +01:00
|
|
|
*/
|
|
|
|
if ((fmask & DTK_TIME_M) == DTK_TIME_M)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Should not get here and fail. Sanity check only...
|
2002-09-04 22:31:48 +02:00
|
|
|
*/
|
2001-12-29 19:31:48 +01:00
|
|
|
if ((cp = strchr(field[i], '-')) == NULL)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
/* Get the time zone from the end of the string */
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeTimezone(cp, tzp);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
*cp = '\0';
|
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Then read the rest of the field as a concatenated
|
|
|
|
* time
|
2002-09-04 22:31:48 +02:00
|
|
|
*/
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeNumberField(strlen(field[i]), field[i],
|
|
|
|
(fmask | DTK_DATE_M),
|
|
|
|
&tmask, tm,
|
|
|
|
fsec, &is2digits);
|
|
|
|
if (dterr < 0)
|
|
|
|
return dterr;
|
|
|
|
ftype[i] = dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
tmask |= DTK_M(TZ);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-10-17 23:03:21 +02:00
|
|
|
namedTz = pg_tzset(field[i]);
|
|
|
|
if (!namedTz)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We should return an error code instead of
|
2007-11-15 22:14:46 +01:00
|
|
|
* ereport'ing directly, but then there is no way
|
|
|
|
* to report the bad time zone name.
|
2006-10-17 23:03:21 +02:00
|
|
|
*/
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("time zone \"%s\" not recognized",
|
|
|
|
field[i])));
|
|
|
|
}
|
|
|
|
/* we'll apply the zone setting below */
|
2001-12-29 19:31:48 +01:00
|
|
|
ftype[i] = DTK_TZ;
|
|
|
|
tmask = DTK_M(TZ);
|
|
|
|
}
|
|
|
|
}
|
2000-03-16 15:38:42 +01:00
|
|
|
break;
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
case DTK_TIME:
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeTime(field[i], (fmask | DTK_DATE_M),
|
2008-09-10 20:29:41 +02:00
|
|
|
INTERVAL_FULL_RANGE,
|
2003-08-28 01:29:29 +02:00
|
|
|
&tmask, tm, fsec);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
2000-03-15 00:06:59 +01:00
|
|
|
case DTK_TZ:
|
2000-03-16 15:38:42 +01:00
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
int tz;
|
2000-03-16 15:38:42 +01:00
|
|
|
|
2003-08-28 01:29:29 +02:00
|
|
|
if (tzp == NULL)
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
|
2006-10-17 23:03:21 +02:00
|
|
|
dterr = DecodeTimezone(field[i], &tz);
|
2003-08-28 01:29:29 +02:00
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2006-10-17 23:03:21 +02:00
|
|
|
*tzp = tz;
|
|
|
|
tmask = DTK_M(TZ);
|
2000-03-16 15:38:42 +01:00
|
|
|
}
|
2000-03-15 00:06:59 +01:00
|
|
|
break;
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
case DTK_NUMBER:
|
2002-09-04 22:31:48 +02:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
/*
|
|
|
|
* Was this an "ISO time" with embedded field labels? An
|
2019-07-22 03:01:50 +02:00
|
|
|
* example is "h04mm05s06" - thomas 2001-02-04
|
2001-12-29 19:31:48 +01:00
|
|
|
*/
|
|
|
|
if (ptype != 0)
|
|
|
|
{
|
|
|
|
char *cp;
|
|
|
|
int val;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
/* Only accept a date under limited circumstances */
|
|
|
|
switch (ptype)
|
|
|
|
{
|
|
|
|
case DTK_JULIAN:
|
|
|
|
case DTK_YEAR:
|
|
|
|
case DTK_MONTH:
|
|
|
|
case DTK_DAY:
|
|
|
|
if (tzp == NULL)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-12-02 03:49:11 +01:00
|
|
|
errno = 0;
|
2016-04-23 22:53:15 +02:00
|
|
|
val = strtoint(field[i], &cp, 10);
|
2005-12-01 18:56:34 +01:00
|
|
|
if (errno == ERANGE)
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
2002-09-04 22:31:48 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* only a few kinds are allowed to have an embedded
|
|
|
|
* decimal
|
|
|
|
*/
|
2001-12-29 19:31:48 +01:00
|
|
|
if (*cp == '.')
|
|
|
|
switch (ptype)
|
|
|
|
{
|
|
|
|
case DTK_JULIAN:
|
|
|
|
case DTK_TIME:
|
|
|
|
case DTK_SECOND:
|
|
|
|
break;
|
|
|
|
default:
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (*cp != '\0')
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
switch (ptype)
|
|
|
|
{
|
|
|
|
case DTK_YEAR:
|
|
|
|
tm->tm_year = val;
|
|
|
|
tmask = DTK_M(YEAR);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_MONTH:
|
2002-09-04 22:31:48 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* already have a month and hour? then assume
|
|
|
|
* minutes
|
|
|
|
*/
|
2005-05-23 19:13:14 +02:00
|
|
|
if ((fmask & DTK_M(MONTH)) != 0 &&
|
|
|
|
(fmask & DTK_M(HOUR)) != 0)
|
2001-12-29 19:31:48 +01:00
|
|
|
{
|
|
|
|
tm->tm_min = val;
|
|
|
|
tmask = DTK_M(MINUTE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tm->tm_mon = val;
|
|
|
|
tmask = DTK_M(MONTH);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_DAY:
|
|
|
|
tm->tm_mday = val;
|
|
|
|
tmask = DTK_M(DAY);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_HOUR:
|
|
|
|
tm->tm_hour = val;
|
|
|
|
tmask = DTK_M(HOUR);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_MINUTE:
|
|
|
|
tm->tm_min = val;
|
|
|
|
tmask = DTK_M(MINUTE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_SECOND:
|
|
|
|
tm->tm_sec = val;
|
|
|
|
tmask = DTK_M(SECOND);
|
|
|
|
if (*cp == '.')
|
|
|
|
{
|
2008-11-12 02:36:20 +01:00
|
|
|
dterr = ParseFractionalSecond(cp, fsec);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2007-05-29 06:58:43 +02:00
|
|
|
tmask = DTK_ALL_SECS_M;
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_TZ:
|
|
|
|
tmask = DTK_M(TZ);
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeTimezone(field[i], tzp);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_JULIAN:
|
2010-09-23 05:48:07 +02:00
|
|
|
/* previous field was a label for "julian date" */
|
|
|
|
if (val < 0)
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
2001-12-29 19:31:48 +01:00
|
|
|
tmask = DTK_DATE_M;
|
|
|
|
j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
2017-08-16 06:22:32 +02:00
|
|
|
isjulian = true;
|
2010-09-23 05:48:07 +02:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
if (*cp == '.')
|
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
double time;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
2008-11-12 02:36:20 +01:00
|
|
|
errno = 0;
|
2001-12-29 19:31:48 +01:00
|
|
|
time = strtod(cp, &cp);
|
2008-11-12 02:36:20 +01:00
|
|
|
if (*cp != '\0' || errno != 0)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2008-11-12 02:36:20 +01:00
|
|
|
time *= USECS_PER_DAY;
|
|
|
|
dt2time(time,
|
|
|
|
&tm->tm_hour, &tm->tm_min,
|
|
|
|
&tm->tm_sec, fsec);
|
|
|
|
tmask |= DTK_TIME_M;
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_TIME:
|
|
|
|
/* previous field was "t" for ISO time */
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeNumberField(strlen(field[i]), field[i],
|
2005-10-15 04:49:52 +02:00
|
|
|
(fmask | DTK_DATE_M),
|
2003-08-28 01:29:29 +02:00
|
|
|
&tmask, tm,
|
|
|
|
fsec, &is2digits);
|
|
|
|
if (dterr < 0)
|
|
|
|
return dterr;
|
|
|
|
ftype[i] = dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
if (tmask != DTK_TIME_M)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptype = 0;
|
|
|
|
*dtype = DTK_DATE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
char *cp;
|
|
|
|
int flen;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
flen = strlen(field[i]);
|
|
|
|
cp = strchr(field[i], '.');
|
|
|
|
|
|
|
|
/* Embedded decimal? */
|
|
|
|
if (cp != NULL)
|
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
|
|
|
* Under limited circumstances, we will accept a
|
|
|
|
* date...
|
|
|
|
*/
|
2005-05-23 19:13:14 +02:00
|
|
|
if (i == 0 && nf >= 2 && ftype[nf - 1] == DTK_DATE)
|
2001-12-29 19:31:48 +01:00
|
|
|
{
|
2008-02-26 00:21:01 +01:00
|
|
|
dterr = DecodeDate(field[i], fmask,
|
|
|
|
&tmask, &is2digits, tm);
|
2003-08-28 01:29:29 +02:00
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
|
|
|
/* embedded decimal and several digits before? */
|
2005-05-23 19:13:14 +02:00
|
|
|
else if (flen - strlen(cp) > 2)
|
2001-12-29 19:31:48 +01:00
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Interpret as a concatenated date or time Set
|
|
|
|
* the type field to allow decoding other fields
|
|
|
|
* later. Example: 20011223 or 040506
|
2001-12-29 19:31:48 +01:00
|
|
|
*/
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeNumberField(flen, field[i],
|
2005-10-15 04:49:52 +02:00
|
|
|
(fmask | DTK_DATE_M),
|
2003-08-28 01:29:29 +02:00
|
|
|
&tmask, tm,
|
|
|
|
fsec, &is2digits);
|
|
|
|
if (dterr < 0)
|
|
|
|
return dterr;
|
|
|
|
ftype[i] = dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
|
|
|
else
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
|
|
|
else if (flen > 4)
|
|
|
|
{
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeNumberField(flen, field[i],
|
|
|
|
(fmask | DTK_DATE_M),
|
|
|
|
&tmask, tm,
|
|
|
|
fsec, &is2digits);
|
|
|
|
if (dterr < 0)
|
|
|
|
return dterr;
|
|
|
|
ftype[i] = dterr;
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
|
|
|
/* otherwise it is a single date/time field... */
|
2003-08-28 01:29:29 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
dterr = DecodeNumber(flen, field[i],
|
2017-08-16 06:22:32 +02:00
|
|
|
false,
|
2003-08-28 01:29:29 +02:00
|
|
|
(fmask | DTK_DATE_M),
|
|
|
|
&tmask, tm,
|
|
|
|
fsec, &is2digits);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
|
|
|
}
|
2001-12-29 19:31:48 +01:00
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_STRING:
|
|
|
|
case DTK_SPECIAL:
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/* timezone abbrevs take precedence over built-in tokens */
|
|
|
|
type = DecodeTimezoneAbbrev(i, field[i], &val, &valtz);
|
|
|
|
if (type == UNKNOWN_FIELD)
|
|
|
|
type = DecodeSpecial(i, field[i], &val);
|
2002-06-11 15:40:53 +02:00
|
|
|
if (type == IGNORE_DTF)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
tmask = DTK_M(type);
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case RESERV:
|
|
|
|
switch (val)
|
|
|
|
{
|
|
|
|
case DTK_NOW:
|
|
|
|
tmask = DTK_TIME_M;
|
|
|
|
*dtype = DTK_TIME;
|
2003-02-20 06:24:55 +01:00
|
|
|
GetCurrentTimeUsec(tm, fsec, NULL);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_ZULU:
|
|
|
|
tmask = (DTK_TIME_M | DTK_M(TZ));
|
|
|
|
*dtype = DTK_TIME;
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
tm->tm_min = 0;
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
tm->tm_isdst = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2000-03-16 15:38:42 +01:00
|
|
|
case DTZMOD:
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* daylight savings time modifier (solves "MET DST"
|
|
|
|
* syntax)
|
2000-03-16 15:38:42 +01:00
|
|
|
*/
|
|
|
|
tmask |= DTK_M(DTZ);
|
|
|
|
tm->tm_isdst = 1;
|
|
|
|
if (tzp == NULL)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*tzp -= val;
|
2000-03-16 15:38:42 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTZ:
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* set mask for TZ here _or_ check for DTZ later when
|
|
|
|
* getting default timezone
|
2000-03-16 15:38:42 +01:00
|
|
|
*/
|
|
|
|
tmask |= DTK_M(TZ);
|
|
|
|
tm->tm_isdst = 1;
|
|
|
|
if (tzp == NULL)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*tzp = -val;
|
2000-03-16 15:38:42 +01:00
|
|
|
ftype[i] = DTK_TZ;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TZ:
|
|
|
|
tm->tm_isdst = 0;
|
|
|
|
if (tzp == NULL)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*tzp = -val;
|
2000-03-16 15:38:42 +01:00
|
|
|
ftype[i] = DTK_TZ;
|
|
|
|
break;
|
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
case DYNTZ:
|
|
|
|
tmask |= DTK_M(TZ);
|
|
|
|
if (tzp == NULL)
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
/* we'll determine the actual offset later */
|
|
|
|
abbrevTz = valtz;
|
|
|
|
abbrev = field[i];
|
|
|
|
ftype[i] = DTK_TZ;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AMPM:
|
|
|
|
mer = val;
|
|
|
|
break;
|
|
|
|
|
2008-02-26 00:21:01 +01:00
|
|
|
case ADBC:
|
|
|
|
bc = (val == BC);
|
|
|
|
break;
|
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
case UNITS:
|
|
|
|
tmask = 0;
|
|
|
|
ptype = val;
|
|
|
|
break;
|
|
|
|
|
2002-01-01 03:54:33 +01:00
|
|
|
case ISOTIME:
|
2001-12-29 19:31:48 +01:00
|
|
|
tmask = 0;
|
|
|
|
|
|
|
|
/***
|
|
|
|
* We will need one of the following fields:
|
2002-09-04 22:31:48 +02:00
|
|
|
* DTK_NUMBER should be hhmmss.fff
|
|
|
|
* DTK_TIME should be hh:mm:ss.fff
|
|
|
|
* DTK_DATE should be hhmmss-zz
|
2001-12-29 19:31:48 +01:00
|
|
|
***/
|
2005-05-23 19:13:14 +02:00
|
|
|
if (i >= nf - 1 ||
|
|
|
|
(ftype[i + 1] != DTK_NUMBER &&
|
|
|
|
ftype[i + 1] != DTK_TIME &&
|
|
|
|
ftype[i + 1] != DTK_DATE))
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
ptype = val;
|
|
|
|
break;
|
|
|
|
|
2006-10-18 18:43:14 +02:00
|
|
|
case UNKNOWN_FIELD:
|
2007-11-15 22:14:46 +01:00
|
|
|
|
2006-10-18 18:43:14 +02:00
|
|
|
/*
|
|
|
|
* Before giving up and declaring error, check to see
|
|
|
|
* if it is an all-alpha timezone name.
|
|
|
|
*/
|
|
|
|
namedTz = pg_tzset(field[i]);
|
|
|
|
if (!namedTz)
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
/* we'll apply the zone setting below */
|
|
|
|
tmask = DTK_M(TZ);
|
|
|
|
break;
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
default:
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (tmask & fmask)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
fmask |= tmask;
|
2009-06-11 16:49:15 +02:00
|
|
|
} /* end loop over fields */
|
2008-02-26 00:21:01 +01:00
|
|
|
|
|
|
|
/* do final checking/adjustment of Y/M/D fields */
|
2010-09-23 05:48:07 +02:00
|
|
|
dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
|
2008-02-26 00:21:01 +01:00
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
1997-05-16 09:19:50 +02:00
|
|
|
|
2008-02-26 00:21:01 +01:00
|
|
|
/* handle AM/PM */
|
2011-03-12 15:31:18 +01:00
|
|
|
if (mer != HR24 && tm->tm_hour > HOURS_PER_DAY / 2)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_FIELD_OVERFLOW;
|
2011-03-12 15:31:18 +01:00
|
|
|
if (mer == AM && tm->tm_hour == HOURS_PER_DAY / 2)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
tm->tm_hour = 0;
|
2011-03-12 15:31:18 +01:00
|
|
|
else if (mer == PM && tm->tm_hour != HOURS_PER_DAY / 2)
|
|
|
|
tm->tm_hour += HOURS_PER_DAY / 2;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2014-03-04 19:09:43 +01:00
|
|
|
/*
|
|
|
|
* This should match the checks in make_timestamp_internal
|
|
|
|
*/
|
2011-03-12 15:31:18 +01:00
|
|
|
if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > MINS_PER_HOUR - 1 ||
|
|
|
|
tm->tm_sec < 0 || tm->tm_sec > SECS_PER_MINUTE ||
|
|
|
|
tm->tm_hour > HOURS_PER_DAY ||
|
2009-06-11 16:49:15 +02:00
|
|
|
/* test for > 24:00:00 */
|
2011-03-12 15:31:18 +01:00
|
|
|
(tm->tm_hour == HOURS_PER_DAY &&
|
2009-05-01 21:29:07 +02:00
|
|
|
(tm->tm_min > 0 || tm->tm_sec > 0 || *fsec > 0)) ||
|
2017-02-23 20:04:43 +01:00
|
|
|
*fsec < INT64CONST(0) || *fsec > USECS_PER_SEC)
|
2006-10-17 23:03:21 +02:00
|
|
|
return DTERR_FIELD_OVERFLOW;
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
if ((fmask & DTK_TIME_M) != DTK_TIME_M)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
|
2006-10-17 23:03:21 +02:00
|
|
|
/*
|
2007-11-15 22:14:46 +01:00
|
|
|
* If we had a full timezone spec, compute the offset (we could not do it
|
|
|
|
* before, because we may need the date to resolve DST status).
|
2006-10-17 23:03:21 +02:00
|
|
|
*/
|
|
|
|
if (namedTz != NULL)
|
|
|
|
{
|
2006-10-18 18:43:14 +02:00
|
|
|
long int gmtoff;
|
|
|
|
|
2006-10-17 23:03:21 +02:00
|
|
|
/* daylight savings time modifier disallowed with full TZ */
|
|
|
|
if (fmask & DTK_M(DTZMOD))
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
|
2006-10-18 18:43:14 +02:00
|
|
|
/* if non-DST zone, we do not need to know the date */
|
|
|
|
if (pg_get_timezone_offset(namedTz, &gmtoff))
|
|
|
|
{
|
|
|
|
*tzp = -(int) gmtoff;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* a date has to be specified */
|
|
|
|
if ((fmask & DTK_DATE_M) != DTK_DATE_M)
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
*tzp = DetermineTimeZoneOffset(tm, namedTz);
|
|
|
|
}
|
2006-10-17 23:03:21 +02:00
|
|
|
}
|
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/*
|
|
|
|
* Likewise, if we had a dynamic timezone abbreviation, resolve it now.
|
|
|
|
*/
|
|
|
|
if (abbrevTz != NULL)
|
|
|
|
{
|
|
|
|
struct pg_tm tt,
|
|
|
|
*tmp = &tt;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* daylight savings time modifier but no standard timezone? then error
|
|
|
|
*/
|
|
|
|
if (fmask & DTK_M(DTZMOD))
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
|
|
|
|
if ((fmask & DTK_DATE_M) == 0)
|
|
|
|
GetCurrentDateTime(tmp);
|
|
|
|
else
|
|
|
|
{
|
2019-08-07 11:16:31 +02:00
|
|
|
/* a date has to be specified */
|
|
|
|
if ((fmask & DTK_DATE_M) != DTK_DATE_M)
|
|
|
|
return DTERR_BAD_FORMAT;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
tmp->tm_year = tm->tm_year;
|
|
|
|
tmp->tm_mon = tm->tm_mon;
|
|
|
|
tmp->tm_mday = tm->tm_mday;
|
|
|
|
}
|
|
|
|
tmp->tm_hour = tm->tm_hour;
|
|
|
|
tmp->tm_min = tm->tm_min;
|
|
|
|
tmp->tm_sec = tm->tm_sec;
|
|
|
|
*tzp = DetermineTimeZoneAbbrevOffset(tmp, abbrev, abbrevTz);
|
|
|
|
tm->tm_isdst = tmp->tm_isdst;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* timezone not specified? then use session timezone */
|
2005-05-21 05:38:05 +02:00
|
|
|
if (tzp != NULL && !(fmask & DTK_M(TZ)))
|
2000-03-15 00:06:59 +01:00
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
struct pg_tm tt,
|
2000-04-12 19:17:23 +02:00
|
|
|
*tmp = &tt;
|
2000-03-15 00:06:59 +01:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* daylight savings time modifier but no standard timezone? then error
|
2000-03-15 00:06:59 +01:00
|
|
|
*/
|
|
|
|
if (fmask & DTK_M(DTZMOD))
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2000-03-15 00:06:59 +01:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
if ((fmask & DTK_DATE_M) == 0)
|
2002-06-11 15:40:53 +02:00
|
|
|
GetCurrentDateTime(tmp);
|
2001-12-29 19:31:48 +01:00
|
|
|
else
|
|
|
|
{
|
2019-08-07 11:16:31 +02:00
|
|
|
/* a date has to be specified */
|
|
|
|
if ((fmask & DTK_DATE_M) != DTK_DATE_M)
|
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
tmp->tm_year = tm->tm_year;
|
|
|
|
tmp->tm_mon = tm->tm_mon;
|
|
|
|
tmp->tm_mday = tm->tm_mday;
|
|
|
|
}
|
2000-03-15 00:06:59 +01:00
|
|
|
tmp->tm_hour = tm->tm_hour;
|
|
|
|
tmp->tm_min = tm->tm_min;
|
|
|
|
tmp->tm_sec = tm->tm_sec;
|
2007-08-04 03:26:54 +02:00
|
|
|
*tzp = DetermineTimeZoneOffset(tmp, session_timezone);
|
2000-03-15 00:06:59 +01:00
|
|
|
tm->tm_isdst = tmp->tm_isdst;
|
|
|
|
}
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
return 0;
|
2003-08-28 01:29:29 +02:00
|
|
|
}
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* DecodeDate()
|
|
|
|
* Decode date string which includes delimiters.
|
2003-08-28 01:29:29 +02:00
|
|
|
* Return 0 if okay, a DTERR code if not.
|
|
|
|
*
|
2008-02-26 00:21:01 +01:00
|
|
|
* str: field to be parsed
|
|
|
|
* fmask: bitmask for field types already seen
|
|
|
|
* *tmask: receives bitmask for fields found here
|
2017-08-16 06:22:32 +02:00
|
|
|
* *is2digits: set to true if we find 2-digit year
|
2008-02-26 00:21:01 +01:00
|
|
|
* *tm: field values are stored into appropriate members of this struct
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
*/
|
2000-06-09 00:38:00 +02:00
|
|
|
static int
|
2008-02-26 00:21:01 +01:00
|
|
|
DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
|
2017-06-21 20:39:04 +02:00
|
|
|
struct pg_tm *tm)
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
{
|
2002-04-21 21:52:18 +02:00
|
|
|
fsec_t fsec;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
int nf = 0;
|
|
|
|
int i,
|
|
|
|
len;
|
2003-08-28 01:29:29 +02:00
|
|
|
int dterr;
|
2017-08-16 06:22:32 +02:00
|
|
|
bool haveTextMonth = false;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
int type,
|
|
|
|
val,
|
|
|
|
dmask = 0;
|
|
|
|
char *field[MAXDATEFIELDS];
|
|
|
|
|
2008-02-26 00:21:01 +01:00
|
|
|
*tmask = 0;
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* parse this string... */
|
2005-05-23 19:13:14 +02:00
|
|
|
while (*str != '\0' && nf < MAXDATEFIELDS)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
|
|
|
/* skip field separators */
|
2012-10-02 09:43:48 +02:00
|
|
|
while (*str != '\0' && !isalnum((unsigned char) *str))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
str++;
|
|
|
|
|
2012-10-02 09:43:48 +02:00
|
|
|
if (*str == '\0')
|
2013-05-29 22:58:43 +02:00
|
|
|
return DTERR_BAD_FORMAT; /* end of string after separator */
|
2012-10-02 09:43:48 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
field[nf] = str;
|
2000-12-03 21:45:40 +01:00
|
|
|
if (isdigit((unsigned char) *str))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2000-12-03 21:45:40 +01:00
|
|
|
while (isdigit((unsigned char) *str))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
str++;
|
|
|
|
}
|
2000-12-03 21:45:40 +01:00
|
|
|
else if (isalpha((unsigned char) *str))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2000-12-03 21:45:40 +01:00
|
|
|
while (isalpha((unsigned char) *str))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
str++;
|
|
|
|
}
|
|
|
|
|
2001-09-28 10:09:14 +02:00
|
|
|
/* Just get rid of any non-digit, non-alpha characters... */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
if (*str != '\0')
|
|
|
|
*str++ = '\0';
|
|
|
|
nf++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* look first for text fields, since that will be unambiguous month */
|
|
|
|
for (i = 0; i < nf; i++)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-12-03 21:45:40 +01:00
|
|
|
if (isalpha((unsigned char) *field[i]))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
|
|
|
type = DecodeSpecial(i, field[i], &val);
|
2002-06-11 15:40:53 +02:00
|
|
|
if (type == IGNORE_DTF)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
dmask = DTK_M(type);
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case MONTH:
|
|
|
|
tm->tm_mon = val;
|
2017-08-16 06:22:32 +02:00
|
|
|
haveTextMonth = true;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
if (fmask & dmask)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
fmask |= dmask;
|
|
|
|
*tmask |= dmask;
|
|
|
|
|
|
|
|
/* mark this field as being completed */
|
|
|
|
field[i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now pick up remaining numeric fields */
|
|
|
|
for (i = 0; i < nf; i++)
|
|
|
|
{
|
|
|
|
if (field[i] == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ((len = strlen(field[i])) <= 0)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2003-11-16 21:29:16 +01:00
|
|
|
dterr = DecodeNumber(len, field[i], haveTextMonth, fmask,
|
2003-08-28 01:29:29 +02:00
|
|
|
&dmask, tm,
|
2008-02-26 00:21:01 +01:00
|
|
|
&fsec, is2digits);
|
2003-08-28 01:29:29 +02:00
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
if (fmask & dmask)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
fmask |= dmask;
|
|
|
|
*tmask |= dmask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((fmask & ~(DTK_M(DOY) | DTK_M(TZ))) != DTK_DATE_M)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2008-02-26 00:21:01 +01:00
|
|
|
/* validation of the field values must wait until ValidateDate() */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ValidateDate()
|
|
|
|
* Check valid year/month/day values, handle BC and DOY cases
|
|
|
|
* Return 0 if okay, a DTERR code if not.
|
|
|
|
*/
|
2013-11-17 21:06:50 +01:00
|
|
|
int
|
2010-09-23 05:48:07 +02:00
|
|
|
ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
|
2017-06-21 20:39:04 +02:00
|
|
|
struct pg_tm *tm)
|
2008-02-26 00:21:01 +01:00
|
|
|
{
|
|
|
|
if (fmask & DTK_M(YEAR))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2010-09-23 05:48:07 +02:00
|
|
|
if (isjulian)
|
|
|
|
{
|
|
|
|
/* tm_year is correct and should not be touched */
|
|
|
|
}
|
|
|
|
else if (bc)
|
2008-02-26 00:21:01 +01:00
|
|
|
{
|
2008-02-26 00:36:28 +01:00
|
|
|
/* there is no year zero in AD/BC notation */
|
|
|
|
if (tm->tm_year <= 0)
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
|
|
|
/* internally, we represent 1 BC as year zero, 2 BC as -1, etc */
|
|
|
|
tm->tm_year = -(tm->tm_year - 1);
|
2008-02-26 00:21:01 +01:00
|
|
|
}
|
|
|
|
else if (is2digits)
|
|
|
|
{
|
2009-03-17 19:39:39 +01:00
|
|
|
/* process 1 or 2-digit input as 1970-2069 AD, allow '0' and '00' */
|
2009-06-11 16:49:15 +02:00
|
|
|
if (tm->tm_year < 0) /* just paranoia */
|
2008-02-26 00:36:28 +01:00
|
|
|
return DTERR_FIELD_OVERFLOW;
|
2008-02-26 00:21:01 +01:00
|
|
|
if (tm->tm_year < 70)
|
|
|
|
tm->tm_year += 2000;
|
|
|
|
else if (tm->tm_year < 100)
|
|
|
|
tm->tm_year += 1900;
|
|
|
|
}
|
2008-02-26 00:36:28 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* there is no year zero in AD/BC notation */
|
|
|
|
if (tm->tm_year <= 0)
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
|
2003-07-29 02:03:19 +02:00
|
|
|
/* now that we have correct year, decode DOY */
|
|
|
|
if (fmask & DTK_M(DOY))
|
|
|
|
{
|
|
|
|
j2date(date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1,
|
|
|
|
&tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check for valid month */
|
2008-02-26 00:21:01 +01:00
|
|
|
if (fmask & DTK_M(MONTH))
|
|
|
|
{
|
|
|
|
if (tm->tm_mon < 1 || tm->tm_mon > MONTHS_PER_YEAR)
|
|
|
|
return DTERR_MD_FIELD_OVERFLOW;
|
|
|
|
}
|
2003-07-29 02:03:19 +02:00
|
|
|
|
2008-02-26 00:21:01 +01:00
|
|
|
/* minimal check for valid day */
|
|
|
|
if (fmask & DTK_M(DAY))
|
|
|
|
{
|
|
|
|
if (tm->tm_mday < 1 || tm->tm_mday > 31)
|
|
|
|
return DTERR_MD_FIELD_OVERFLOW;
|
|
|
|
}
|
2003-08-28 01:29:29 +02:00
|
|
|
|
2008-02-26 00:21:01 +01:00
|
|
|
if ((fmask & DTK_DATE_M) == DTK_DATE_M)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Check for valid day of month, now that we know for sure the month
|
|
|
|
* and year. Note we don't use MD_FIELD_OVERFLOW here, since it seems
|
|
|
|
* unlikely that "Feb 29" is a YMD-order error.
|
|
|
|
*/
|
|
|
|
if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
|
|
|
}
|
2003-07-29 02:03:19 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
return 0;
|
2003-08-28 01:29:29 +02:00
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
|
|
|
|
/* DecodeTime()
|
|
|
|
* Decode time string which includes delimiters.
|
2003-08-28 01:29:29 +02:00
|
|
|
* Return 0 if okay, a DTERR code if not.
|
|
|
|
*
|
2007-05-27 22:32:16 +02:00
|
|
|
* Only check the lower limit on hours, since this same code can be
|
|
|
|
* used to represent time spans.
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
2000-06-09 00:38:00 +02:00
|
|
|
static int
|
2008-09-10 20:29:41 +02:00
|
|
|
DecodeTime(char *str, int fmask, int range,
|
2017-06-21 20:39:04 +02:00
|
|
|
int *tmask, struct pg_tm *tm, fsec_t *fsec)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
|
|
|
char *cp;
|
2008-11-12 02:36:20 +01:00
|
|
|
int dterr;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
*tmask = DTK_TIME_M;
|
|
|
|
|
2005-12-02 03:49:11 +01:00
|
|
|
errno = 0;
|
2016-04-23 22:53:15 +02:00
|
|
|
tm->tm_hour = strtoint(str, &cp, 10);
|
2005-12-01 18:56:34 +01:00
|
|
|
if (errno == ERANGE)
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
if (*cp != ':')
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2005-12-02 03:49:11 +01:00
|
|
|
errno = 0;
|
2016-04-23 22:53:15 +02:00
|
|
|
tm->tm_min = strtoint(cp + 1, &cp, 10);
|
2005-12-01 18:56:34 +01:00
|
|
|
if (errno == ERANGE)
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
if (*cp == '\0')
|
|
|
|
{
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
*fsec = 0;
|
2008-09-10 20:29:41 +02:00
|
|
|
/* If it's a MINUTE TO SECOND interval, take 2 fields as being mm:ss */
|
|
|
|
if (range == (INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND)))
|
|
|
|
{
|
|
|
|
tm->tm_sec = tm->tm_min;
|
|
|
|
tm->tm_min = tm->tm_hour;
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
2008-09-11 17:27:30 +02:00
|
|
|
else if (*cp == '.')
|
|
|
|
{
|
|
|
|
/* always assume mm:ss.sss is MINUTE TO SECOND */
|
2008-11-12 02:36:20 +01:00
|
|
|
dterr = ParseFractionalSecond(cp, fsec);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2008-09-11 17:27:30 +02:00
|
|
|
tm->tm_sec = tm->tm_min;
|
|
|
|
tm->tm_min = tm->tm_hour;
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
}
|
|
|
|
else if (*cp == ':')
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2005-12-02 03:49:11 +01:00
|
|
|
errno = 0;
|
2016-04-23 22:53:15 +02:00
|
|
|
tm->tm_sec = strtoint(cp + 1, &cp, 10);
|
2005-12-01 18:56:34 +01:00
|
|
|
if (errno == ERANGE)
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
if (*cp == '\0')
|
|
|
|
*fsec = 0;
|
|
|
|
else if (*cp == '.')
|
|
|
|
{
|
2008-11-12 02:36:20 +01:00
|
|
|
dterr = ParseFractionalSecond(cp, fsec);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
else
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
2008-09-11 17:27:30 +02:00
|
|
|
else
|
|
|
|
return DTERR_BAD_FORMAT;
|
1997-05-16 09:19:50 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* do a sanity check */
|
2011-04-10 17:42:00 +02:00
|
|
|
if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > MINS_PER_HOUR - 1 ||
|
2011-03-12 15:31:18 +01:00
|
|
|
tm->tm_sec < 0 || tm->tm_sec > SECS_PER_MINUTE ||
|
|
|
|
*fsec < INT64CONST(0) ||
|
2009-05-01 21:29:07 +02:00
|
|
|
*fsec > USECS_PER_SEC)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_FIELD_OVERFLOW;
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
return 0;
|
2003-08-28 01:29:29 +02:00
|
|
|
}
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* DecodeNumber()
|
2001-12-29 19:31:48 +01:00
|
|
|
* Interpret plain numeric field as a date value in context.
|
2003-08-28 01:29:29 +02:00
|
|
|
* Return 0 if okay, a DTERR code if not.
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
*/
|
2000-06-09 00:38:00 +02:00
|
|
|
static int
|
2003-11-16 21:29:16 +01:00
|
|
|
DecodeNumber(int flen, char *str, bool haveTextMonth, int fmask,
|
2017-06-21 20:39:04 +02:00
|
|
|
int *tmask, struct pg_tm *tm, fsec_t *fsec, bool *is2digits)
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
{
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
int val;
|
|
|
|
char *cp;
|
2003-08-28 01:29:29 +02:00
|
|
|
int dterr;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
*tmask = 0;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2005-12-02 03:49:11 +01:00
|
|
|
errno = 0;
|
2016-04-23 22:53:15 +02:00
|
|
|
val = strtoint(str, &cp, 10);
|
2005-12-01 18:56:34 +01:00
|
|
|
if (errno == ERANGE)
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
if (cp == str)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
if (*cp == '.')
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* More than two digits before decimal point? Then could be a date or
|
|
|
|
* a run-together time: 2001.360 20011225 040506.789
|
2001-12-29 19:31:48 +01:00
|
|
|
*/
|
2005-05-23 19:13:14 +02:00
|
|
|
if (cp - str > 2)
|
2003-08-26 00:47:34 +02:00
|
|
|
{
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeNumberField(flen, str,
|
|
|
|
(fmask | DTK_DATE_M),
|
|
|
|
tmask, tm,
|
|
|
|
fsec, is2digits);
|
|
|
|
if (dterr < 0)
|
|
|
|
return dterr;
|
2003-08-26 00:47:34 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2001-12-29 19:31:48 +01:00
|
|
|
|
2008-11-12 02:36:20 +01:00
|
|
|
dterr = ParseFractionalSecond(cp, fsec);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
2001-12-29 19:31:48 +01:00
|
|
|
else if (*cp != '\0')
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
1997-09-08 04:41:22 +02:00
|
|
|
|
2003-07-29 02:03:19 +02:00
|
|
|
/* Special case for day of year */
|
2005-05-23 19:13:14 +02:00
|
|
|
if (flen == 3 && (fmask & DTK_DATE_M) == DTK_M(YEAR) && val >= 1 &&
|
|
|
|
val <= 366)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
|
|
|
*tmask = (DTK_M(DOY) | DTK_M(MONTH) | DTK_M(DAY));
|
|
|
|
tm->tm_yday = val;
|
2003-07-29 02:03:19 +02:00
|
|
|
/* tm_mon and tm_mday can't actually be set yet ... */
|
|
|
|
return 0;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
1997-09-08 04:41:22 +02:00
|
|
|
|
2003-07-29 02:03:19 +02:00
|
|
|
/* Switch based on what we have so far */
|
|
|
|
switch (fmask & DTK_DATE_M)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2003-07-29 02:03:19 +02:00
|
|
|
case 0:
|
2003-08-04 02:43:34 +02:00
|
|
|
|
2003-07-29 02:03:19 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Nothing so far; make a decision about what we think the input
|
2014-05-06 18:12:18 +02:00
|
|
|
* is. There used to be lots of heuristics here, but the
|
2005-10-15 04:49:52 +02:00
|
|
|
* consensus now is to be paranoid. It *must* be either
|
2003-07-29 02:03:19 +02:00
|
|
|
* YYYY-MM-DD (with a more-than-two-digit year field), or the
|
|
|
|
* field order defined by DateOrder.
|
|
|
|
*/
|
|
|
|
if (flen >= 3 || DateOrder == DATEORDER_YMD)
|
|
|
|
{
|
|
|
|
*tmask = DTK_M(YEAR);
|
|
|
|
tm->tm_year = val;
|
|
|
|
}
|
|
|
|
else if (DateOrder == DATEORDER_DMY)
|
|
|
|
{
|
|
|
|
*tmask = DTK_M(DAY);
|
|
|
|
tm->tm_mday = val;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*tmask = DTK_M(MONTH);
|
|
|
|
tm->tm_mon = val;
|
|
|
|
}
|
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
|
2003-07-29 02:03:19 +02:00
|
|
|
case (DTK_M(YEAR)):
|
|
|
|
/* Must be at second field of YY-MM-DD */
|
|
|
|
*tmask = DTK_M(MONTH);
|
|
|
|
tm->tm_mon = val;
|
|
|
|
break;
|
|
|
|
|
2003-11-16 21:29:16 +01:00
|
|
|
case (DTK_M(MONTH)):
|
|
|
|
if (haveTextMonth)
|
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* We are at the first numeric field of a date that included a
|
2014-05-06 18:12:18 +02:00
|
|
|
* textual month name. We want to support the variants
|
2005-10-15 04:49:52 +02:00
|
|
|
* MON-DD-YYYY, DD-MON-YYYY, and YYYY-MON-DD as unambiguous
|
2014-05-06 18:12:18 +02:00
|
|
|
* inputs. We will also accept MON-DD-YY or DD-MON-YY in
|
2005-10-15 04:49:52 +02:00
|
|
|
* either DMY or MDY modes, as well as YY-MON-DD in YMD mode.
|
2003-11-16 21:29:16 +01:00
|
|
|
*/
|
|
|
|
if (flen >= 3 || DateOrder == DATEORDER_YMD)
|
|
|
|
{
|
|
|
|
*tmask = DTK_M(YEAR);
|
|
|
|
tm->tm_year = val;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*tmask = DTK_M(DAY);
|
|
|
|
tm->tm_mday = val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Must be at second field of MM-DD-YY */
|
|
|
|
*tmask = DTK_M(DAY);
|
|
|
|
tm->tm_mday = val;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2003-07-29 02:03:19 +02:00
|
|
|
case (DTK_M(YEAR) | DTK_M(MONTH)):
|
2003-11-16 21:29:16 +01:00
|
|
|
if (haveTextMonth)
|
|
|
|
{
|
|
|
|
/* Need to accept DD-MON-YYYY even in YMD mode */
|
|
|
|
if (flen >= 3 && *is2digits)
|
|
|
|
{
|
|
|
|
/* Guess that first numeric field is day was wrong */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
*tmask = DTK_M(DAY); /* YEAR is already set */
|
2003-11-16 21:29:16 +01:00
|
|
|
tm->tm_mday = tm->tm_year;
|
|
|
|
tm->tm_year = val;
|
2017-08-16 06:22:32 +02:00
|
|
|
*is2digits = false;
|
2003-11-16 21:29:16 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*tmask = DTK_M(DAY);
|
|
|
|
tm->tm_mday = val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Must be at third field of YY-MM-DD */
|
|
|
|
*tmask = DTK_M(DAY);
|
|
|
|
tm->tm_mday = val;
|
|
|
|
}
|
2003-07-29 02:03:19 +02:00
|
|
|
break;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2003-07-29 02:03:19 +02:00
|
|
|
case (DTK_M(DAY)):
|
|
|
|
/* Must be at second field of DD-MM-YY */
|
|
|
|
*tmask = DTK_M(MONTH);
|
|
|
|
tm->tm_mon = val;
|
|
|
|
break;
|
2000-03-29 05:57:18 +02:00
|
|
|
|
2003-07-29 02:03:19 +02:00
|
|
|
case (DTK_M(MONTH) | DTK_M(DAY)):
|
|
|
|
/* Must be at third field of DD-MM-YY or MM-DD-YY */
|
|
|
|
*tmask = DTK_M(YEAR);
|
|
|
|
tm->tm_year = val;
|
|
|
|
break;
|
|
|
|
|
2003-08-26 00:47:34 +02:00
|
|
|
case (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY)):
|
|
|
|
/* we have all the date, so it must be a time field */
|
2003-08-28 01:29:29 +02:00
|
|
|
dterr = DecodeNumberField(flen, str, fmask,
|
|
|
|
tmask, tm,
|
|
|
|
fsec, is2digits);
|
|
|
|
if (dterr < 0)
|
|
|
|
return dterr;
|
2003-08-26 00:47:34 +02:00
|
|
|
return 0;
|
|
|
|
|
2003-07-29 02:03:19 +02:00
|
|
|
default:
|
|
|
|
/* Anything else is bogus input */
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
2000-04-12 19:17:23 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* When processing a year field, mark it for adjustment if it's only one
|
|
|
|
* or two digits.
|
2000-03-29 05:57:18 +02:00
|
|
|
*/
|
2003-07-29 02:03:19 +02:00
|
|
|
if (*tmask == DTK_M(YEAR))
|
2003-11-16 21:29:16 +01:00
|
|
|
*is2digits = (flen <= 2);
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
return 0;
|
2003-07-29 02:03:19 +02:00
|
|
|
}
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
|
1997-05-16 09:19:50 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* DecodeNumberField()
|
2001-12-29 19:31:48 +01:00
|
|
|
* Interpret numeric string as a concatenated date or time field.
|
2003-08-28 01:29:29 +02:00
|
|
|
* Return a DTK token (>= 0) if successful, a DTERR code (< 0) if not.
|
|
|
|
*
|
2001-12-29 19:31:48 +01:00
|
|
|
* Use the context of previously decoded fields to help with
|
|
|
|
* the interpretation.
|
1997-05-16 09:19:50 +02:00
|
|
|
*/
|
2000-06-09 00:38:00 +02:00
|
|
|
static int
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
DecodeNumberField(int len, char *str, int fmask,
|
2017-06-21 20:39:04 +02:00
|
|
|
int *tmask, struct pg_tm *tm, fsec_t *fsec, bool *is2digits)
|
1997-05-16 09:19:50 +02:00
|
|
|
{
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
char *cp;
|
1997-05-16 09:19:50 +02:00
|
|
|
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Have a decimal point? Then this is a date or something with a seconds
|
|
|
|
* field...
|
2001-12-29 19:31:48 +01:00
|
|
|
*/
|
|
|
|
if ((cp = strchr(str, '.')) != NULL)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2008-11-12 02:36:20 +01:00
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* Can we use ParseFractionalSecond here? Not clear whether trailing
|
|
|
|
* junk should be rejected ...
|
2008-11-12 02:36:20 +01:00
|
|
|
*/
|
2003-08-05 19:39:19 +02:00
|
|
|
double frac;
|
2002-04-21 21:52:18 +02:00
|
|
|
|
2008-11-12 02:36:20 +01:00
|
|
|
errno = 0;
|
2003-08-05 19:39:19 +02:00
|
|
|
frac = strtod(cp, NULL);
|
2008-11-12 02:36:20 +01:00
|
|
|
if (errno != 0)
|
|
|
|
return DTERR_BAD_FORMAT;
|
2003-08-05 19:39:19 +02:00
|
|
|
*fsec = rint(frac * 1000000);
|
2008-11-12 02:36:20 +01:00
|
|
|
/* Now truncate off the fraction for further processing */
|
2001-12-29 19:31:48 +01:00
|
|
|
*cp = '\0';
|
|
|
|
len = strlen(str);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
2001-12-29 19:31:48 +01:00
|
|
|
/* No decimal point and no complete date yet? */
|
|
|
|
else if ((fmask & DTK_DATE_M) != DTK_DATE_M)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2013-10-16 19:22:55 +02:00
|
|
|
if (len >= 6)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
|
|
|
*tmask = DTK_DATE_M;
|
2014-05-06 18:12:18 +02:00
|
|
|
|
2013-10-16 19:22:55 +02:00
|
|
|
/*
|
|
|
|
* Start from end and consider first 2 as Day, next 2 as Month,
|
|
|
|
* and the rest as Year.
|
|
|
|
*/
|
|
|
|
tm->tm_mday = atoi(str + (len - 2));
|
|
|
|
*(str + (len - 2)) = '\0';
|
|
|
|
tm->tm_mon = atoi(str + (len - 4));
|
|
|
|
*(str + (len - 4)) = '\0';
|
|
|
|
tm->tm_year = atoi(str);
|
|
|
|
if ((len - 4) == 2)
|
2017-08-16 06:22:32 +02:00
|
|
|
*is2digits = true;
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
return DTK_DATE;
|
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
/* not all time fields are specified? */
|
|
|
|
if ((fmask & DTK_TIME_M) != DTK_TIME_M)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2001-12-29 19:31:48 +01:00
|
|
|
/* hhmmss */
|
|
|
|
if (len == 6)
|
|
|
|
{
|
|
|
|
*tmask = DTK_TIME_M;
|
|
|
|
tm->tm_sec = atoi(str + 4);
|
|
|
|
*(str + 4) = '\0';
|
|
|
|
tm->tm_min = atoi(str + 2);
|
|
|
|
*(str + 2) = '\0';
|
2013-10-16 19:22:55 +02:00
|
|
|
tm->tm_hour = atoi(str);
|
2001-12-29 19:31:48 +01:00
|
|
|
|
|
|
|
return DTK_TIME;
|
|
|
|
}
|
|
|
|
/* hhmm? */
|
|
|
|
else if (len == 4)
|
|
|
|
{
|
|
|
|
*tmask = DTK_TIME_M;
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
tm->tm_min = atoi(str + 2);
|
|
|
|
*(str + 2) = '\0';
|
2013-10-16 19:22:55 +02:00
|
|
|
tm->tm_hour = atoi(str);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2001-12-29 19:31:48 +01:00
|
|
|
return DTK_TIME;
|
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
}
|
1997-05-16 09:19:50 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* DecodeTimezone()
|
|
|
|
* Interpret string as a numeric timezone.
|
2002-11-13 18:24:05 +01:00
|
|
|
*
|
2003-08-28 01:29:29 +02:00
|
|
|
* Return 0 if okay (and set *tzp), a DTERR code if not okay.
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
2014-03-04 19:09:43 +01:00
|
|
|
int
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
DecodeTimezone(char *str, int *tzp)
|
|
|
|
{
|
|
|
|
int tz;
|
|
|
|
int hr,
|
2006-10-17 23:03:21 +02:00
|
|
|
min,
|
|
|
|
sec = 0;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
char *cp;
|
|
|
|
|
2003-05-18 03:06:26 +02:00
|
|
|
/* leading character must be "+" or "-" */
|
|
|
|
if (*str != '+' && *str != '-')
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
2003-05-18 03:06:26 +02:00
|
|
|
|
2005-12-02 03:49:11 +01:00
|
|
|
errno = 0;
|
2016-04-23 22:53:15 +02:00
|
|
|
hr = strtoint(str + 1, &cp, 10);
|
2005-12-01 18:56:34 +01:00
|
|
|
if (errno == ERANGE)
|
|
|
|
return DTERR_TZDISP_OVERFLOW;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
/* explicit delimiter? */
|
|
|
|
if (*cp == ':')
|
2005-12-01 18:56:34 +01:00
|
|
|
{
|
2005-12-02 03:49:11 +01:00
|
|
|
errno = 0;
|
2016-04-23 22:53:15 +02:00
|
|
|
min = strtoint(cp + 1, &cp, 10);
|
2005-12-01 18:56:34 +01:00
|
|
|
if (errno == ERANGE)
|
|
|
|
return DTERR_TZDISP_OVERFLOW;
|
2006-10-17 23:03:21 +02:00
|
|
|
if (*cp == ':')
|
|
|
|
{
|
|
|
|
errno = 0;
|
2016-04-23 22:53:15 +02:00
|
|
|
sec = strtoint(cp + 1, &cp, 10);
|
2006-10-17 23:03:21 +02:00
|
|
|
if (errno == ERANGE)
|
|
|
|
return DTERR_TZDISP_OVERFLOW;
|
|
|
|
}
|
2005-12-01 18:56:34 +01:00
|
|
|
}
|
2001-12-29 19:31:48 +01:00
|
|
|
/* otherwise, might have run things together... */
|
2005-05-23 19:13:14 +02:00
|
|
|
else if (*cp == '\0' && strlen(str) > 3)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2003-08-28 01:29:29 +02:00
|
|
|
min = hr % 100;
|
|
|
|
hr = hr / 100;
|
2006-10-17 23:03:21 +02:00
|
|
|
/* we could, but don't, support a run-together hhmmss format */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
min = 0;
|
1997-05-16 09:19:50 +02:00
|
|
|
|
2012-05-31 01:58:35 +02:00
|
|
|
/* Range-check the values; see notes in datatype/timestamp.h */
|
|
|
|
if (hr < 0 || hr > MAX_TZDISP_HOUR)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_TZDISP_OVERFLOW;
|
2011-03-12 15:31:18 +01:00
|
|
|
if (min < 0 || min >= MINS_PER_HOUR)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_TZDISP_OVERFLOW;
|
2011-03-12 15:31:18 +01:00
|
|
|
if (sec < 0 || sec >= SECS_PER_MINUTE)
|
2006-10-17 23:03:21 +02:00
|
|
|
return DTERR_TZDISP_OVERFLOW;
|
2003-05-18 03:06:26 +02:00
|
|
|
|
2006-10-17 23:03:21 +02:00
|
|
|
tz = (hr * MINS_PER_HOUR + min) * SECS_PER_MINUTE + sec;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
if (*str == '-')
|
|
|
|
tz = -tz;
|
1997-05-16 09:19:50 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*tzp = -tz;
|
2003-08-28 01:29:29 +02:00
|
|
|
|
|
|
|
if (*cp != '\0')
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
|
|
|
|
/* DecodeTimezoneAbbrev()
|
|
|
|
* Interpret string as a timezone abbreviation, if possible.
|
|
|
|
*
|
|
|
|
* Returns an abbreviation type (TZ, DTZ, or DYNTZ), or UNKNOWN_FIELD if
|
|
|
|
* string is not any known abbreviation. On success, set *offset and *tz to
|
|
|
|
* represent the UTC offset (for TZ or DTZ) or underlying zone (for DYNTZ).
|
|
|
|
* Note that full timezone names (such as America/New_York) are not handled
|
|
|
|
* here, mostly for historical reasons.
|
|
|
|
*
|
|
|
|
* Given string must be lowercased already.
|
|
|
|
*
|
|
|
|
* Implement a cache lookup since it is likely that dates
|
|
|
|
* will be related in format.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
DecodeTimezoneAbbrev(int field, char *lowtoken,
|
|
|
|
int *offset, pg_tz **tz)
|
|
|
|
{
|
|
|
|
int type;
|
|
|
|
const datetkn *tp;
|
|
|
|
|
|
|
|
tp = abbrevcache[field];
|
|
|
|
/* use strncmp so that we match truncated tokens */
|
|
|
|
if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
|
|
|
|
{
|
|
|
|
if (zoneabbrevtbl)
|
|
|
|
tp = datebsearch(lowtoken, zoneabbrevtbl->abbrevs,
|
|
|
|
zoneabbrevtbl->numabbrevs);
|
|
|
|
else
|
|
|
|
tp = NULL;
|
|
|
|
}
|
|
|
|
if (tp == NULL)
|
|
|
|
{
|
|
|
|
type = UNKNOWN_FIELD;
|
|
|
|
*offset = 0;
|
|
|
|
*tz = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
abbrevcache[field] = tp;
|
|
|
|
type = tp->type;
|
|
|
|
if (type == DYNTZ)
|
|
|
|
{
|
|
|
|
*offset = 0;
|
|
|
|
*tz = FetchDynamicTimeZone(zoneabbrevtbl, tp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*offset = tp->value;
|
|
|
|
*tz = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* DecodeSpecial()
|
|
|
|
* Decode text string using lookup table.
|
2003-05-18 03:06:26 +02:00
|
|
|
*
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
* Recognizes the keywords listed in datetktbl.
|
|
|
|
* Note: at one time this would also recognize timezone abbreviations,
|
|
|
|
* but no more; use DecodeTimezoneAbbrev for that.
|
|
|
|
*
|
|
|
|
* Given string must be lowercased already.
|
|
|
|
*
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
* Implement a cache lookup since it is likely that dates
|
|
|
|
* will be related in format.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
DecodeSpecial(int field, char *lowtoken, int *val)
|
|
|
|
{
|
|
|
|
int type;
|
2006-07-25 05:51:23 +02:00
|
|
|
const datetkn *tp;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2006-07-25 05:51:23 +02:00
|
|
|
tp = datecache[field];
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/* use strncmp so that we match truncated tokens */
|
2006-07-25 05:51:23 +02:00
|
|
|
if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
tp = datebsearch(lowtoken, datetktbl, szdatetktbl);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
if (tp == NULL)
|
|
|
|
{
|
2001-09-28 10:09:14 +02:00
|
|
|
type = UNKNOWN_FIELD;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*val = 0;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-07-25 05:51:23 +02:00
|
|
|
datecache[field] = tp;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
type = tp->type;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*val = tp->value;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1997-05-16 09:19:50 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
return type;
|
2003-08-28 01:29:29 +02:00
|
|
|
}
|
1997-03-15 00:21:12 +01:00
|
|
|
|
|
|
|
|
2019-07-01 03:00:23 +02:00
|
|
|
/* ClearPgTm
|
2008-11-12 02:36:20 +01:00
|
|
|
*
|
|
|
|
* Zero out a pg_tm and associated fsec_t
|
|
|
|
*/
|
2009-06-11 16:49:15 +02:00
|
|
|
static inline void
|
2017-06-21 20:39:04 +02:00
|
|
|
ClearPgTm(struct pg_tm *tm, fsec_t *fsec)
|
2008-11-12 02:36:20 +01:00
|
|
|
{
|
|
|
|
tm->tm_year = 0;
|
2009-06-11 16:49:15 +02:00
|
|
|
tm->tm_mon = 0;
|
2008-11-12 02:36:20 +01:00
|
|
|
tm->tm_mday = 0;
|
|
|
|
tm->tm_hour = 0;
|
2009-06-11 16:49:15 +02:00
|
|
|
tm->tm_min = 0;
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
*fsec = 0;
|
2008-11-12 02:36:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-04-21 21:52:18 +02:00
|
|
|
/* DecodeInterval()
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
* Interpret previously parsed fields for general time interval.
|
2003-08-28 01:29:29 +02:00
|
|
|
* Returns 0 if successful, DTERR code if bogus input detected.
|
2008-11-11 03:42:33 +01:00
|
|
|
* dtype, tm, fsec are output parameters.
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*
|
|
|
|
* Allow "date" field DTK_DATE since this could be just
|
|
|
|
* an unsigned floating point number. - thomas 1997-11-16
|
|
|
|
*
|
|
|
|
* Allow ISO-style time span, with implicit units on number of days
|
2001-11-21 23:57:01 +01:00
|
|
|
* preceding an hh:mm:ss field. - thomas 1998-04-30
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
|
|
|
int
|
2008-09-10 20:29:41 +02:00
|
|
|
DecodeInterval(char **field, int *ftype, int nf, int range,
|
2017-06-21 20:39:04 +02:00
|
|
|
int *dtype, struct pg_tm *tm, fsec_t *fsec)
|
1997-03-15 00:21:12 +01:00
|
|
|
{
|
2017-08-16 06:22:32 +02:00
|
|
|
bool is_before = false;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
char *cp;
|
|
|
|
int fmask = 0,
|
|
|
|
tmask,
|
|
|
|
type;
|
|
|
|
int i;
|
2003-08-28 01:29:29 +02:00
|
|
|
int dterr;
|
2000-11-06 16:57:00 +01:00
|
|
|
int val;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
double fval;
|
|
|
|
|
|
|
|
*dtype = DTK_DELTA;
|
2002-06-11 15:40:53 +02:00
|
|
|
type = IGNORE_DTF;
|
2009-06-11 16:49:15 +02:00
|
|
|
ClearPgTm(tm, fsec);
|
1997-03-15 00:21:12 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* read through list backwards to pick up units before values */
|
|
|
|
for (i = nf - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
switch (ftype[i])
|
|
|
|
{
|
|
|
|
case DTK_TIME:
|
2008-09-10 20:29:41 +02:00
|
|
|
dterr = DecodeTime(field[i], fmask, range,
|
|
|
|
&tmask, tm, fsec);
|
2003-08-28 01:29:29 +02:00
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
type = DTK_DAY;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_TZ:
|
2001-03-22 05:01:46 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/*
|
2012-08-03 23:39:39 +02:00
|
|
|
* Timezone means a token with a leading sign character and at
|
2009-06-11 16:49:15 +02:00
|
|
|
* least one digit; there could be ':', '.', '-' embedded in
|
|
|
|
* it as well.
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
2005-05-23 19:13:14 +02:00
|
|
|
Assert(*field[i] == '-' || *field[i] == '+');
|
2001-03-22 05:01:46 +01:00
|
|
|
|
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Check for signed hh:mm or hh:mm:ss. If so, process exactly
|
2012-08-03 23:39:39 +02:00
|
|
|
* like DTK_TIME case above, plus handling the sign.
|
2000-11-06 16:57:00 +01:00
|
|
|
*/
|
2008-09-17 00:31:21 +02:00
|
|
|
if (strchr(field[i] + 1, ':') != NULL &&
|
2012-08-03 23:39:39 +02:00
|
|
|
DecodeTime(field[i] + 1, fmask, range,
|
2008-09-10 20:29:41 +02:00
|
|
|
&tmask, tm, fsec) == 0)
|
2001-03-22 05:01:46 +01:00
|
|
|
{
|
|
|
|
if (*field[i] == '-')
|
|
|
|
{
|
2000-11-06 16:57:00 +01:00
|
|
|
/* flip the sign on all fields */
|
|
|
|
tm->tm_hour = -tm->tm_hour;
|
|
|
|
tm->tm_min = -tm->tm_min;
|
|
|
|
tm->tm_sec = -tm->tm_sec;
|
|
|
|
*fsec = -(*fsec);
|
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
/*
|
|
|
|
* Set the next type to be a day, if units are not
|
2005-10-15 04:49:52 +02:00
|
|
|
* specified. This handles the case of '1 +02:03' since we
|
|
|
|
* are reading right to left.
|
2000-11-06 16:57:00 +01:00
|
|
|
*/
|
|
|
|
type = DTK_DAY;
|
|
|
|
break;
|
2001-03-22 05:01:46 +01:00
|
|
|
}
|
2012-08-03 23:39:39 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Otherwise, fall through to DTK_NUMBER case, which can
|
|
|
|
* handle signed float numbers and signed year-month values.
|
|
|
|
*/
|
|
|
|
|
2018-05-02 01:35:08 +02:00
|
|
|
/* FALLTHROUGH */
|
2000-11-06 16:57:00 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
case DTK_DATE:
|
|
|
|
case DTK_NUMBER:
|
2008-09-10 20:29:41 +02:00
|
|
|
if (type == IGNORE_DTF)
|
|
|
|
{
|
2008-09-17 00:31:21 +02:00
|
|
|
/* use typmod to decide what rightmost field is */
|
2008-09-10 20:29:41 +02:00
|
|
|
switch (range)
|
|
|
|
{
|
|
|
|
case INTERVAL_MASK(YEAR):
|
|
|
|
type = DTK_YEAR;
|
|
|
|
break;
|
|
|
|
case INTERVAL_MASK(MONTH):
|
|
|
|
case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
|
|
|
|
type = DTK_MONTH;
|
|
|
|
break;
|
|
|
|
case INTERVAL_MASK(DAY):
|
|
|
|
type = DTK_DAY;
|
|
|
|
break;
|
|
|
|
case INTERVAL_MASK(HOUR):
|
|
|
|
case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
|
|
|
|
type = DTK_HOUR;
|
|
|
|
break;
|
|
|
|
case INTERVAL_MASK(MINUTE):
|
|
|
|
case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
|
2009-06-10 07:05:03 +02:00
|
|
|
case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
|
2008-09-10 20:29:41 +02:00
|
|
|
type = DTK_MINUTE;
|
|
|
|
break;
|
|
|
|
case INTERVAL_MASK(SECOND):
|
|
|
|
case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
|
2009-06-10 07:05:03 +02:00
|
|
|
case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
|
|
|
|
case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
|
2008-09-10 20:29:41 +02:00
|
|
|
type = DTK_SECOND;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
type = DTK_SECOND;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-02 03:49:11 +01:00
|
|
|
errno = 0;
|
2016-04-23 22:53:15 +02:00
|
|
|
val = strtoint(field[i], &cp, 10);
|
2005-12-01 18:56:34 +01:00
|
|
|
if (errno == ERANGE)
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
2000-11-06 16:57:00 +01:00
|
|
|
|
2008-09-10 20:29:41 +02:00
|
|
|
if (*cp == '-')
|
|
|
|
{
|
|
|
|
/* SQL "years-months" syntax */
|
2009-06-11 16:49:15 +02:00
|
|
|
int val2;
|
2001-09-28 10:09:14 +02:00
|
|
|
|
2016-04-23 22:53:15 +02:00
|
|
|
val2 = strtoint(cp + 1, &cp, 10);
|
2008-09-10 20:29:41 +02:00
|
|
|
if (errno == ERANGE || val2 < 0 || val2 >= MONTHS_PER_YEAR)
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
|
|
|
if (*cp != '\0')
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
type = DTK_MONTH;
|
2008-11-08 21:51:49 +01:00
|
|
|
if (*field[i] == '-')
|
2008-09-17 00:31:21 +02:00
|
|
|
val2 = -val2;
|
2014-05-06 18:12:18 +02:00
|
|
|
if (((double) val * MONTHS_PER_YEAR + val2) > INT_MAX ||
|
|
|
|
((double) val * MONTHS_PER_YEAR + val2) < INT_MIN)
|
2014-01-30 15:41:43 +01:00
|
|
|
return DTERR_FIELD_OVERFLOW;
|
2008-09-10 20:29:41 +02:00
|
|
|
val = val * MONTHS_PER_YEAR + val2;
|
|
|
|
fval = 0;
|
|
|
|
}
|
|
|
|
else if (*cp == '.')
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2008-11-12 02:36:20 +01:00
|
|
|
errno = 0;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
fval = strtod(cp, &cp);
|
2008-11-12 02:36:20 +01:00
|
|
|
if (*cp != '\0' || errno != 0)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2003-12-17 22:45:44 +01:00
|
|
|
if (*field[i] == '-')
|
2005-05-24 04:09:45 +02:00
|
|
|
fval = -fval;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
else if (*cp == '\0')
|
|
|
|
fval = 0;
|
|
|
|
else
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
|
|
|
tmask = 0; /* DTK_M(type); */
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case DTK_MICROSEC:
|
2008-09-24 21:46:44 +02:00
|
|
|
*fsec += rint(val + fval);
|
2007-05-29 06:58:43 +02:00
|
|
|
tmask = DTK_M(MICROSECOND);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_MILLISEC:
|
2009-08-18 23:23:14 +02:00
|
|
|
/* avoid overflowing the fsec field */
|
|
|
|
tm->tm_sec += val / 1000;
|
|
|
|
val -= (val / 1000) * 1000;
|
2008-09-24 21:46:44 +02:00
|
|
|
*fsec += rint((val + fval) * 1000);
|
2007-05-29 06:58:43 +02:00
|
|
|
tmask = DTK_M(MILLISECOND);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_SECOND:
|
|
|
|
tm->tm_sec += val;
|
2008-09-24 21:46:44 +02:00
|
|
|
*fsec += rint(fval * 1000000);
|
2007-11-15 22:14:46 +01:00
|
|
|
|
2007-05-29 06:58:43 +02:00
|
|
|
/*
|
2007-11-15 22:14:46 +01:00
|
|
|
* If any subseconds were specified, consider this
|
|
|
|
* microsecond and millisecond input as well.
|
2007-05-29 06:58:43 +02:00
|
|
|
*/
|
|
|
|
if (fval == 0)
|
|
|
|
tmask = DTK_M(SECOND);
|
|
|
|
else
|
|
|
|
tmask = DTK_ALL_SECS_M;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_MINUTE:
|
|
|
|
tm->tm_min += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(fval, tm, fsec, SECS_PER_MINUTE);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
tmask = DTK_M(MINUTE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_HOUR:
|
|
|
|
tm->tm_hour += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
tmask = DTK_M(HOUR);
|
2009-06-11 16:49:15 +02:00
|
|
|
type = DTK_DAY; /* set for next field */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_DAY:
|
|
|
|
tm->tm_mday += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
|
2009-06-01 18:55:11 +02:00
|
|
|
tmask = DTK_M(DAY);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_WEEK:
|
|
|
|
tm->tm_mday += val * 7;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractDays(fval, tm, fsec, 7);
|
2009-06-01 18:55:11 +02:00
|
|
|
tmask = DTK_M(WEEK);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_MONTH:
|
|
|
|
tm->tm_mon += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractDays(fval, tm, fsec, DAYS_PER_MONTH);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
tmask = DTK_M(MONTH);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_YEAR:
|
|
|
|
tm->tm_year += val;
|
|
|
|
if (fval != 0)
|
2005-07-21 05:56:25 +02:00
|
|
|
tm->tm_mon += fval * MONTHS_PER_YEAR;
|
2009-06-01 18:55:11 +02:00
|
|
|
tmask = DTK_M(YEAR);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_DECADE:
|
|
|
|
tm->tm_year += val * 10;
|
|
|
|
if (fval != 0)
|
2005-07-21 05:56:25 +02:00
|
|
|
tm->tm_mon += fval * MONTHS_PER_YEAR * 10;
|
2009-06-01 18:55:11 +02:00
|
|
|
tmask = DTK_M(DECADE);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_CENTURY:
|
|
|
|
tm->tm_year += val * 100;
|
|
|
|
if (fval != 0)
|
2005-07-21 05:56:25 +02:00
|
|
|
tm->tm_mon += fval * MONTHS_PER_YEAR * 100;
|
2009-06-01 18:55:11 +02:00
|
|
|
tmask = DTK_M(CENTURY);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
2000-04-14 17:22:10 +02:00
|
|
|
case DTK_MILLENNIUM:
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
tm->tm_year += val * 1000;
|
|
|
|
if (fval != 0)
|
2005-07-21 05:56:25 +02:00
|
|
|
tm->tm_mon += fval * MONTHS_PER_YEAR * 1000;
|
2009-06-01 18:55:11 +02:00
|
|
|
tmask = DTK_M(MILLENNIUM);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_STRING:
|
|
|
|
case DTK_SPECIAL:
|
|
|
|
type = DecodeUnits(i, field[i], &val);
|
2002-06-11 15:40:53 +02:00
|
|
|
if (type == IGNORE_DTF)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
tmask = 0; /* DTK_M(type); */
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case UNITS:
|
|
|
|
type = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AGO:
|
2017-08-16 06:22:32 +02:00
|
|
|
is_before = true;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
type = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESERV:
|
2010-08-02 03:24:54 +02:00
|
|
|
tmask = (DTK_DATE_M | DTK_TIME_M);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*dtype = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (tmask & fmask)
|
2003-08-28 01:29:29 +02:00
|
|
|
return DTERR_BAD_FORMAT;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
fmask |= tmask;
|
|
|
|
}
|
1997-03-15 00:21:12 +01:00
|
|
|
|
2008-11-09 01:28:35 +01:00
|
|
|
/* ensure that at least one time field has been found */
|
|
|
|
if (fmask == 0)
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
|
|
|
|
/* ensure fractional seconds are fractional */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
if (*fsec != 0)
|
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
int sec;
|
2002-04-21 21:52:18 +02:00
|
|
|
|
2005-07-21 06:41:43 +02:00
|
|
|
sec = *fsec / USECS_PER_SEC;
|
|
|
|
*fsec -= sec * USECS_PER_SEC;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
tm->tm_sec += sec;
|
|
|
|
}
|
1997-03-15 00:21:12 +01:00
|
|
|
|
2008-11-09 01:28:35 +01:00
|
|
|
/*----------
|
|
|
|
* The SQL standard defines the interval literal
|
2009-06-11 16:49:15 +02:00
|
|
|
* '-1 1:00:00'
|
2008-11-09 01:28:35 +01:00
|
|
|
* to mean "negative 1 days and negative 1 hours", while Postgres
|
|
|
|
* traditionally treats this as meaning "negative 1 days and positive
|
|
|
|
* 1 hours". In SQL_STANDARD intervalstyle, we apply the leading sign
|
|
|
|
* to all fields if there are no other explicit signs.
|
|
|
|
*
|
|
|
|
* We leave the signs alone if there are additional explicit signs.
|
|
|
|
* This protects us against misinterpreting postgres-style dump output,
|
|
|
|
* since the postgres-style output code has always put an explicit sign on
|
|
|
|
* all fields following a negative field. But note that SQL-spec output
|
2009-06-11 16:49:15 +02:00
|
|
|
* is ambiguous and can be misinterpreted on load! (So it's best practice
|
2008-11-09 01:28:35 +01:00
|
|
|
* to dump in postgres style, not SQL style.)
|
|
|
|
*----------
|
|
|
|
*/
|
|
|
|
if (IntervalStyle == INTSTYLE_SQL_STANDARD && *field[0] == '-')
|
|
|
|
{
|
|
|
|
/* Check for additional explicit signs */
|
2009-06-11 16:49:15 +02:00
|
|
|
bool more_signs = false;
|
2008-11-09 01:28:35 +01:00
|
|
|
|
|
|
|
for (i = 1; i < nf; i++)
|
|
|
|
{
|
|
|
|
if (*field[i] == '-' || *field[i] == '+')
|
|
|
|
{
|
|
|
|
more_signs = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!more_signs)
|
|
|
|
{
|
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* Rather than re-determining which field was field[0], just force
|
|
|
|
* 'em all negative.
|
2008-11-09 01:28:35 +01:00
|
|
|
*/
|
|
|
|
if (*fsec > 0)
|
|
|
|
*fsec = -(*fsec);
|
|
|
|
if (tm->tm_sec > 0)
|
|
|
|
tm->tm_sec = -tm->tm_sec;
|
|
|
|
if (tm->tm_min > 0)
|
|
|
|
tm->tm_min = -tm->tm_min;
|
|
|
|
if (tm->tm_hour > 0)
|
|
|
|
tm->tm_hour = -tm->tm_hour;
|
|
|
|
if (tm->tm_mday > 0)
|
|
|
|
tm->tm_mday = -tm->tm_mday;
|
|
|
|
if (tm->tm_mon > 0)
|
|
|
|
tm->tm_mon = -tm->tm_mon;
|
|
|
|
if (tm->tm_year > 0)
|
|
|
|
tm->tm_year = -tm->tm_year;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* finally, AGO negates everything */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
if (is_before)
|
|
|
|
{
|
|
|
|
*fsec = -(*fsec);
|
2005-05-24 04:09:45 +02:00
|
|
|
tm->tm_sec = -tm->tm_sec;
|
|
|
|
tm->tm_min = -tm->tm_min;
|
|
|
|
tm->tm_hour = -tm->tm_hour;
|
|
|
|
tm->tm_mday = -tm->tm_mday;
|
|
|
|
tm->tm_mon = -tm->tm_mon;
|
|
|
|
tm->tm_year = -tm->tm_year;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
1997-03-15 00:21:12 +01:00
|
|
|
|
2003-08-28 01:29:29 +02:00
|
|
|
return 0;
|
|
|
|
}
|
1997-03-15 00:21:12 +01:00
|
|
|
|
|
|
|
|
2008-11-11 03:42:33 +01:00
|
|
|
/*
|
|
|
|
* Helper functions to avoid duplicated code in DecodeISO8601Interval.
|
|
|
|
*
|
|
|
|
* Parse a decimal value and break it into integer and fractional parts.
|
|
|
|
* Returns 0 or DTERR code.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
ParseISO8601Number(char *str, char **endptr, int *ipart, double *fpart)
|
|
|
|
{
|
|
|
|
double val;
|
|
|
|
|
|
|
|
if (!(isdigit((unsigned char) *str) || *str == '-' || *str == '.'))
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
errno = 0;
|
|
|
|
val = strtod(str, endptr);
|
|
|
|
/* did we not see anything that looks like a double? */
|
|
|
|
if (*endptr == str || errno != 0)
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
/* watch out for overflow */
|
|
|
|
if (val < INT_MIN || val > INT_MAX)
|
|
|
|
return DTERR_FIELD_OVERFLOW;
|
|
|
|
/* be very sure we truncate towards zero (cf dtrunc()) */
|
|
|
|
if (val >= 0)
|
|
|
|
*ipart = (int) floor(val);
|
|
|
|
else
|
|
|
|
*ipart = (int) -floor(-val);
|
|
|
|
*fpart = val - *ipart;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine number of integral digits in a valid ISO 8601 number field
|
|
|
|
* (we should ignore sign and any fraction part)
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
ISO8601IntegerWidth(char *fieldstart)
|
|
|
|
{
|
|
|
|
/* We might have had a leading '-' */
|
|
|
|
if (*fieldstart == '-')
|
|
|
|
fieldstart++;
|
|
|
|
return strspn(fieldstart, "0123456789");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* DecodeISO8601Interval()
|
2009-06-11 16:49:15 +02:00
|
|
|
* Decode an ISO 8601 time interval of the "format with designators"
|
|
|
|
* (section 4.4.3.2) or "alternative format" (section 4.4.3.3)
|
|
|
|
* Examples: P1D for 1 day
|
|
|
|
* PT1H for 1 hour
|
|
|
|
* P2Y6M7DT1H30M for 2 years, 6 months, 7 days 1 hour 30 min
|
|
|
|
* P0002-06-07T01:30:00 the same value in alternative format
|
2008-11-11 03:42:33 +01:00
|
|
|
*
|
|
|
|
* Returns 0 if successful, DTERR code if bogus input detected.
|
|
|
|
* Note: error code should be DTERR_BAD_FORMAT if input doesn't look like
|
|
|
|
* ISO8601, otherwise this could cause unexpected error messages.
|
|
|
|
* dtype, tm, fsec are output parameters.
|
|
|
|
*
|
2009-06-11 16:49:15 +02:00
|
|
|
* A couple exceptions from the spec:
|
|
|
|
* - a week field ('W') may coexist with other units
|
|
|
|
* - allows decimals in fields other than the least significant unit.
|
2008-11-11 03:42:33 +01:00
|
|
|
*/
|
|
|
|
int
|
|
|
|
DecodeISO8601Interval(char *str,
|
2017-06-21 20:39:04 +02:00
|
|
|
int *dtype, struct pg_tm *tm, fsec_t *fsec)
|
2008-11-11 03:42:33 +01:00
|
|
|
{
|
2009-06-11 16:49:15 +02:00
|
|
|
bool datepart = true;
|
|
|
|
bool havefield = false;
|
2008-11-11 03:42:33 +01:00
|
|
|
|
|
|
|
*dtype = DTK_DELTA;
|
2008-11-12 02:36:20 +01:00
|
|
|
ClearPgTm(tm, fsec);
|
2008-11-11 03:42:33 +01:00
|
|
|
|
|
|
|
if (strlen(str) < 2 || str[0] != 'P')
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
|
|
|
|
str++;
|
|
|
|
while (*str)
|
|
|
|
{
|
2009-06-11 16:49:15 +02:00
|
|
|
char *fieldstart;
|
|
|
|
int val;
|
|
|
|
double fval;
|
|
|
|
char unit;
|
|
|
|
int dterr;
|
2008-11-11 03:42:33 +01:00
|
|
|
|
2009-06-11 16:49:15 +02:00
|
|
|
if (*str == 'T') /* T indicates the beginning of the time part */
|
2008-11-11 03:42:33 +01:00
|
|
|
{
|
|
|
|
datepart = false;
|
|
|
|
havefield = false;
|
|
|
|
str++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
fieldstart = str;
|
|
|
|
dterr = ParseISO8601Number(str, &str, &val, &fval);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
|
|
|
|
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Note: we could step off the end of the string here. Code below
|
2008-11-11 03:42:33 +01:00
|
|
|
* *must* exit the loop if unit == '\0'.
|
|
|
|
*/
|
|
|
|
unit = *str++;
|
|
|
|
|
|
|
|
if (datepart)
|
|
|
|
{
|
2009-06-11 16:49:15 +02:00
|
|
|
switch (unit) /* before T: Y M W D */
|
2008-11-11 03:42:33 +01:00
|
|
|
{
|
|
|
|
case 'Y':
|
|
|
|
tm->tm_year += val;
|
2011-03-12 15:31:18 +01:00
|
|
|
tm->tm_mon += (fval * MONTHS_PER_YEAR);
|
2008-11-11 03:42:33 +01:00
|
|
|
break;
|
|
|
|
case 'M':
|
|
|
|
tm->tm_mon += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractDays(fval, tm, fsec, DAYS_PER_MONTH);
|
2008-11-11 03:42:33 +01:00
|
|
|
break;
|
|
|
|
case 'W':
|
|
|
|
tm->tm_mday += val * 7;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractDays(fval, tm, fsec, 7);
|
2008-11-11 03:42:33 +01:00
|
|
|
break;
|
|
|
|
case 'D':
|
|
|
|
tm->tm_mday += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
|
2008-11-11 03:42:33 +01:00
|
|
|
break;
|
2009-06-11 16:49:15 +02:00
|
|
|
case 'T': /* ISO 8601 4.4.3.3 Alternative Format / Basic */
|
2008-11-11 03:42:33 +01:00
|
|
|
case '\0':
|
|
|
|
if (ISO8601IntegerWidth(fieldstart) == 8 && !havefield)
|
|
|
|
{
|
|
|
|
tm->tm_year += val / 10000;
|
2009-06-11 16:49:15 +02:00
|
|
|
tm->tm_mon += (val / 100) % 100;
|
2008-11-11 03:42:33 +01:00
|
|
|
tm->tm_mday += val % 100;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
|
2008-11-11 03:42:33 +01:00
|
|
|
if (unit == '\0')
|
|
|
|
return 0;
|
|
|
|
datepart = false;
|
|
|
|
havefield = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* Else fall through to extended alternative format */
|
2018-05-02 01:35:08 +02:00
|
|
|
/* FALLTHROUGH */
|
2009-06-11 16:49:15 +02:00
|
|
|
case '-': /* ISO 8601 4.4.3.3 Alternative Format,
|
|
|
|
* Extended */
|
2008-11-11 03:42:33 +01:00
|
|
|
if (havefield)
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
|
|
|
|
tm->tm_year += val;
|
2011-03-12 15:31:18 +01:00
|
|
|
tm->tm_mon += (fval * MONTHS_PER_YEAR);
|
2008-11-11 03:42:33 +01:00
|
|
|
if (unit == '\0')
|
|
|
|
return 0;
|
|
|
|
if (unit == 'T')
|
|
|
|
{
|
|
|
|
datepart = false;
|
|
|
|
havefield = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
dterr = ParseISO8601Number(str, &str, &val, &fval);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2009-06-11 16:49:15 +02:00
|
|
|
tm->tm_mon += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractDays(fval, tm, fsec, DAYS_PER_MONTH);
|
2008-11-11 03:42:33 +01:00
|
|
|
if (*str == '\0')
|
|
|
|
return 0;
|
|
|
|
if (*str == 'T')
|
|
|
|
{
|
|
|
|
datepart = false;
|
|
|
|
havefield = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (*str != '-')
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
str++;
|
2009-06-11 16:49:15 +02:00
|
|
|
|
2008-11-11 03:42:33 +01:00
|
|
|
dterr = ParseISO8601Number(str, &str, &val, &fval);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
|
|
|
tm->tm_mday += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
|
2008-11-11 03:42:33 +01:00
|
|
|
if (*str == '\0')
|
|
|
|
return 0;
|
|
|
|
if (*str == 'T')
|
|
|
|
{
|
|
|
|
datepart = false;
|
|
|
|
havefield = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
default:
|
|
|
|
/* not a valid date unit suffix */
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-06-11 16:49:15 +02:00
|
|
|
switch (unit) /* after T: H M S */
|
2008-11-11 03:42:33 +01:00
|
|
|
{
|
|
|
|
case 'H':
|
|
|
|
tm->tm_hour += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR);
|
2008-11-11 03:42:33 +01:00
|
|
|
break;
|
|
|
|
case 'M':
|
|
|
|
tm->tm_min += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(fval, tm, fsec, SECS_PER_MINUTE);
|
2008-11-11 03:42:33 +01:00
|
|
|
break;
|
|
|
|
case 'S':
|
|
|
|
tm->tm_sec += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(fval, tm, fsec, 1);
|
2008-11-11 03:42:33 +01:00
|
|
|
break;
|
2009-06-11 16:49:15 +02:00
|
|
|
case '\0': /* ISO 8601 4.4.3.3 Alternative Format */
|
|
|
|
if (ISO8601IntegerWidth(fieldstart) == 6 && !havefield)
|
2008-11-11 03:42:33 +01:00
|
|
|
{
|
|
|
|
tm->tm_hour += val / 10000;
|
2009-06-11 16:49:15 +02:00
|
|
|
tm->tm_min += (val / 100) % 100;
|
|
|
|
tm->tm_sec += val % 100;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(fval, tm, fsec, 1);
|
2008-11-11 03:42:33 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* Else fall through to extended alternative format */
|
2018-05-02 01:35:08 +02:00
|
|
|
/* FALLTHROUGH */
|
2009-06-11 16:49:15 +02:00
|
|
|
case ':': /* ISO 8601 4.4.3.3 Alternative Format,
|
|
|
|
* Extended */
|
2008-11-11 03:42:33 +01:00
|
|
|
if (havefield)
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
|
|
|
|
tm->tm_hour += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR);
|
2008-11-11 03:42:33 +01:00
|
|
|
if (unit == '\0')
|
|
|
|
return 0;
|
2009-06-11 16:49:15 +02:00
|
|
|
|
2008-11-11 03:42:33 +01:00
|
|
|
dterr = ParseISO8601Number(str, &str, &val, &fval);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2009-06-11 16:49:15 +02:00
|
|
|
tm->tm_min += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(fval, tm, fsec, SECS_PER_MINUTE);
|
2008-11-11 03:42:33 +01:00
|
|
|
if (*str == '\0')
|
|
|
|
return 0;
|
|
|
|
if (*str != ':')
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
str++;
|
2009-06-11 16:49:15 +02:00
|
|
|
|
2008-11-11 03:42:33 +01:00
|
|
|
dterr = ParseISO8601Number(str, &str, &val, &fval);
|
|
|
|
if (dterr)
|
|
|
|
return dterr;
|
2009-06-11 16:49:15 +02:00
|
|
|
tm->tm_sec += val;
|
2008-11-12 02:36:20 +01:00
|
|
|
AdjustFractSeconds(fval, tm, fsec, 1);
|
2008-11-11 03:42:33 +01:00
|
|
|
if (*str == '\0')
|
|
|
|
return 0;
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* not a valid time unit suffix */
|
|
|
|
return DTERR_BAD_FORMAT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
havefield = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* DecodeUnits()
|
|
|
|
* Decode text string using lookup table.
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*
|
|
|
|
* This routine recognizes keywords associated with time interval units.
|
|
|
|
*
|
|
|
|
* Given string must be lowercased already.
|
|
|
|
*
|
|
|
|
* Implement a cache lookup since it is likely that dates
|
|
|
|
* will be related in format.
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
|
|
|
int
|
|
|
|
DecodeUnits(int field, char *lowtoken, int *val)
|
|
|
|
{
|
|
|
|
int type;
|
2006-07-25 05:51:23 +02:00
|
|
|
const datetkn *tp;
|
1997-03-15 00:21:12 +01:00
|
|
|
|
2006-07-25 05:51:23 +02:00
|
|
|
tp = deltacache[field];
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/* use strncmp so that we match truncated tokens */
|
2006-07-25 05:51:23 +02:00
|
|
|
if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
|
|
|
|
{
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
|
2006-07-25 05:51:23 +02:00
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
if (tp == NULL)
|
|
|
|
{
|
2001-09-28 10:09:14 +02:00
|
|
|
type = UNKNOWN_FIELD;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*val = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-07-25 05:51:23 +02:00
|
|
|
deltacache[field] = tp;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
type = tp->type;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
*val = tp->value;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return type;
|
2017-06-21 20:39:04 +02:00
|
|
|
} /* DecodeUnits() */
|
1997-03-15 00:21:12 +01:00
|
|
|
|
2003-08-28 01:29:29 +02:00
|
|
|
/*
|
|
|
|
* Report an error detected by one of the datetime input processing routines.
|
|
|
|
*
|
|
|
|
* dterr is the error code, str is the original input string, datatype is
|
|
|
|
* the name of the datatype we were trying to accept.
|
|
|
|
*
|
|
|
|
* Note: it might seem useless to distinguish DTERR_INTERVAL_OVERFLOW and
|
|
|
|
* DTERR_TZDISP_OVERFLOW from DTERR_FIELD_OVERFLOW, but SQL99 mandates three
|
|
|
|
* separate SQLSTATE codes, so ...
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
DateTimeParseError(int dterr, const char *str, const char *datatype)
|
|
|
|
{
|
|
|
|
switch (dterr)
|
|
|
|
{
|
|
|
|
case DTERR_FIELD_OVERFLOW:
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
|
|
|
|
errmsg("date/time field value out of range: \"%s\"",
|
|
|
|
str)));
|
|
|
|
break;
|
|
|
|
case DTERR_MD_FIELD_OVERFLOW:
|
|
|
|
/* <nanny>same as above, but add hint about DateStyle</nanny> */
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
|
|
|
|
errmsg("date/time field value out of range: \"%s\"",
|
|
|
|
str),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errhint("Perhaps you need a different \"datestyle\" setting.")));
|
2003-08-28 01:29:29 +02:00
|
|
|
break;
|
|
|
|
case DTERR_INTERVAL_OVERFLOW:
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INTERVAL_FIELD_OVERFLOW),
|
|
|
|
errmsg("interval field value out of range: \"%s\"",
|
|
|
|
str)));
|
|
|
|
break;
|
|
|
|
case DTERR_TZDISP_OVERFLOW:
|
|
|
|
ereport(ERROR,
|
2005-10-15 04:49:52 +02:00
|
|
|
(errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
|
|
|
|
errmsg("time zone displacement out of range: \"%s\"",
|
|
|
|
str)));
|
2003-08-28 01:29:29 +02:00
|
|
|
break;
|
|
|
|
case DTERR_BAD_FORMAT:
|
|
|
|
default:
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
|
2003-09-25 08:58:07 +02:00
|
|
|
errmsg("invalid input syntax for type %s: \"%s\"",
|
2003-08-28 01:29:29 +02:00
|
|
|
datatype, str)));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1997-03-15 00:21:12 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* datebsearch()
|
|
|
|
* Binary search -- from Knuth (6.2.1) Algorithm B. Special case like this
|
|
|
|
* is WAY faster than the generic bsearch().
|
|
|
|
*/
|
2006-07-25 05:51:23 +02:00
|
|
|
static const datetkn *
|
|
|
|
datebsearch(const char *key, const datetkn *base, int nel)
|
1997-03-15 00:21:12 +01:00
|
|
|
{
|
2011-05-11 02:36:22 +02:00
|
|
|
if (nel > 0)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2011-05-11 02:36:22 +02:00
|
|
|
const datetkn *last = base + nel - 1,
|
|
|
|
*position;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
while (last >= base)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2011-05-11 02:36:22 +02:00
|
|
|
position = base + ((last - base) >> 1);
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/* precheck the first character for a bit of extra speed */
|
|
|
|
result = (int) key[0] - (int) position->token[0];
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
if (result == 0)
|
2011-05-11 02:36:22 +02:00
|
|
|
{
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/* use strncmp so that we match truncated tokens */
|
2011-05-11 02:36:22 +02:00
|
|
|
result = strncmp(key, position->token, TOKMAXLEN);
|
|
|
|
if (result == 0)
|
|
|
|
return position;
|
|
|
|
}
|
|
|
|
if (result < 0)
|
|
|
|
last = position - 1;
|
|
|
|
else
|
|
|
|
base = position + 1;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
1997-03-15 00:21:12 +01:00
|
|
|
|
2006-10-17 23:03:21 +02:00
|
|
|
/* EncodeTimezone()
|
2016-02-07 05:11:28 +01:00
|
|
|
* Copies representation of a numeric timezone offset to str.
|
|
|
|
*
|
|
|
|
* Returns a pointer to the new end of string. No NUL terminator is put
|
|
|
|
* there; callers are responsible for NUL terminating str themselves.
|
2006-10-17 23:03:21 +02:00
|
|
|
*/
|
2016-02-07 05:11:28 +01:00
|
|
|
static char *
|
2007-03-01 15:52:04 +01:00
|
|
|
EncodeTimezone(char *str, int tz, int style)
|
2006-10-17 23:03:21 +02:00
|
|
|
{
|
|
|
|
int hour,
|
|
|
|
min,
|
|
|
|
sec;
|
|
|
|
|
|
|
|
sec = abs(tz);
|
|
|
|
min = sec / SECS_PER_MINUTE;
|
|
|
|
sec -= min * SECS_PER_MINUTE;
|
|
|
|
hour = min / MINS_PER_HOUR;
|
|
|
|
min -= hour * MINS_PER_HOUR;
|
|
|
|
|
|
|
|
/* TZ is negated compared to sign we wish to display ... */
|
|
|
|
*str++ = (tz <= 0 ? '+' : '-');
|
|
|
|
|
|
|
|
if (sec != 0)
|
2016-02-07 05:11:28 +01:00
|
|
|
{
|
|
|
|
str = pg_ltostr_zeropad(str, hour, 2);
|
|
|
|
*str++ = ':';
|
|
|
|
str = pg_ltostr_zeropad(str, min, 2);
|
|
|
|
*str++ = ':';
|
|
|
|
str = pg_ltostr_zeropad(str, sec, 2);
|
|
|
|
}
|
2007-03-01 15:52:04 +01:00
|
|
|
else if (min != 0 || style == USE_XSD_DATES)
|
2016-02-07 05:11:28 +01:00
|
|
|
{
|
|
|
|
str = pg_ltostr_zeropad(str, hour, 2);
|
|
|
|
*str++ = ':';
|
|
|
|
str = pg_ltostr_zeropad(str, min, 2);
|
|
|
|
}
|
2006-10-17 23:03:21 +02:00
|
|
|
else
|
2016-02-07 05:11:28 +01:00
|
|
|
str = pg_ltostr_zeropad(str, hour, 2);
|
|
|
|
return str;
|
2006-10-17 23:03:21 +02:00
|
|
|
}
|
1997-03-15 00:21:12 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* EncodeDateOnly()
|
|
|
|
* Encode date as local time.
|
|
|
|
*/
|
2009-05-26 04:17:50 +02:00
|
|
|
void
|
2017-06-21 20:39:04 +02:00
|
|
|
EncodeDateOnly(struct pg_tm *tm, int style, char *str)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2009-05-26 04:17:50 +02:00
|
|
|
Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
|
1997-05-16 09:19:50 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
switch (style)
|
|
|
|
{
|
|
|
|
case USE_ISO_DATES:
|
2007-03-01 15:52:04 +01:00
|
|
|
case USE_XSD_DATES:
|
2001-09-28 10:09:14 +02:00
|
|
|
/* compatible with ISO date formats */
|
2016-02-07 05:11:28 +01:00
|
|
|
str = pg_ltostr_zeropad(str,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
|
2016-02-07 05:11:28 +01:00
|
|
|
*str++ = '-';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
|
|
|
|
*str++ = '-';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
1997-05-16 09:19:50 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
case USE_SQL_DATES:
|
2001-09-28 10:09:14 +02:00
|
|
|
/* compatible with Oracle/Ingres date formats */
|
2003-07-29 02:03:19 +02:00
|
|
|
if (DateOrder == DATEORDER_DMY)
|
2016-02-07 05:11:28 +01:00
|
|
|
{
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
|
|
|
|
*str++ = '/';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
|
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
else
|
2016-02-07 05:11:28 +01:00
|
|
|
{
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
|
|
|
|
*str++ = '/';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
|
|
|
|
}
|
|
|
|
*str++ = '/';
|
|
|
|
str = pg_ltostr_zeropad(str,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
1997-07-01 02:22:46 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
case USE_GERMAN_DATES:
|
2001-09-28 10:09:14 +02:00
|
|
|
/* German-style date format */
|
2016-02-07 05:11:28 +01:00
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
|
|
|
|
*str++ = '.';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
|
|
|
|
*str++ = '.';
|
|
|
|
str = pg_ltostr_zeropad(str,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
1997-03-15 00:21:12 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
case USE_POSTGRES_DATES:
|
|
|
|
default:
|
2001-09-28 10:09:14 +02:00
|
|
|
/* traditional date-only style for Postgres */
|
2003-07-29 02:03:19 +02:00
|
|
|
if (DateOrder == DATEORDER_DMY)
|
2016-02-07 05:11:28 +01:00
|
|
|
{
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
|
|
|
|
*str++ = '-';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
|
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
else
|
2016-02-07 05:11:28 +01:00
|
|
|
{
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
|
|
|
|
*str++ = '-';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
|
|
|
|
}
|
|
|
|
*str++ = '-';
|
|
|
|
str = pg_ltostr_zeropad(str,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
|
|
|
}
|
2016-02-07 05:11:28 +01:00
|
|
|
|
|
|
|
if (tm->tm_year <= 0)
|
|
|
|
{
|
|
|
|
memcpy(str, " BC", 3); /* Don't copy NUL */
|
|
|
|
str += 3;
|
|
|
|
}
|
|
|
|
*str = '\0';
|
2009-05-26 04:17:50 +02:00
|
|
|
}
|
1997-03-15 00:21:12 +01:00
|
|
|
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* EncodeTimeOnly()
|
|
|
|
* Encode time fields only.
|
2012-03-14 22:03:34 +01:00
|
|
|
*
|
|
|
|
* tm and fsec are the value to encode, print_tz determines whether to include
|
|
|
|
* a time zone (the difference between time and timetz types), tz is the
|
|
|
|
* numeric time zone offset, style is the date style, str is where to write the
|
|
|
|
* output.
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
2009-05-26 04:17:50 +02:00
|
|
|
void
|
2017-06-21 20:39:04 +02:00
|
|
|
EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
|
1997-03-15 00:21:12 +01:00
|
|
|
{
|
2016-02-07 05:11:28 +01:00
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
|
|
|
|
*str++ = ':';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_min, 2);
|
|
|
|
*str++ = ':';
|
|
|
|
str = AppendSeconds(str, tm->tm_sec, fsec, MAX_TIME_PRECISION, true);
|
2012-03-14 22:03:34 +01:00
|
|
|
if (print_tz)
|
2016-02-07 05:11:28 +01:00
|
|
|
str = EncodeTimezone(str, tz, style);
|
|
|
|
*str = '\0';
|
2009-05-26 04:17:50 +02:00
|
|
|
}
|
1997-03-15 00:21:12 +01:00
|
|
|
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
/* EncodeDateTime()
|
|
|
|
* Encode date and time interpreted as local time.
|
2012-03-14 22:03:34 +01:00
|
|
|
*
|
|
|
|
* tm and fsec are the value to encode, print_tz determines whether to include
|
|
|
|
* a time zone (the difference between timestamp and timestamptz types), tz is
|
|
|
|
* the numeric time zone offset, tzn is the textual time zone, which if
|
|
|
|
* specified will be used instead of tz by some styles, style is the date
|
|
|
|
* style, str is where to write the output.
|
|
|
|
*
|
|
|
|
* Supported date styles:
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
* Postgres - day mon hh:mm:ss yyyy tz
|
|
|
|
* SQL - mm/dd/yyyy hh:mm:ss.ss tz
|
|
|
|
* ISO - yyyy-mm-dd hh:mm:ss+/-tz
|
2001-12-29 19:31:48 +01:00
|
|
|
* German - dd.mm.yyyy hh:mm:ss tz
|
2007-03-01 15:52:04 +01:00
|
|
|
* XSD - yyyy-mm-ddThh:mm:ss.ss+/-tz
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
*/
|
2009-05-26 04:17:50 +02:00
|
|
|
void
|
2017-06-21 20:39:04 +02:00
|
|
|
EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
|
1997-03-15 00:21:12 +01:00
|
|
|
{
|
2006-10-17 23:03:21 +02:00
|
|
|
int day;
|
2002-09-04 22:31:48 +02:00
|
|
|
|
2005-07-21 05:56:25 +02:00
|
|
|
Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
|
1997-03-15 00:21:12 +01:00
|
|
|
|
2012-03-14 22:03:34 +01:00
|
|
|
/*
|
|
|
|
* Negative tm_isdst means we have no valid time zone translation.
|
|
|
|
*/
|
|
|
|
if (tm->tm_isdst < 0)
|
|
|
|
print_tz = false;
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
switch (style)
|
|
|
|
{
|
|
|
|
case USE_ISO_DATES:
|
2007-03-01 15:52:04 +01:00
|
|
|
case USE_XSD_DATES:
|
2002-04-21 21:52:18 +02:00
|
|
|
/* Compatible with ISO-8601 date formats */
|
2016-02-07 05:11:28 +01:00
|
|
|
str = pg_ltostr_zeropad(str,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
|
2016-02-07 05:11:28 +01:00
|
|
|
*str++ = '-';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
|
|
|
|
*str++ = '-';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
|
|
|
|
*str++ = (style == USE_ISO_DATES) ? ' ' : 'T';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
|
|
|
|
*str++ = ':';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_min, 2);
|
|
|
|
*str++ = ':';
|
|
|
|
str = AppendTimestampSeconds(str, tm, fsec);
|
2012-03-14 22:03:34 +01:00
|
|
|
if (print_tz)
|
2016-02-07 05:11:28 +01:00
|
|
|
str = EncodeTimezone(str, tz, style);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
1997-03-15 00:21:12 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
case USE_SQL_DATES:
|
2002-04-21 21:52:18 +02:00
|
|
|
/* Compatible with Oracle/Ingres date formats */
|
2003-07-29 02:03:19 +02:00
|
|
|
if (DateOrder == DATEORDER_DMY)
|
2016-02-07 05:11:28 +01:00
|
|
|
{
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
|
|
|
|
*str++ = '/';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
|
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
else
|
2016-02-07 05:11:28 +01:00
|
|
|
{
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
|
|
|
|
*str++ = '/';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
|
|
|
|
}
|
|
|
|
*str++ = '/';
|
|
|
|
str = pg_ltostr_zeropad(str,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
|
2016-02-07 05:11:28 +01:00
|
|
|
*str++ = ' ';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
|
|
|
|
*str++ = ':';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_min, 2);
|
|
|
|
*str++ = ':';
|
|
|
|
str = AppendTimestampSeconds(str, tm, fsec);
|
2001-10-03 07:29:27 +02:00
|
|
|
|
2010-05-08 18:39:53 +02:00
|
|
|
/*
|
2010-05-09 04:16:00 +02:00
|
|
|
* Note: the uses of %.*s in this function would be risky if the
|
|
|
|
* timezone names ever contain non-ASCII characters. However, all
|
2016-02-07 05:11:28 +01:00
|
|
|
* TZ abbreviations in the IANA database are plain ASCII.
|
2010-05-08 18:39:53 +02:00
|
|
|
*/
|
2012-03-14 22:03:34 +01:00
|
|
|
if (print_tz)
|
2002-04-21 21:52:18 +02:00
|
|
|
{
|
2012-03-14 22:03:34 +01:00
|
|
|
if (tzn)
|
2016-02-07 05:11:28 +01:00
|
|
|
{
|
|
|
|
sprintf(str, " %.*s", MAXTZLEN, tzn);
|
|
|
|
str += strlen(str);
|
|
|
|
}
|
2002-04-21 21:52:18 +02:00
|
|
|
else
|
2016-02-07 05:11:28 +01:00
|
|
|
str = EncodeTimezone(str, tz, style);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
break;
|
1997-03-15 00:21:12 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
case USE_GERMAN_DATES:
|
2002-04-21 21:52:18 +02:00
|
|
|
/* German variant on European style */
|
2016-02-07 05:11:28 +01:00
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
|
|
|
|
*str++ = '.';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
|
|
|
|
*str++ = '.';
|
|
|
|
str = pg_ltostr_zeropad(str,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
|
2016-02-07 05:11:28 +01:00
|
|
|
*str++ = ' ';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
|
|
|
|
*str++ = ':';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_min, 2);
|
|
|
|
*str++ = ':';
|
|
|
|
str = AppendTimestampSeconds(str, tm, fsec);
|
2001-10-03 07:29:27 +02:00
|
|
|
|
2012-03-14 22:03:34 +01:00
|
|
|
if (print_tz)
|
2002-04-21 21:52:18 +02:00
|
|
|
{
|
2012-03-14 22:03:34 +01:00
|
|
|
if (tzn)
|
2016-02-07 05:11:28 +01:00
|
|
|
{
|
|
|
|
sprintf(str, " %.*s", MAXTZLEN, tzn);
|
|
|
|
str += strlen(str);
|
|
|
|
}
|
2002-04-21 21:52:18 +02:00
|
|
|
else
|
2016-02-07 05:11:28 +01:00
|
|
|
str = EncodeTimezone(str, tz, style);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
break;
|
1997-03-15 00:21:12 +01:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
case USE_POSTGRES_DATES:
|
|
|
|
default:
|
2002-04-21 21:52:18 +02:00
|
|
|
/* Backward-compatible with traditional Postgres abstime dates */
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
|
|
|
|
tm->tm_wday = j2day(day);
|
Replace a bunch more uses of strncpy() with safer coding.
strncpy() has a well-deserved reputation for being unsafe, so make an
effort to get rid of nearly all occurrences in HEAD.
A large fraction of the remaining uses were passing length less than or
equal to the known strlen() of the source, in which case no null-padding
can occur and the behavior is equivalent to memcpy(), though doubtless
slower and certainly harder to reason about. So just use memcpy() in
these cases.
In other cases, use either StrNCpy() or strlcpy() as appropriate (depending
on whether padding to the full length of the destination buffer seems
useful).
I left a few strncpy() calls alone in the src/timezone/ code, to keep it
in sync with upstream (the IANA tzcode distribution). There are also a
few such calls in ecpg that could possibly do with more analysis.
AFAICT, none of these changes are more than cosmetic, except for the four
occurrences in fe-secure-openssl.c, which are in fact buggy: an overlength
source leads to a non-null-terminated destination buffer and ensuing
misbehavior. These don't seem like security issues, first because no stack
clobber is possible and second because if your values of sslcert etc are
coming from untrusted sources then you've got problems way worse than this.
Still, it's undesirable to have unpredictable behavior for overlength
inputs, so back-patch those four changes to all active branches.
2015-01-24 19:05:42 +01:00
|
|
|
memcpy(str, days[tm->tm_wday], 3);
|
2016-02-07 05:11:28 +01:00
|
|
|
str += 3;
|
|
|
|
*str++ = ' ';
|
2003-07-29 02:03:19 +02:00
|
|
|
if (DateOrder == DATEORDER_DMY)
|
2016-02-07 05:11:28 +01:00
|
|
|
{
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
|
|
|
|
*str++ = ' ';
|
|
|
|
memcpy(str, months[tm->tm_mon - 1], 3);
|
|
|
|
str += 3;
|
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
else
|
2016-02-07 05:11:28 +01:00
|
|
|
{
|
|
|
|
memcpy(str, months[tm->tm_mon - 1], 3);
|
|
|
|
str += 3;
|
|
|
|
*str++ = ' ';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
|
|
|
|
}
|
|
|
|
*str++ = ' ';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
|
|
|
|
*str++ = ':';
|
|
|
|
str = pg_ltostr_zeropad(str, tm->tm_min, 2);
|
|
|
|
*str++ = ':';
|
|
|
|
str = AppendTimestampSeconds(str, tm, fsec);
|
|
|
|
*str++ = ' ';
|
|
|
|
str = pg_ltostr_zeropad(str,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
|
2001-10-18 19:30:21 +02:00
|
|
|
|
2012-03-14 22:03:34 +01:00
|
|
|
if (print_tz)
|
2002-04-21 21:52:18 +02:00
|
|
|
{
|
2012-03-14 22:03:34 +01:00
|
|
|
if (tzn)
|
2016-02-07 05:11:28 +01:00
|
|
|
{
|
|
|
|
sprintf(str, " %.*s", MAXTZLEN, tzn);
|
|
|
|
str += strlen(str);
|
|
|
|
}
|
2002-04-21 21:52:18 +02:00
|
|
|
else
|
2001-10-18 19:30:21 +02:00
|
|
|
{
|
2002-04-21 21:52:18 +02:00
|
|
|
/*
|
2002-09-04 22:31:48 +02:00
|
|
|
* We have a time zone, but no string version. Use the
|
2005-10-15 04:49:52 +02:00
|
|
|
* numeric form, but be sure to include a leading space to
|
|
|
|
* avoid formatting something which would be rejected by
|
|
|
|
* the date/time parser later. - thomas 2001-10-19
|
2002-04-21 21:52:18 +02:00
|
|
|
*/
|
2016-02-07 05:11:28 +01:00
|
|
|
*str++ = ' ';
|
|
|
|
str = EncodeTimezone(str, tz, style);
|
2001-10-18 19:30:21 +02:00
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-02-07 05:11:28 +01:00
|
|
|
|
|
|
|
if (tm->tm_year <= 0)
|
|
|
|
{
|
|
|
|
memcpy(str, " BC", 3); /* Don't copy NUL */
|
|
|
|
str += 3;
|
|
|
|
}
|
|
|
|
*str = '\0';
|
2004-07-11 06:57:20 +02:00
|
|
|
}
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 20:36:24 +02:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
|
2008-11-09 01:28:35 +01:00
|
|
|
/*
|
2008-11-11 03:42:33 +01:00
|
|
|
* Helper functions to avoid duplicated code in EncodeInterval.
|
2008-11-09 01:28:35 +01:00
|
|
|
*/
|
2008-11-12 02:36:20 +01:00
|
|
|
|
|
|
|
/* Append an ISO-8601-style interval field, but only if value isn't zero */
|
|
|
|
static char *
|
|
|
|
AddISO8601IntPart(char *cp, int value, char units)
|
2008-11-09 01:28:35 +01:00
|
|
|
{
|
2008-11-12 02:36:20 +01:00
|
|
|
if (value == 0)
|
|
|
|
return cp;
|
|
|
|
sprintf(cp, "%d%c", value, units);
|
|
|
|
return cp + strlen(cp);
|
2008-11-09 01:28:35 +01:00
|
|
|
}
|
|
|
|
|
2008-11-12 02:36:20 +01:00
|
|
|
/* Append a postgres-style interval field, but only if value isn't zero */
|
2008-11-11 03:42:33 +01:00
|
|
|
static char *
|
2008-11-12 02:36:20 +01:00
|
|
|
AddPostgresIntPart(char *cp, int value, const char *units,
|
|
|
|
bool *is_zero, bool *is_before)
|
2008-11-11 03:42:33 +01:00
|
|
|
{
|
|
|
|
if (value == 0)
|
|
|
|
return cp;
|
2008-11-12 02:36:20 +01:00
|
|
|
sprintf(cp, "%s%s%d %s%s",
|
|
|
|
(!*is_zero) ? " " : "",
|
|
|
|
(*is_before && value > 0) ? "+" : "",
|
|
|
|
value,
|
|
|
|
units,
|
|
|
|
(value != 1) ? "s" : "");
|
2009-06-11 16:49:15 +02:00
|
|
|
|
2008-11-12 02:36:20 +01:00
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* Each nonzero field sets is_before for (only) the next one. This is a
|
|
|
|
* tad bizarre but it's how it worked before...
|
2008-11-12 02:36:20 +01:00
|
|
|
*/
|
|
|
|
*is_before = (value < 0);
|
2017-08-16 06:22:32 +02:00
|
|
|
*is_zero = false;
|
2008-11-12 02:36:20 +01:00
|
|
|
return cp + strlen(cp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Append a verbose-style interval field, but only if value isn't zero */
|
|
|
|
static char *
|
|
|
|
AddVerboseIntPart(char *cp, int value, const char *units,
|
|
|
|
bool *is_zero, bool *is_before)
|
|
|
|
{
|
|
|
|
if (value == 0)
|
|
|
|
return cp;
|
|
|
|
/* first nonzero value sets is_before */
|
|
|
|
if (*is_zero)
|
|
|
|
{
|
|
|
|
*is_before = (value < 0);
|
|
|
|
value = abs(value);
|
|
|
|
}
|
|
|
|
else if (*is_before)
|
|
|
|
value = -value;
|
|
|
|
sprintf(cp, " %d %s%s", value, units, (value == 1) ? "" : "s");
|
2017-08-16 06:22:32 +02:00
|
|
|
*is_zero = false;
|
2008-11-11 03:42:33 +01:00
|
|
|
return cp + strlen(cp);
|
|
|
|
}
|
|
|
|
|
2008-11-09 01:28:35 +01:00
|
|
|
|
2002-04-21 21:52:18 +02:00
|
|
|
/* EncodeInterval()
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
* Interpret time structure as a delta time and convert to string.
|
|
|
|
*
|
|
|
|
* Support "traditional Postgres" and ISO-8601 styles.
|
|
|
|
* Actually, afaik ISO does not address time interval formatting,
|
|
|
|
* but this looks similar to the spec for absolute date/time.
|
|
|
|
* - thomas 1998-04-30
|
2008-11-09 01:28:35 +01:00
|
|
|
*
|
|
|
|
* Actually, afaik, ISO 8601 does specify formats for "time
|
|
|
|
* intervals...[of the]...format with time-unit designators", which
|
|
|
|
* are pretty ugly. The format looks something like
|
2009-06-11 16:49:15 +02:00
|
|
|
* P1Y1M1DT1H1M1.12345S
|
2008-11-09 01:28:35 +01:00
|
|
|
* but useful for exchanging data with computers instead of humans.
|
|
|
|
* - ron 2003-07-14
|
|
|
|
*
|
|
|
|
* And ISO's SQL 2008 standard specifies standards for
|
|
|
|
* "year-month literal"s (that look like '2-3') and
|
|
|
|
* "day-time literal"s (that look like ('4 5:6:7')
|
1997-10-25 07:16:09 +02:00
|
|
|
*/
|
2009-05-26 04:17:50 +02:00
|
|
|
void
|
2017-06-21 20:39:04 +02:00
|
|
|
EncodeInterval(struct pg_tm *tm, fsec_t fsec, int style, char *str)
|
1997-10-25 07:16:09 +02:00
|
|
|
{
|
2008-11-09 01:28:35 +01:00
|
|
|
char *cp = str;
|
|
|
|
int year = tm->tm_year;
|
2009-06-11 16:49:15 +02:00
|
|
|
int mon = tm->tm_mon;
|
2008-11-09 01:28:35 +01:00
|
|
|
int mday = tm->tm_mday;
|
|
|
|
int hour = tm->tm_hour;
|
2009-06-11 16:49:15 +02:00
|
|
|
int min = tm->tm_min;
|
|
|
|
int sec = tm->tm_sec;
|
2017-08-16 06:22:32 +02:00
|
|
|
bool is_before = false;
|
|
|
|
bool is_zero = true;
|
1997-10-25 07:16:09 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
/*
|
|
|
|
* The sign of year and month are guaranteed to match, since they are
|
2005-10-15 04:49:52 +02:00
|
|
|
* stored internally as "month". But we'll need to check for is_before and
|
2008-11-12 02:36:20 +01:00
|
|
|
* is_zero when determining the signs of day and hour/minute/seconds
|
2008-11-09 01:28:35 +01:00
|
|
|
* fields.
|
2000-11-06 16:57:00 +01:00
|
|
|
*/
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
switch (style)
|
|
|
|
{
|
2009-06-11 16:49:15 +02:00
|
|
|
/* SQL Standard interval format */
|
2008-11-09 01:28:35 +01:00
|
|
|
case INTSTYLE_SQL_STANDARD:
|
|
|
|
{
|
2009-06-11 16:49:15 +02:00
|
|
|
bool has_negative = year < 0 || mon < 0 ||
|
|
|
|
mday < 0 || hour < 0 ||
|
|
|
|
min < 0 || sec < 0 || fsec < 0;
|
|
|
|
bool has_positive = year > 0 || mon > 0 ||
|
|
|
|
mday > 0 || hour > 0 ||
|
|
|
|
min > 0 || sec > 0 || fsec > 0;
|
|
|
|
bool has_year_month = year != 0 || mon != 0;
|
|
|
|
bool has_day_time = mday != 0 || hour != 0 ||
|
|
|
|
min != 0 || sec != 0 || fsec != 0;
|
|
|
|
bool has_day = mday != 0;
|
|
|
|
bool sql_standard_value = !(has_negative && has_positive) &&
|
|
|
|
!(has_year_month && has_day_time);
|
2008-11-09 01:28:35 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* SQL Standard wants only 1 "<sign>" preceding the whole
|
|
|
|
* interval ... but can't do that if mixed signs.
|
|
|
|
*/
|
|
|
|
if (has_negative && sql_standard_value)
|
|
|
|
{
|
|
|
|
*cp++ = '-';
|
|
|
|
year = -year;
|
2009-06-11 16:49:15 +02:00
|
|
|
mon = -mon;
|
2008-11-09 01:28:35 +01:00
|
|
|
mday = -mday;
|
|
|
|
hour = -hour;
|
2009-06-11 16:49:15 +02:00
|
|
|
min = -min;
|
|
|
|
sec = -sec;
|
2008-11-09 01:28:35 +01:00
|
|
|
fsec = -fsec;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!has_negative && !has_positive)
|
|
|
|
{
|
|
|
|
sprintf(cp, "0");
|
|
|
|
}
|
|
|
|
else if (!sql_standard_value)
|
|
|
|
{
|
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* For non sql-standard interval values, force outputting
|
|
|
|
* the signs to avoid ambiguities with intervals with
|
|
|
|
* mixed sign components.
|
2008-11-09 01:28:35 +01:00
|
|
|
*/
|
2009-06-11 16:49:15 +02:00
|
|
|
char year_sign = (year < 0 || mon < 0) ? '-' : '+';
|
|
|
|
char day_sign = (mday < 0) ? '-' : '+';
|
|
|
|
char sec_sign = (hour < 0 || min < 0 ||
|
|
|
|
sec < 0 || fsec < 0) ? '-' : '+';
|
2008-11-09 01:28:35 +01:00
|
|
|
|
2008-11-11 03:42:33 +01:00
|
|
|
sprintf(cp, "%c%d-%d %c%d %c%d:%02d:",
|
2008-11-09 01:28:35 +01:00
|
|
|
year_sign, abs(year), abs(mon),
|
|
|
|
day_sign, abs(mday),
|
|
|
|
sec_sign, abs(hour), abs(min));
|
|
|
|
cp += strlen(cp);
|
2016-02-07 05:11:28 +01:00
|
|
|
cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
|
|
|
|
*cp = '\0';
|
2008-11-09 01:28:35 +01:00
|
|
|
}
|
|
|
|
else if (has_year_month)
|
|
|
|
{
|
|
|
|
sprintf(cp, "%d-%d", year, mon);
|
|
|
|
}
|
|
|
|
else if (has_day)
|
|
|
|
{
|
2008-11-11 03:42:33 +01:00
|
|
|
sprintf(cp, "%d %d:%02d:", mday, hour, min);
|
2008-11-09 01:28:35 +01:00
|
|
|
cp += strlen(cp);
|
2016-02-07 05:11:28 +01:00
|
|
|
cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
|
|
|
|
*cp = '\0';
|
2008-11-09 01:28:35 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-11-11 03:42:33 +01:00
|
|
|
sprintf(cp, "%d:%02d:", hour, min);
|
2008-11-09 01:28:35 +01:00
|
|
|
cp += strlen(cp);
|
2016-02-07 05:11:28 +01:00
|
|
|
cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
|
|
|
|
*cp = '\0';
|
2008-11-09 01:28:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2009-06-11 16:49:15 +02:00
|
|
|
/* ISO 8601 "time-intervals by duration only" */
|
2008-11-11 03:42:33 +01:00
|
|
|
case INTSTYLE_ISO_8601:
|
|
|
|
/* special-case zero to avoid printing nothing */
|
|
|
|
if (year == 0 && mon == 0 && mday == 0 &&
|
2009-06-11 16:49:15 +02:00
|
|
|
hour == 0 && min == 0 && sec == 0 && fsec == 0)
|
2008-11-11 03:42:33 +01:00
|
|
|
{
|
|
|
|
sprintf(cp, "PT0S");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*cp++ = 'P';
|
2008-11-12 02:36:20 +01:00
|
|
|
cp = AddISO8601IntPart(cp, year, 'Y');
|
2009-06-11 16:49:15 +02:00
|
|
|
cp = AddISO8601IntPart(cp, mon, 'M');
|
2008-11-12 02:36:20 +01:00
|
|
|
cp = AddISO8601IntPart(cp, mday, 'D');
|
2008-11-11 03:42:33 +01:00
|
|
|
if (hour != 0 || min != 0 || sec != 0 || fsec != 0)
|
|
|
|
*cp++ = 'T';
|
2008-11-12 02:36:20 +01:00
|
|
|
cp = AddISO8601IntPart(cp, hour, 'H');
|
2009-06-11 16:49:15 +02:00
|
|
|
cp = AddISO8601IntPart(cp, min, 'M');
|
2008-11-11 03:42:33 +01:00
|
|
|
if (sec != 0 || fsec != 0)
|
|
|
|
{
|
|
|
|
if (sec < 0 || fsec < 0)
|
|
|
|
*cp++ = '-';
|
2016-02-07 05:11:28 +01:00
|
|
|
cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, false);
|
2008-11-11 03:42:33 +01:00
|
|
|
*cp++ = 'S';
|
|
|
|
*cp++ = '\0';
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2009-06-11 16:49:15 +02:00
|
|
|
/* Compatible with postgresql < 8.4 when DateStyle = 'iso' */
|
2008-11-09 01:28:35 +01:00
|
|
|
case INTSTYLE_POSTGRES:
|
2008-11-12 02:36:20 +01:00
|
|
|
cp = AddPostgresIntPart(cp, year, "year", &is_zero, &is_before);
|
2011-06-09 20:32:50 +02:00
|
|
|
|
2011-05-25 05:24:44 +02:00
|
|
|
/*
|
2011-06-09 20:32:50 +02:00
|
|
|
* Ideally we should spell out "month" like we do for "year" and
|
|
|
|
* "day". However, for backward compatibility, we can't easily
|
|
|
|
* fix this. bjm 2011-05-24
|
2011-05-25 05:24:44 +02:00
|
|
|
*/
|
2008-11-12 02:36:20 +01:00
|
|
|
cp = AddPostgresIntPart(cp, mon, "mon", &is_zero, &is_before);
|
|
|
|
cp = AddPostgresIntPart(cp, mday, "day", &is_zero, &is_before);
|
|
|
|
if (is_zero || hour != 0 || min != 0 || sec != 0 || fsec != 0)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2009-06-11 16:49:15 +02:00
|
|
|
bool minus = (hour < 0 || min < 0 || sec < 0 || fsec < 0);
|
2000-11-06 16:57:00 +01:00
|
|
|
|
2008-11-12 02:36:20 +01:00
|
|
|
sprintf(cp, "%s%s%02d:%02d:",
|
|
|
|
is_zero ? "" : " ",
|
2001-01-18 08:22:43 +01:00
|
|
|
(minus ? "-" : (is_before ? "+" : "")),
|
2008-11-12 02:36:20 +01:00
|
|
|
abs(hour), abs(min));
|
2008-11-09 01:28:35 +01:00
|
|
|
cp += strlen(cp);
|
2016-02-07 05:11:28 +01:00
|
|
|
cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
|
|
|
|
*cp = '\0';
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
|
|
|
break;
|
1997-10-25 07:16:09 +02:00
|
|
|
|
2009-06-11 16:49:15 +02:00
|
|
|
/* Compatible with postgresql < 8.4 when DateStyle != 'iso' */
|
2008-11-09 01:28:35 +01:00
|
|
|
case INTSTYLE_POSTGRES_VERBOSE:
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
default:
|
2008-11-12 02:36:20 +01:00
|
|
|
strcpy(cp, "@");
|
|
|
|
cp++;
|
|
|
|
cp = AddVerboseIntPart(cp, year, "year", &is_zero, &is_before);
|
|
|
|
cp = AddVerboseIntPart(cp, mon, "mon", &is_zero, &is_before);
|
|
|
|
cp = AddVerboseIntPart(cp, mday, "day", &is_zero, &is_before);
|
|
|
|
cp = AddVerboseIntPart(cp, hour, "hour", &is_zero, &is_before);
|
|
|
|
cp = AddVerboseIntPart(cp, min, "min", &is_zero, &is_before);
|
|
|
|
if (sec != 0 || fsec != 0)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
{
|
2008-11-12 02:36:20 +01:00
|
|
|
*cp++ = ' ';
|
|
|
|
if (sec < 0 || (sec == 0 && fsec < 0))
|
2005-04-20 19:14:50 +02:00
|
|
|
{
|
2008-11-12 02:36:20 +01:00
|
|
|
if (is_zero)
|
2017-08-16 06:22:32 +02:00
|
|
|
is_before = true;
|
2008-11-12 02:36:20 +01:00
|
|
|
else if (!is_before)
|
|
|
|
*cp++ = '-';
|
2005-04-20 19:14:50 +02:00
|
|
|
}
|
2008-11-12 02:36:20 +01:00
|
|
|
else if (is_before)
|
|
|
|
*cp++ = '-';
|
2016-02-07 05:11:28 +01:00
|
|
|
cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, false);
|
2008-11-12 02:36:20 +01:00
|
|
|
sprintf(cp, " sec%s",
|
|
|
|
(abs(sec) != 1 || fsec != 0) ? "s" : "");
|
2017-08-16 06:22:32 +02:00
|
|
|
is_zero = false;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
}
|
2008-11-09 01:28:35 +01:00
|
|
|
/* identically zero? then put in a unitless zero... */
|
2008-11-12 02:36:20 +01:00
|
|
|
if (is_zero)
|
|
|
|
strcat(cp, " 0");
|
2008-11-09 01:28:35 +01:00
|
|
|
if (is_before)
|
|
|
|
strcat(cp, " ago");
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 19:17:02 +01:00
|
|
|
break;
|
1997-10-25 07:16:09 +02:00
|
|
|
}
|
2009-05-26 04:17:50 +02:00
|
|
|
}
|
2001-06-18 18:14:44 +02:00
|
|
|
|
|
|
|
|
2003-01-16 01:26:49 +01:00
|
|
|
/*
|
|
|
|
* We've been burnt by stupid errors in the ordering of the datetkn tables
|
2014-05-06 18:12:18 +02:00
|
|
|
* once too often. Arrange to check them during postmaster start.
|
2003-01-16 01:26:49 +01:00
|
|
|
*/
|
|
|
|
static bool
|
2006-07-25 05:51:23 +02:00
|
|
|
CheckDateTokenTable(const char *tablename, const datetkn *base, int nel)
|
2003-01-16 01:26:49 +01:00
|
|
|
{
|
|
|
|
bool ok = true;
|
2006-07-25 05:51:23 +02:00
|
|
|
int i;
|
2003-01-16 01:26:49 +01:00
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
for (i = 0; i < nel; i++)
|
2003-01-16 01:26:49 +01:00
|
|
|
{
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/* check for token strings that don't fit */
|
|
|
|
if (strlen(base[i].token) > TOKMAXLEN)
|
2003-01-16 01:26:49 +01:00
|
|
|
{
|
2010-05-08 18:39:53 +02:00
|
|
|
/* %.*s is safe since all our tokens are ASCII */
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
elog(LOG, "token too long in %s table: \"%.*s\"",
|
2003-01-16 01:26:49 +01:00
|
|
|
tablename,
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
TOKMAXLEN + 1, base[i].token);
|
|
|
|
ok = false;
|
|
|
|
break; /* don't risk applying strcmp */
|
|
|
|
}
|
|
|
|
/* check for out of order */
|
|
|
|
if (i > 0 &&
|
|
|
|
strcmp(base[i - 1].token, base[i].token) >= 0)
|
|
|
|
{
|
|
|
|
elog(LOG, "ordering error in %s table: \"%s\" >= \"%s\"",
|
|
|
|
tablename,
|
|
|
|
base[i - 1].token,
|
|
|
|
base[i].token);
|
2003-01-16 01:26:49 +01:00
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
CheckDateTokenTables(void)
|
|
|
|
{
|
|
|
|
bool ok = true;
|
|
|
|
|
2003-04-04 06:50:44 +02:00
|
|
|
Assert(UNIX_EPOCH_JDATE == date2j(1970, 1, 1));
|
|
|
|
Assert(POSTGRES_EPOCH_JDATE == date2j(2000, 1, 1));
|
|
|
|
|
2003-01-16 01:26:49 +01:00
|
|
|
ok &= CheckDateTokenTable("datetktbl", datetktbl, szdatetktbl);
|
|
|
|
ok &= CheckDateTokenTable("deltatktbl", deltatktbl, szdeltatktbl);
|
|
|
|
return ok;
|
|
|
|
}
|
2006-07-25 05:51:23 +02:00
|
|
|
|
2012-02-08 15:33:02 +01:00
|
|
|
/*
|
2019-02-10 00:08:48 +01:00
|
|
|
* Common code for temporal prosupport functions: simplify, if possible,
|
|
|
|
* a call to a temporal type's length-coercion function.
|
|
|
|
*
|
|
|
|
* Types time, timetz, timestamp and timestamptz each have a range of allowed
|
|
|
|
* precisions. An unspecified precision is rigorously equivalent to the
|
|
|
|
* highest specifiable precision. We can replace the function call with a
|
|
|
|
* no-op RelabelType if it is coercing to the same or higher precision as the
|
|
|
|
* input is known to have.
|
|
|
|
*
|
|
|
|
* The input Node is always a FuncExpr, but to reduce the #include footprint
|
|
|
|
* of datetime.h, we declare it as Node *.
|
2012-03-23 22:29:57 +01:00
|
|
|
*
|
|
|
|
* Note: timestamp_scale throws an error when the typmod is out of range, but
|
|
|
|
* we can't get there from a cast: our typmodin will have caught it already.
|
2012-02-08 15:33:02 +01:00
|
|
|
*/
|
|
|
|
Node *
|
2019-02-10 00:08:48 +01:00
|
|
|
TemporalSimplify(int32 max_precis, Node *node)
|
2012-02-08 15:33:02 +01:00
|
|
|
{
|
2017-02-21 17:33:07 +01:00
|
|
|
FuncExpr *expr = castNode(FuncExpr, node);
|
2012-02-08 15:33:02 +01:00
|
|
|
Node *ret = NULL;
|
2012-03-23 22:29:57 +01:00
|
|
|
Node *typmod;
|
2012-02-08 15:33:02 +01:00
|
|
|
|
2012-03-23 22:29:57 +01:00
|
|
|
Assert(list_length(expr->args) >= 2);
|
2012-02-08 15:33:02 +01:00
|
|
|
|
2012-03-23 22:29:57 +01:00
|
|
|
typmod = (Node *) lsecond(expr->args);
|
2012-02-08 15:33:02 +01:00
|
|
|
|
2012-06-10 21:20:04 +02:00
|
|
|
if (IsA(typmod, Const) &&!((Const *) typmod)->constisnull)
|
2012-02-08 15:33:02 +01:00
|
|
|
{
|
2012-03-23 22:29:57 +01:00
|
|
|
Node *source = (Node *) linitial(expr->args);
|
2012-02-08 15:33:02 +01:00
|
|
|
int32 old_precis = exprTypmod(source);
|
|
|
|
int32 new_precis = DatumGetInt32(((Const *) typmod)->constvalue);
|
|
|
|
|
2012-03-23 22:29:57 +01:00
|
|
|
if (new_precis < 0 || new_precis == max_precis ||
|
|
|
|
(old_precis >= 0 && new_precis >= old_precis))
|
2012-02-08 15:33:02 +01:00
|
|
|
ret = relabel_to_typmod(source, new_precis);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2006-07-25 05:51:23 +02:00
|
|
|
/*
|
|
|
|
* This function gets called during timezone config file load or reload
|
|
|
|
* to create the final array of timezone tokens. The argument array
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
* is already sorted in name order.
|
|
|
|
*
|
|
|
|
* The result is a TimeZoneAbbrevTable (which must be a single malloc'd chunk)
|
|
|
|
* or NULL on malloc failure. No other error conditions are defined.
|
2006-07-25 05:51:23 +02:00
|
|
|
*/
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
TimeZoneAbbrevTable *
|
|
|
|
ConvertTimeZoneAbbrevs(struct tzEntry *abbrevs, int n)
|
2006-07-25 05:51:23 +02:00
|
|
|
{
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
TimeZoneAbbrevTable *tbl;
|
|
|
|
Size tbl_size;
|
2006-07-25 05:51:23 +02:00
|
|
|
int i;
|
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/* Space for fixed fields and datetkn array */
|
|
|
|
tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
|
|
|
|
n * sizeof(datetkn);
|
|
|
|
tbl_size = MAXALIGN(tbl_size);
|
|
|
|
/* Count up space for dynamic abbreviations */
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
{
|
|
|
|
struct tzEntry *abbr = abbrevs + i;
|
|
|
|
|
|
|
|
if (abbr->zone != NULL)
|
|
|
|
{
|
|
|
|
Size dsize;
|
|
|
|
|
|
|
|
dsize = offsetof(DynamicZoneAbbrev, zone) +
|
|
|
|
strlen(abbr->zone) + 1;
|
|
|
|
tbl_size += MAXALIGN(dsize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Alloc the result ... */
|
|
|
|
tbl = malloc(tbl_size);
|
|
|
|
if (!tbl)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* ... and fill it in */
|
|
|
|
tbl->tblsize = tbl_size;
|
2011-04-07 06:11:01 +02:00
|
|
|
tbl->numabbrevs = n;
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/* in this loop, tbl_size reprises the space calculation above */
|
|
|
|
tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
|
|
|
|
n * sizeof(datetkn);
|
|
|
|
tbl_size = MAXALIGN(tbl_size);
|
2006-07-25 05:51:23 +02:00
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
{
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
struct tzEntry *abbr = abbrevs + i;
|
|
|
|
datetkn *dtoken = tbl->abbrevs + i;
|
|
|
|
|
|
|
|
/* use strlcpy to truncate name if necessary */
|
|
|
|
strlcpy(dtoken->token, abbr->abbrev, TOKMAXLEN + 1);
|
|
|
|
if (abbr->zone != NULL)
|
|
|
|
{
|
|
|
|
/* Allocate a DynamicZoneAbbrev for this abbreviation */
|
|
|
|
DynamicZoneAbbrev *dtza;
|
|
|
|
Size dsize;
|
|
|
|
|
|
|
|
dtza = (DynamicZoneAbbrev *) ((char *) tbl + tbl_size);
|
|
|
|
dtza->tz = NULL;
|
|
|
|
strcpy(dtza->zone, abbr->zone);
|
|
|
|
|
|
|
|
dtoken->type = DYNTZ;
|
|
|
|
/* value is offset from table start to DynamicZoneAbbrev */
|
|
|
|
dtoken->value = (int32) tbl_size;
|
|
|
|
|
|
|
|
dsize = offsetof(DynamicZoneAbbrev, zone) +
|
|
|
|
strlen(abbr->zone) + 1;
|
|
|
|
tbl_size += MAXALIGN(dsize);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dtoken->type = abbr->is_dst ? DTZ : TZ;
|
|
|
|
dtoken->value = abbr->offset;
|
|
|
|
}
|
2006-07-25 05:51:23 +02:00
|
|
|
}
|
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/* Assert the two loops above agreed on size calculations */
|
|
|
|
Assert(tbl->tblsize == tbl_size);
|
|
|
|
|
2006-07-25 05:51:23 +02:00
|
|
|
/* Check the ordering, if testing */
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
Assert(CheckDateTokenTable("timezone abbreviations", tbl->abbrevs, n));
|
|
|
|
|
|
|
|
return tbl;
|
2011-04-07 06:11:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Install a TimeZoneAbbrevTable as the active table.
|
|
|
|
*
|
|
|
|
* Caller is responsible that the passed table doesn't go away while in use.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
InstallTimeZoneAbbrevs(TimeZoneAbbrevTable *tbl)
|
|
|
|
{
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
zoneabbrevtbl = tbl;
|
|
|
|
/* reset abbrevcache, which may contain pointers into old table */
|
|
|
|
memset(abbrevcache, 0, sizeof(abbrevcache));
|
|
|
|
}
|
2006-07-25 05:51:23 +02:00
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/*
|
|
|
|
* Helper subroutine to locate pg_tz timezone for a dynamic abbreviation.
|
|
|
|
*/
|
|
|
|
static pg_tz *
|
|
|
|
FetchDynamicTimeZone(TimeZoneAbbrevTable *tbl, const datetkn *tp)
|
|
|
|
{
|
|
|
|
DynamicZoneAbbrev *dtza;
|
2006-07-25 05:51:23 +02:00
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/* Just some sanity checks to prevent indexing off into nowhere */
|
|
|
|
Assert(tp->type == DYNTZ);
|
|
|
|
Assert(tp->value > 0 && tp->value < tbl->tblsize);
|
|
|
|
|
|
|
|
dtza = (DynamicZoneAbbrev *) ((char *) tbl + tp->value);
|
|
|
|
|
|
|
|
/* Look up the underlying zone if we haven't already */
|
|
|
|
if (dtza->tz == NULL)
|
|
|
|
{
|
|
|
|
dtza->tz = pg_tzset(dtza->zone);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ideally we'd let the caller ereport instead of doing it here, but
|
|
|
|
* then there is no way to report the bad time zone name.
|
|
|
|
*/
|
|
|
|
if (dtza->tz == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
|
|
errmsg("time zone \"%s\" not recognized",
|
|
|
|
dtza->zone),
|
|
|
|
errdetail("This time zone name appears in the configuration file for time zone abbreviation \"%s\".",
|
|
|
|
tp->token)));
|
|
|
|
}
|
|
|
|
return dtza->tz;
|
2006-07-25 05:51:23 +02:00
|
|
|
}
|
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
|
2006-07-25 05:51:23 +02:00
|
|
|
/*
|
|
|
|
* This set-returning function reads all the available time zone abbreviations
|
2006-09-16 22:14:34 +02:00
|
|
|
* and returns a set of (abbrev, utc_offset, is_dst).
|
2006-07-25 05:51:23 +02:00
|
|
|
*/
|
|
|
|
Datum
|
2006-09-16 22:14:34 +02:00
|
|
|
pg_timezone_abbrevs(PG_FUNCTION_ARGS)
|
2006-07-25 05:51:23 +02:00
|
|
|
{
|
2006-10-04 02:30:14 +02:00
|
|
|
FuncCallContext *funcctx;
|
|
|
|
int *pindex;
|
|
|
|
Datum result;
|
|
|
|
HeapTuple tuple;
|
|
|
|
Datum values[3];
|
|
|
|
bool nulls[3];
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
const datetkn *tp;
|
2006-10-04 02:30:14 +02:00
|
|
|
char buffer[TOKMAXLEN + 1];
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
int gmtoffset;
|
|
|
|
bool is_dst;
|
2006-10-04 02:30:14 +02:00
|
|
|
unsigned char *p;
|
|
|
|
struct pg_tm tm;
|
|
|
|
Interval *resInterval;
|
2006-07-25 05:51:23 +02:00
|
|
|
|
|
|
|
/* stuff done only on the first call of the function */
|
|
|
|
if (SRF_IS_FIRSTCALL())
|
|
|
|
{
|
2006-10-04 02:30:14 +02:00
|
|
|
TupleDesc tupdesc;
|
|
|
|
MemoryContext oldcontext;
|
2006-07-25 05:51:23 +02:00
|
|
|
|
|
|
|
/* create a function context for cross-call persistence */
|
|
|
|
funcctx = SRF_FIRSTCALL_INIT();
|
|
|
|
|
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* switch to memory context appropriate for multiple function calls
|
2006-07-25 05:51:23 +02:00
|
|
|
*/
|
|
|
|
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
|
|
|
|
|
|
|
/* allocate memory for user context */
|
|
|
|
pindex = (int *) palloc(sizeof(int));
|
|
|
|
*pindex = 0;
|
|
|
|
funcctx->user_fctx = (void *) pindex;
|
|
|
|
|
|
|
|
/*
|
2006-09-16 22:14:34 +02:00
|
|
|
* build tupdesc for result tuples. This must match this function's
|
|
|
|
* pg_proc entry!
|
2006-07-25 05:51:23 +02:00
|
|
|
*/
|
Remove WITH OIDS support, change oid catalog column visibility.
Previously tables declared WITH OIDS, including a significant fraction
of the catalog tables, stored the oid column not as a normal column,
but as part of the tuple header.
This special column was not shown by default, which was somewhat odd,
as it's often (consider e.g. pg_class.oid) one of the more important
parts of a row. Neither pg_dump nor COPY included the contents of the
oid column by default.
The fact that the oid column was not an ordinary column necessitated a
significant amount of special case code to support oid columns. That
already was painful for the existing, but upcoming work aiming to make
table storage pluggable, would have required expanding and duplicating
that "specialness" significantly.
WITH OIDS has been deprecated since 2005 (commit ff02d0a05280e0).
Remove it.
Removing includes:
- CREATE TABLE and ALTER TABLE syntax for declaring the table to be
WITH OIDS has been removed (WITH (oids[ = true]) will error out)
- pg_dump does not support dumping tables declared WITH OIDS and will
issue a warning when dumping one (and ignore the oid column).
- restoring an pg_dump archive with pg_restore will warn when
restoring a table with oid contents (and ignore the oid column)
- COPY will refuse to load binary dump that includes oids.
- pg_upgrade will error out when encountering tables declared WITH
OIDS, they have to be altered to remove the oid column first.
- Functionality to access the oid of the last inserted row (like
plpgsql's RESULT_OID, spi's SPI_lastoid, ...) has been removed.
The syntax for declaring a table WITHOUT OIDS (or WITH (oids = false)
for CREATE TABLE) is still supported. While that requires a bit of
support code, it seems unnecessary to break applications / dumps that
do not use oids, and are explicit about not using them.
The biggest user of WITH OID columns was postgres' catalog. This
commit changes all 'magic' oid columns to be columns that are normally
declared and stored. To reduce unnecessary query breakage all the
newly added columns are still named 'oid', even if a table's column
naming scheme would indicate 'reloid' or such. This obviously
requires adapting a lot code, mostly replacing oid access via
HeapTupleGetOid() with access to the underlying Form_pg_*->oid column.
The bootstrap process now assigns oids for all oid columns in
genbki.pl that do not have an explicit value (starting at the largest
oid previously used), only oids assigned later by oids will be above
FirstBootstrapObjectId. As the oid column now is a normal column the
special bootstrap syntax for oids has been removed.
Oids are not automatically assigned during insertion anymore, all
backend code explicitly assigns oids with GetNewOidWithIndex(). For
the rare case that insertions into the catalog via SQL are called for
the new pg_nextoid() function can be used (which only works on catalog
tables).
The fact that oid columns on system tables are now normal columns
means that they will be included in the set of columns expanded
by * (i.e. SELECT * FROM pg_class will now include the table's oid,
previously it did not). It'd not technically be hard to hide oid
column by default, but that'd mean confusing behavior would either
have to be carried forward forever, or it'd cause breakage down the
line.
While it's not unlikely that further adjustments are needed, the
scope/invasiveness of the patch makes it worthwhile to get merge this
now. It's painful to maintain externally, too complicated to commit
after the code code freeze, and a dependency of a number of other
patches.
Catversion bump, for obvious reasons.
Author: Andres Freund, with contributions by John Naylor
Discussion: https://postgr.es/m/20180930034810.ywp2c7awz7opzcfr@alap3.anarazel.de
2018-11-21 00:36:57 +01:00
|
|
|
tupdesc = CreateTemplateTupleDesc(3);
|
2006-09-16 22:14:34 +02:00
|
|
|
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "abbrev",
|
2006-07-25 05:51:23 +02:00
|
|
|
TEXTOID, -1, 0);
|
|
|
|
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "utc_offset",
|
|
|
|
INTERVALOID, -1, 0);
|
|
|
|
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "is_dst",
|
|
|
|
BOOLOID, -1, 0);
|
|
|
|
|
|
|
|
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* stuff done on every call of the function */
|
|
|
|
funcctx = SRF_PERCALL_SETUP();
|
|
|
|
pindex = (int *) funcctx->user_fctx;
|
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
if (zoneabbrevtbl == NULL ||
|
|
|
|
*pindex >= zoneabbrevtbl->numabbrevs)
|
2006-07-25 05:51:23 +02:00
|
|
|
SRF_RETURN_DONE(funcctx);
|
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
tp = zoneabbrevtbl->abbrevs + *pindex;
|
|
|
|
|
|
|
|
switch (tp->type)
|
|
|
|
{
|
|
|
|
case TZ:
|
|
|
|
gmtoffset = tp->value;
|
|
|
|
is_dst = false;
|
|
|
|
break;
|
|
|
|
case DTZ:
|
|
|
|
gmtoffset = tp->value;
|
|
|
|
is_dst = true;
|
|
|
|
break;
|
|
|
|
case DYNTZ:
|
|
|
|
{
|
|
|
|
/* Determine the current meaning of the abbrev */
|
|
|
|
pg_tz *tzp;
|
|
|
|
TimestampTz now;
|
|
|
|
int isdst;
|
|
|
|
|
|
|
|
tzp = FetchDynamicTimeZone(zoneabbrevtbl, tp);
|
|
|
|
now = GetCurrentTransactionStartTimestamp();
|
|
|
|
gmtoffset = -DetermineTimeZoneAbbrevOffsetTS(now,
|
|
|
|
tp->token,
|
|
|
|
tzp,
|
|
|
|
&isdst);
|
|
|
|
is_dst = (bool) isdst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
elog(ERROR, "unrecognized timezone type %d", (int) tp->type);
|
|
|
|
gmtoffset = 0; /* keep compiler quiet */
|
|
|
|
is_dst = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-07-25 05:51:23 +02:00
|
|
|
MemSet(nulls, 0, sizeof(nulls));
|
|
|
|
|
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* Convert name to text, using upcasing conversion that is the inverse of
|
|
|
|
* what ParseDateTime() uses.
|
2006-07-25 05:51:23 +02:00
|
|
|
*/
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
strlcpy(buffer, tp->token, sizeof(buffer));
|
2006-07-25 05:51:23 +02:00
|
|
|
for (p = (unsigned char *) buffer; *p; p++)
|
|
|
|
*p = pg_toupper(*p);
|
|
|
|
|
2008-03-25 23:42:46 +01:00
|
|
|
values[0] = CStringGetTextDatum(buffer);
|
2006-07-25 05:51:23 +02:00
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
/* Convert offset (in seconds) to an interval */
|
2006-07-25 05:51:23 +02:00
|
|
|
MemSet(&tm, 0, sizeof(struct pg_tm));
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
tm.tm_sec = gmtoffset;
|
2006-07-25 05:51:23 +02:00
|
|
|
resInterval = (Interval *) palloc(sizeof(Interval));
|
|
|
|
tm2interval(&tm, 0, resInterval);
|
|
|
|
values[1] = IntervalPGetDatum(resInterval);
|
|
|
|
|
Support timezone abbreviations that sometimes change.
Up to now, PG has assumed that any given timezone abbreviation (such as
"EDT") represents a constant GMT offset in the usage of any particular
region; we had a way to configure what that offset was, but not for it
to be changeable over time. But, as with most things horological, this
view of the world is too simplistic: there are numerous regions that have
at one time or another switched to a different GMT offset but kept using
the same timezone abbreviation. Almost the entire Russian Federation did
that a few years ago, and later this month they're going to do it again.
And there are similar examples all over the world.
To cope with this, invent the notion of a "dynamic timezone abbreviation",
which is one that is referenced to a particular underlying timezone
(as defined in the IANA timezone database) and means whatever it currently
means in that zone. For zones that use or have used daylight-savings time,
the standard and DST abbreviations continue to have the property that you
can specify standard or DST time and get that time offset whether or not
DST was theoretically in effect at the time. However, the abbreviations
mean what they meant at the time in question (or most recently before that
time) rather than being absolutely fixed.
The standard abbreviation-list files have been changed to use this behavior
for abbreviations that have actually varied in meaning since 1970. The
old simple-numeric definitions are kept for abbreviations that have not
changed, since they are a bit faster to resolve.
While this is clearly a new feature, it seems necessary to back-patch it
into all active branches, because otherwise use of Russian zone
abbreviations is going to become even more problematic than it already was.
This change supersedes the changes in commit 513d06ded et al to modify the
fixed meanings of the Russian abbreviations; since we've not shipped that
yet, this will avoid an undesirably incompatible (not to mention incorrect)
change in behavior for timestamps between 2011 and 2014.
This patch makes some cosmetic changes in ecpglib to keep its usage of
datetime lookup tables as similar as possible to the backend code, but
doesn't do anything about the increasingly obsolete set of timezone
abbreviation definitions that are hard-wired into ecpglib. Whatever we
do about that will likely not be appropriate material for back-patching.
Also, a potential free() of a garbage pointer after an out-of-memory
failure in ecpglib has been fixed.
This patch also fixes pre-existing bugs in DetermineTimeZoneOffset() that
caused it to produce unexpected results near a timezone transition, if
both the "before" and "after" states are marked as standard time. We'd
only ever thought about or tested transitions between standard and DST
time, but that's not what's happening when a zone simply redefines their
base GMT offset.
In passing, update the SGML documentation to refer to the Olson/zoneinfo/
zic timezone database as the "IANA" database, since it's now being
maintained under the auspices of IANA.
2014-10-16 21:22:10 +02:00
|
|
|
values[2] = BoolGetDatum(is_dst);
|
2006-07-25 05:51:23 +02:00
|
|
|
|
|
|
|
(*pindex)++;
|
|
|
|
|
|
|
|
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
|
|
|
|
result = HeapTupleGetDatum(tuple);
|
|
|
|
|
|
|
|
SRF_RETURN_NEXT(funcctx, result);
|
|
|
|
}
|
2006-09-16 22:14:34 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This set-returning function reads all the available full time zones
|
|
|
|
* and returns a set of (name, abbrev, utc_offset, is_dst).
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
pg_timezone_names(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2006-10-04 02:30:14 +02:00
|
|
|
MemoryContext oldcontext;
|
|
|
|
FuncCallContext *funcctx;
|
|
|
|
pg_tzenum *tzenum;
|
|
|
|
pg_tz *tz;
|
|
|
|
Datum result;
|
|
|
|
HeapTuple tuple;
|
|
|
|
Datum values[4];
|
|
|
|
bool nulls[4];
|
2006-09-16 22:14:34 +02:00
|
|
|
int tzoff;
|
2006-10-04 02:30:14 +02:00
|
|
|
struct pg_tm tm;
|
2006-09-16 22:14:34 +02:00
|
|
|
fsec_t fsec;
|
2012-03-15 20:17:19 +01:00
|
|
|
const char *tzn;
|
2006-10-04 02:30:14 +02:00
|
|
|
Interval *resInterval;
|
|
|
|
struct pg_tm itm;
|
2006-09-16 22:14:34 +02:00
|
|
|
|
|
|
|
/* stuff done only on the first call of the function */
|
|
|
|
if (SRF_IS_FIRSTCALL())
|
|
|
|
{
|
2006-10-04 02:30:14 +02:00
|
|
|
TupleDesc tupdesc;
|
2006-09-16 22:14:34 +02:00
|
|
|
|
|
|
|
/* create a function context for cross-call persistence */
|
|
|
|
funcctx = SRF_FIRSTCALL_INIT();
|
|
|
|
|
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* switch to memory context appropriate for multiple function calls
|
2006-09-16 22:14:34 +02:00
|
|
|
*/
|
|
|
|
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
|
|
|
|
|
|
|
/* initialize timezone scanning code */
|
|
|
|
tzenum = pg_tzenumerate_start();
|
|
|
|
funcctx->user_fctx = (void *) tzenum;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* build tupdesc for result tuples. This must match this function's
|
|
|
|
* pg_proc entry!
|
|
|
|
*/
|
Remove WITH OIDS support, change oid catalog column visibility.
Previously tables declared WITH OIDS, including a significant fraction
of the catalog tables, stored the oid column not as a normal column,
but as part of the tuple header.
This special column was not shown by default, which was somewhat odd,
as it's often (consider e.g. pg_class.oid) one of the more important
parts of a row. Neither pg_dump nor COPY included the contents of the
oid column by default.
The fact that the oid column was not an ordinary column necessitated a
significant amount of special case code to support oid columns. That
already was painful for the existing, but upcoming work aiming to make
table storage pluggable, would have required expanding and duplicating
that "specialness" significantly.
WITH OIDS has been deprecated since 2005 (commit ff02d0a05280e0).
Remove it.
Removing includes:
- CREATE TABLE and ALTER TABLE syntax for declaring the table to be
WITH OIDS has been removed (WITH (oids[ = true]) will error out)
- pg_dump does not support dumping tables declared WITH OIDS and will
issue a warning when dumping one (and ignore the oid column).
- restoring an pg_dump archive with pg_restore will warn when
restoring a table with oid contents (and ignore the oid column)
- COPY will refuse to load binary dump that includes oids.
- pg_upgrade will error out when encountering tables declared WITH
OIDS, they have to be altered to remove the oid column first.
- Functionality to access the oid of the last inserted row (like
plpgsql's RESULT_OID, spi's SPI_lastoid, ...) has been removed.
The syntax for declaring a table WITHOUT OIDS (or WITH (oids = false)
for CREATE TABLE) is still supported. While that requires a bit of
support code, it seems unnecessary to break applications / dumps that
do not use oids, and are explicit about not using them.
The biggest user of WITH OID columns was postgres' catalog. This
commit changes all 'magic' oid columns to be columns that are normally
declared and stored. To reduce unnecessary query breakage all the
newly added columns are still named 'oid', even if a table's column
naming scheme would indicate 'reloid' or such. This obviously
requires adapting a lot code, mostly replacing oid access via
HeapTupleGetOid() with access to the underlying Form_pg_*->oid column.
The bootstrap process now assigns oids for all oid columns in
genbki.pl that do not have an explicit value (starting at the largest
oid previously used), only oids assigned later by oids will be above
FirstBootstrapObjectId. As the oid column now is a normal column the
special bootstrap syntax for oids has been removed.
Oids are not automatically assigned during insertion anymore, all
backend code explicitly assigns oids with GetNewOidWithIndex(). For
the rare case that insertions into the catalog via SQL are called for
the new pg_nextoid() function can be used (which only works on catalog
tables).
The fact that oid columns on system tables are now normal columns
means that they will be included in the set of columns expanded
by * (i.e. SELECT * FROM pg_class will now include the table's oid,
previously it did not). It'd not technically be hard to hide oid
column by default, but that'd mean confusing behavior would either
have to be carried forward forever, or it'd cause breakage down the
line.
While it's not unlikely that further adjustments are needed, the
scope/invasiveness of the patch makes it worthwhile to get merge this
now. It's painful to maintain externally, too complicated to commit
after the code code freeze, and a dependency of a number of other
patches.
Catversion bump, for obvious reasons.
Author: Andres Freund, with contributions by John Naylor
Discussion: https://postgr.es/m/20180930034810.ywp2c7awz7opzcfr@alap3.anarazel.de
2018-11-21 00:36:57 +01:00
|
|
|
tupdesc = CreateTemplateTupleDesc(4);
|
2006-09-16 22:14:34 +02:00
|
|
|
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
|
|
|
|
TEXTOID, -1, 0);
|
|
|
|
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "abbrev",
|
|
|
|
TEXTOID, -1, 0);
|
|
|
|
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "utc_offset",
|
|
|
|
INTERVALOID, -1, 0);
|
|
|
|
TupleDescInitEntry(tupdesc, (AttrNumber) 4, "is_dst",
|
|
|
|
BOOLOID, -1, 0);
|
|
|
|
|
|
|
|
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* stuff done on every call of the function */
|
|
|
|
funcctx = SRF_PERCALL_SETUP();
|
|
|
|
tzenum = (pg_tzenum *) funcctx->user_fctx;
|
|
|
|
|
|
|
|
/* search for another zone to display */
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
|
|
|
tz = pg_tzenumerate_next(tzenum);
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
|
|
|
|
if (!tz)
|
|
|
|
{
|
|
|
|
pg_tzenumerate_end(tzenum);
|
|
|
|
funcctx->user_fctx = NULL;
|
|
|
|
SRF_RETURN_DONE(funcctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert now() to local time in this zone */
|
|
|
|
if (timestamp2tm(GetCurrentTransactionStartTimestamp(),
|
|
|
|
&tzoff, &tm, &fsec, &tzn, tz) != 0)
|
|
|
|
continue; /* ignore if conversion fails */
|
|
|
|
|
2016-10-20 00:11:49 +02:00
|
|
|
/*
|
Tweak our special-case logic for the IANA "Factory" timezone.
pg_timezone_names() tries to avoid showing the "Factory" zone in
the view, mainly because that has traditionally had a very long
"abbreviation" such as "Local time zone must be set--see zic manual page",
so that showing it messes up psql's formatting of the whole view.
Since tzdb version 2016g, IANA instead uses the abbreviation "-00",
which is sane enough that there's no reason to discriminate against it.
On the other hand, it emerges that FreeBSD and possibly other packagers
are so wedded to backwards compatibility that they hack the IANA data
to keep the old spelling --- and not just that old spelling, but even
older spellings that IANA used back in the stone age. This caused the
filter logic to fail to suppress "Factory" at all on such platforms,
though the formatting problem is definitely real in that case.
To solve both problems, get rid of the hard-wired assumption about
exactly what Factory's abbreviation is, and instead reject abbreviations
exceeding 31 characters. This will allow Factory to appear in the view
if and only if it's using the modern abbreviation.
In passing, simplify the code we add to zic.c to support "zic -P"
to remove its now-obsolete hacks to not print the Factory zone's
abbreviation. Unlike pg_timezone_names(), there's no reason for
that code to support old/nonstandard timezone data.
Since we generally prefer to keep timezone-related behavior the
same in all branches, and since this is arguably a bug fix,
back-patch to all supported branches.
Discussion: https://postgr.es/m/3961.1564086915@sss.pgh.pa.us
2019-07-26 19:07:08 +02:00
|
|
|
* IANA's rather silly "Factory" time zone used to emit ridiculously
|
|
|
|
* long "abbreviations" such as "Local time zone must be set--see zic
|
|
|
|
* manual page" or "Local time zone must be set--use tzsetup". While
|
|
|
|
* modern versions of tzdb emit the much saner "-00", it seems some
|
|
|
|
* benighted packagers are hacking the IANA data so that it continues
|
|
|
|
* to produce these strings. To prevent producing a weirdly wide
|
|
|
|
* abbrev column, reject ridiculously long abbreviations.
|
2016-10-20 00:11:49 +02:00
|
|
|
*/
|
Tweak our special-case logic for the IANA "Factory" timezone.
pg_timezone_names() tries to avoid showing the "Factory" zone in
the view, mainly because that has traditionally had a very long
"abbreviation" such as "Local time zone must be set--see zic manual page",
so that showing it messes up psql's formatting of the whole view.
Since tzdb version 2016g, IANA instead uses the abbreviation "-00",
which is sane enough that there's no reason to discriminate against it.
On the other hand, it emerges that FreeBSD and possibly other packagers
are so wedded to backwards compatibility that they hack the IANA data
to keep the old spelling --- and not just that old spelling, but even
older spellings that IANA used back in the stone age. This caused the
filter logic to fail to suppress "Factory" at all on such platforms,
though the formatting problem is definitely real in that case.
To solve both problems, get rid of the hard-wired assumption about
exactly what Factory's abbreviation is, and instead reject abbreviations
exceeding 31 characters. This will allow Factory to appear in the view
if and only if it's using the modern abbreviation.
In passing, simplify the code we add to zic.c to support "zic -P"
to remove its now-obsolete hacks to not print the Factory zone's
abbreviation. Unlike pg_timezone_names(), there's no reason for
that code to support old/nonstandard timezone data.
Since we generally prefer to keep timezone-related behavior the
same in all branches, and since this is arguably a bug fix,
back-patch to all supported branches.
Discussion: https://postgr.es/m/3961.1564086915@sss.pgh.pa.us
2019-07-26 19:07:08 +02:00
|
|
|
if (tzn && strlen(tzn) > 31)
|
2006-09-16 22:14:34 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Found a displayable zone */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
MemSet(nulls, 0, sizeof(nulls));
|
|
|
|
|
2008-03-25 23:42:46 +01:00
|
|
|
values[0] = CStringGetTextDatum(pg_get_timezone_name(tz));
|
|
|
|
values[1] = CStringGetTextDatum(tzn ? tzn : "");
|
2006-09-16 22:14:34 +02:00
|
|
|
|
|
|
|
MemSet(&itm, 0, sizeof(struct pg_tm));
|
|
|
|
itm.tm_sec = -tzoff;
|
|
|
|
resInterval = (Interval *) palloc(sizeof(Interval));
|
|
|
|
tm2interval(&itm, 0, resInterval);
|
|
|
|
values[2] = IntervalPGetDatum(resInterval);
|
|
|
|
|
|
|
|
values[3] = BoolGetDatum(tm.tm_isdst > 0);
|
|
|
|
|
|
|
|
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
|
|
|
|
result = HeapTupleGetDatum(tuple);
|
|
|
|
|
|
|
|
SRF_RETURN_NEXT(funcctx, result);
|
|
|
|
}
|