Discussion:
[Firebird-devel] CURRENT_TIMESTAMP
Lester Caine
2005-12-01 19:42:13 UTC
Permalink
Starting to hit a major problem with inter database compatibility,
relating to NOW and CURRENT_TIMESTAMP. The convention seems to be that
CURRENT_TIMESTAMP returns a UTC normalized time while LOCAL_TIMESTAMP
and NOW provides the server time.

Anyway what I need to do is load the database with the current UTC time
to match other engines. Option one is to ensure that the server is
running GMT, then I don't have a problem, but is there any way of
getting a UTC time within SQL without having to 'bodge' the server time?

The main reason for wanting to do this is to ensure that times loaded in
slave databases match when the data is joined in the master copy -
probably in another time zone.
--
Lester Caine
-----------------------------
L.S.Caine Electronic Services
Treasurer - Firebird Foundation Inc.
Leyne, Sean
2005-12-01 21:26:11 UTC
Permalink
Lester,
Post by Lester Caine
Starting to hit a major problem with inter database compatibility,
relating to NOW and CURRENT_TIMESTAMP. The convention seems to be that
CURRENT_TIMESTAMP returns a UTC normalized time while LOCAL_TIMESTAMP
and NOW provides the server time.
A point of clarification.

Are you saying that CURRENT_TIMESTAMP returns time that assumes the
server is running in GMT?


Sean
Lester Caine
2005-12-02 03:18:01 UTC
Permalink
Post by Leyne, Sean
Lester,
Post by Lester Caine
Starting to hit a major problem with inter database compatibility,
relating to NOW and CURRENT_TIMESTAMP. The convention seems to be that
CURRENT_TIMESTAMP returns a UTC normalized time while LOCAL_TIMESTAMP
and NOW provides the server time.
A point of clarification.
Are you saying that CURRENT_TIMESTAMP returns time that assumes the
server is running in GMT?
That is the point of heated debate on the bitweaver IRC. In order that
we can synchronized between sites, all timestamps are managed as GMT
time, so you know exactly 'when' you are. The client displays are then
either UTC(GMT) or are local time (offset by the current timezone).
Since 'NOW' returns the current server time in Firebird I have to
provide a PHP timestamp to ensure that the right time is returned, but I
am being forceably told that the database should take care of that. I do
not agree that MySQL or Postgres do anything else, ( THEY provide a
LOCAL_TIMESTAMP Alan but I can't tell what their CURRENT_TIMESTAMP
actually returns because I don't use them )

The debate seems to be centered about including the timezone data with
the timestamp when you store it so you know both the local time and GMT,
but I see a problem with that in that the fact that the timezone does
not know about daylight savings, so the only thing that you can safely
store is a clean GMT time. The local display of historic data has a
similar problem in that you need both daylight saving and timezone
accurate to the client site calendar.

The discussion on the identification of local time against a particular
GMT timestamp is probably one for the architect list, but I have already
been caught out by the CURRENT_TIMESTAMP problem as the server switches
daylight savings settings - hence the 'fix' of only running the server
on GMT! When the clocks go ON we get an extra hour, when the clocks go
back we get negative durations :(

( My railway stuff has historical always run GMT just for this reason )
--
Lester Caine
-----------------------------
L.S.Caine Electronic Services
Treasurer - Firebird Foundation Inc.
Alan McDonald
2005-12-01 21:45:08 UTC
Permalink
Post by Lester Caine
Starting to hit a major problem with inter database compatibility,
relating to NOW and CURRENT_TIMESTAMP. The convention seems to be that
CURRENT_TIMESTAMP returns a UTC normalized time while LOCAL_TIMESTAMP
and NOW provides the server time.
Anyway what I need to do is load the database with the current UTC time
to match other engines. Option one is to ensure that the server is
running GMT, then I don't have a problem, but is there any way of
getting a UTC time within SQL without having to 'bodge' the server time?
The main reason for wanting to do this is to ensure that times loaded in
slave databases match when the data is joined in the master copy -
probably in another time zone.
--
Lester Caine
I can't get LOCAL_TIMESTAMP. Are you supposed to get this? OR do you mean
CURRENT?
Alan
Claudio Valderrama C.
2005-12-02 04:50:01 UTC
Permalink
-----Original Message-----
Caine
Starting to hit a major problem with inter database compatibility,
relating to NOW and CURRENT_TIMESTAMP. The convention seems to be that
CURRENT_TIMESTAMP returns a UTC normalized time while LOCAL_TIMESTAMP
and NOW provides the server time.
Where is this convention, in other databases or in the SQL spec or in FB?
I ask because we don't have LOCAL_TIMESTAMP.
Anyway what I need to do is load the database with the current UTC time
to match other engines. Option one is to ensure that the server is
running GMT, then I don't have a problem, but is there any way of
getting a UTC time within SQL without having to 'bodge' the server time?
We always call localtime().
The only differences between our NOW and our CURRENT_TIMESTAMP that I see
are:
- NOW is evaluated on each call, whereas CURRENT_TIMESTAMP remains the same
for the whole request (as per the SQL spec). I didn't check what would
happen with sub-requests. Dmitry?
- NOW cast to TIMESTAMP gives you (our) full precision. If you use
CURRENT_TIMESTAMP, you can control the millisec precision (0-3). Maybe we
should allow 0-4; the last digit will be always zero in Windows but
significative on UNIX.

C.
Lester Caine
2005-12-02 05:36:03 UTC
Permalink
Post by Claudio Valderrama C.
-----Original Message-----
Caine
Starting to hit a major problem with inter database compatibility,
relating to NOW and CURRENT_TIMESTAMP. The convention seems to be that
CURRENT_TIMESTAMP returns a UTC normalized time while LOCAL_TIMESTAMP
and NOW provides the server time.
Where is this convention, in other databases or in the SQL spec or in FB?
I ask because we don't have LOCAL_TIMESTAMP.
Actually we ONLY have LOCALTIMESTAMP ;)
I have been doing a bit more research and based on SQL2003
CURRENT_TIMESTAMP is required to provide the current timezone as well.
LOCALTIMESTAMP (don't you just like consistent standards :( - what
happened to the underscore? ) Is the local time without any timezone
indication.

So the problem with Firebird is the lack of timezone in the timestamp. I
do not see how that actually fixes the problem anyway as some timezones
have multiple daylight savings offsets, however since the SQL standard
only stores an offset then it does not 'actually' store the timezone
anyway, but would store the actual current offset to GMT. The main
problem is wanting to INDEX on the GMT times so that 'time' is in
chronological order, but I suppose that is not too difficult once the
date and time are converted to numbers - the offset can be added before
building an index.

The ONLY reference to daylight savings in the SQL2003 standard is in the
one line - "The time zone displacement is constant throughout a time
zone, changing at the beginning and end of Daylight Time, where
applicable." Which still misses the point that the changes in 'Daylight
time' are not constant throughout a time zone :)

I may be making a mountain out of a molehill, but it's a subtle little
problem that poked it's head up because someone pointed out that while
PHP 'time' is GMT, NOW isn't :( and so I'm looking for a way to solve
that problem ;)
--
Lester Caine
-----------------------------
L.S.Caine Electronic Services
Treasurer - Firebird Foundation Inc.
Daniel Rail
2005-12-02 08:54:03 UTC
Permalink
Hi,
Post by Claudio Valderrama C.
-----Original Message-----
Caine
Starting to hit a major problem with inter database compatibility,
relating to NOW and CURRENT_TIMESTAMP. The convention seems to be that
CURRENT_TIMESTAMP returns a UTC normalized time while LOCAL_TIMESTAMP
and NOW provides the server time.
Where is this convention, in other databases or in the SQL spec or in FB?
I ask because we don't have LOCAL_TIMESTAMP.
It's a SQL spec. According to the SQL-2003 standard, we shouldn't even
have CURRENT_TIMESTAMP, because we don't save the time zone. And IIRC,
this discussion did take place a few months ago, either here in
Firebird-Devel or Firebird-Architect. And, i think at the time the
discussion was about the precision, not time zones. But, if we want
to follow the SQL standard(especially if other RDBMS are following the
same convention), we should seriously look at making those changes.

Maybe(?) it's too late for FB 2, but my vote would be at least for FB
3, with a warning in FB 2 release notes that CURRENT_TIMESTAMP and
CURRENT_TIME would have a different behavior in FB 3. And, maybe add
LOCALTIMESTAMP and LOCALTIME to FB 2, so people can start making the
appropriate changes for FB 3. And, it will require a change on how
timestamps are saved physically, because with time zone data it should
be able to save 25 positions.
Here's an example of a possible value to be stored(at least how I see
it): "2005-12-02 12:30:35.111111 -04:00"
The data might be actually stored as: "20051202123035111111-0400"

I know a change in behavior is not very much welcomed, but this change
would put Firebird more in line with the SQL standard and other RDBMS.

And, here the time zone should come from the client, not just the
server. Because both might be in different time zones.

Here's the SQL-2003 definition:

[Start Quote...]
6.31 <datetime value function>

Function:
Specify a function yielding a value of type datetime.

Format:
<datetime value function> ::=
<current date value function>
| <current time value function>
| <current timestamp value function>
| <current local time value function>
| <current local timestamp value function>

<current date value function> ::= CURRENT_DATE

<current time value function> ::=
CURRENT_TIME [ <left paren> <time precision> <right paren> ]

<current local time value function> ::=
LOCALTIME [ <left paren> <time precision> <right paren> ]

<current timestamp value function> ::=
CURRENT_TIMESTAMP [ <left paren> <timestamp precision> <right paren> ]

<current local timestamp value function> ::=
LOCALTIMESTAMP [ <left paren> <timestamp precision> <right paren> ]

Syntax Rules:
1) The declared type of a <current date value function> is DATE. The
declared type of a <current time value function> is TIME WITH TIME
ZONE. The declared type of a <current timestamp value function> is
TIMESTAMP WITH TIME ZONE. NOTE 117 — See the Syntax Rules of Subclause
6.1, “<data type>”, for rules governing <time precision> and
<timestamp precision>.

2) If <time precision> TP is specified, then LOCALTIME(TP) is
equivalent to:
CAST (CURRENT_TIME(TP) AS TIME(TP) WITHOUT TIME ZONE)
Otherwise, LOCALTIME is equivalent to:
CAST (CURRENT_TIME AS TIME WITHOUT TIME ZONE)

3) If <timestamp precision> TP is specified, then LOCALTIMESTAMP(TP)
is equivalent to:
CAST (CURRENT_TIMESTAMP(TP) AS TIMESTAMP(TP) WITHOUT TIME ZONE)
Otherwise, LOCALTIMESTAMP is equivalent to:
CAST (CURRENT_TIMESTAMP AS TIMESTAMP WITHOUT TIME ZONE)

Access Rules:
None.

General Rules:
1) The <datetime value function>s CURRENT_DATE, CURRENT_TIME, and
CURRENT_TIMESTAMP respectively return the current date, current time,
and current timestamp; the time and timestamp values are returned with
time zone displacement equal to the current default time zone
displacement of the SQLsession.

2) If specified, <time precision> and <timestamp precision>
respectively determine the precision of the time or timestamp value
returned.

3) Let S be an <SQL procedure statement> that is not generally
contained in a <triggered action>. All <datetime value function>s that
are contained in <value expression>s that are generally contained,
without an intervening <routine invocation> whose subject routines do
not include an SQL function, either in S without an intervening <SQL
procedure statement> or in an <SQL procedure statement> contained in
the <triggered action> of a trigger activated as a consequence of
executing S, are effectively evaluated simultaneously. The time of
evaluation of a <datetime value function> during the execution of S
and its activated triggers is implementation-dependent.

NOTE 118 — Activation of triggers is defined in Subclause 4.38.2, “Trigger execution”.

Conformance Rules
1) Without Feature F555, “Enhanced seconds precision”, conforming SQL
language shall not contain a <current local time value function> that
contains a <time precision> that is not 0 (zero).

2) Without Feature F555, “Enhanced seconds precision”, conforming SQL
language shall not contain a <current local timestamp value function>
that contains a <timestamp precision> that is neither 0 (zero) nor 6.

3) Without Feature F411, “Time zone specification”, conforming SQL
language shall not contain a <current time value function>.

4) Without Feature F411, “Time zone specification”, conforming SQL
language shall not contain a <current timestamp value function>.
[...End Quote]


Here's the SQL-2003 definition for the data type:

[Start Quote...]
<datetime type> ::=
DATE
| TIME [ <left paren> <time precision> <right paren> ] [ <with or without time zone> ]
| TIMESTAMP [ <left paren> <timestamp precision> <right paren> ]
[ <with or without time zone> ]

<with or without time zone> ::=
WITH TIME ZONE
| WITHOUT TIME ZONE

<time precision> ::= <time fractional seconds precision>

<timestamp precision> ::= <time fractional seconds precision>

<time fractional seconds precision> ::= <unsigned integer>

Syntax Rules:
[...]

28) If <time precision> is not specified, then 0 (zero) is implicit.
If <timestamp precision> is not specified, then 6 is implicit.

29) If <with or without time zone> is not specified, then WITHOUT TIME
ZONE is implicit.

30) The maximum value of <time precision> and the maximum value of
<timestamp precision> shall be the same implementation-defined value
that is not less than 6. The values of <time precision> and <timestamp
precision> shall not be greater than that maximum value.

31) The length of a DATE is 10 positions. The length of a TIME WITHOUT
TIME ZONE is 8 positions plus the <time fractional seconds precision>,
plus 1 (one) position if the <time fractional seconds precision> is
greater than 0 (zero). The length of a TIME WITH TIME ZONE is 14
positions plus the <time fractional seconds precision> plus 1 (one)
position if the <time fractional seconds precision> is greater than 0
(zero). The length of a TIMESTAMP WITHOUT TIME ZONE is 19 positions
plus the <time fractional seconds precision>, plus 1 (one) position if
the <time fractional seconds precision> is greater than 0 (zero). The
length of a TIMESTAMP WITH TIME ZONE is 25 positions plus the <time
fractional seconds precision> plus 1 (one) position if the <time
fractional seconds precision> is greater than 0 (zero).


General Rules:
[...]
4) For a <datetime type>,
Case:
a) If DATE is specified, then the data type contains the <primary
datetime field>s years, months, and days.
b) If TIME is specified, then the data type contains the <primary
datetime field>s hours, minutes, and seconds.
c) If TIMESTAMP is specified, then the data type contains the <primary
datetime field>s years, months, days, hours, minutes, and seconds.
d) If WITH TIME ZONE is specified, then the data type contains the
time zone datetime fields.

NOTE 83 — Within the non-null values of a <datetime type>, the value
of the time zone interval is in the range –13:59 to +14:00. The range
for time zone intervals is larger than many readers might expect
because it is governed by political decisions in governmental bodies
rather than by any natural law.

NOTE 84 — A <datetime type> contains no other fields than those
specified by the preceding Rule.

5) For a <datetime type>, a <time fractional seconds precision> that
is an explicit or implicit <time precision> or <timestamp precision>
defines the number of decimal digits following the decimal point in
the SECOND <primary datetime field>.

[...End Quote]
--
Best regards,
Daniel Rail
Senior System Engineer
ACCRA Group Inc. (www.accra.ca)
ACCRA Med Software Inc. (www.filopto.com)
Lester Caine
2005-12-02 10:09:01 UTC
Permalink
Post by Daniel Rail
Here's an example of a possible value to be stored(at least how I see
it): "2005-12-02 12:30:35.111111 -04:00"
The data might be actually stored as: "20051202123035111111-0400"
I don't think we need to go the whole hog and destroy the current date
and time structure which only used 8 bytes? I would be looking to just
adding a TIMESTAMP_TZ format which added the offset as a two byte signed
minute value. Currently I'm looking at adding a SMALLINT TimeStamp_TZ
field to go with the TimeStamp field, a trigger will then convert the
supplied TimeStamp TO GMT based, and the _TZ will be used if I need to
display the local time of that value.

Update is fun, but simple maths should indicate if the TimeStamp value
has changed ?

What I think is missing here is an identifier for the ACTUAL
Timezone/Daylight Saving setting, as you can't determine that from
anything included in the SQL spec :(
--
Lester Caine
-----------------------------
L.S.Caine Electronic Services
Treasurer - Firebird Foundation Inc.
Thomas Miller
2005-12-02 17:21:01 UTC
Permalink
Post by Claudio Valderrama C.
Where is this convention, in other databases or in the SQL spec or in FB?
I ask because we don't have LOCAL_TIMESTAMP.
Oracle

It has three time stamp type: TimeStamp, TimeStamp With Local Time
Zone, Timestamp With Time Zone

Funtions: CURRENT_DATE, CURRENT_TIMESTAMP, DBTIMEZONE, LOCALTIMESTAMP,
SESSIONTIMEZONE, SYSDATE, SYSTIMESTAMP.

There might be more, but I assume Martijn has been pretty complete in
DBW with these options.
--
Thomas Miller
Chrome Portal Project Manager
Wash DC Delphi SIG Chairperson
Delphi Client/Server Certified Developer
BSS Accounting & Distribution Software
BSS Enterprise Accounting FrameWork

http://www.bss-software.com
http://www.cpcug.org/user/delphi/index.html
http://sourceforge.net/projects/chromeportal/
http://sourceforge.net/projects/uopl/
http://sourceforge.net/projects/dbexpressplus
Continue reading on narkive:
Loading...