How does this teradata timestamp with timezone example make sense? - teradata

In the teradata documentation it says:
"Suppose an installation is in the PST time zone and it is New Years Eve, 1998-12-31 20:30 local time.
The system TIMESTAMP WITH TIME ZONE for the indicated time is ' 1999-01-01 04:30-08:00 ' internally."
This does not mesh with my understanding. I figure it ought to be '1999-01-01 04:30+00:00' internally because it should be stored in UTC.
Or, it can be stored as a the local time with a -8 offset, but this example seems to mix the two. Perhaps I am misunderstanding the text?

Not sure if this is an answer, but it's too long for a comment.
That "internal" storage part is very misleading. We don't care how Teradata stores anything internally.
I find this easier to look at using BTEQ, since SQL Assistant doesn't show timezones, at least by default. So, assuming you've logged into BTEQ...
--set session timezone to pst (GMT - 8)
SET TIME ZONE INTERVAL -'08:00' HOUR TO MINUTE ;
create volatile table vt_foo (
ts_w_zone timestamp(0) with time zone,
ts_wo_zone timestamp) on commit preserve rows;
insert into vt_foo
select
cast('1998-12-31 20:30:00' as timestamp(0)),
cast('1998-12-31 20:30:00' as timestamp);
select * from vt_foo;
Currently the two values (with and without tz) will match.
ts_w_zone ts_wo_zone
------------------------- --------------------------
1998-12-31 20:30:00-08:00 1998-12-31 20:30:00.000000
Now let's change the timezone for your session to something else, and look at what we get.
SET TIME ZONE INTERVAL -'03:00' HOUR TO MINUTE ;
select * from vt_foo;
ts_w_zone ts_wo_zone
------------------------- --------------------------
1998-12-31 20:30:00-08:00 1999-01-01 01:30:00.000000
The timestamp with zone is still the same. Displaying it without timezone is automatically converting it to your session timezone, which in this example is GMT -3.
EDIT:
Technically, Teradata is actually storing the time with timezone as GMT (1999-01-01 04:30:00) with the timezone offset (-8). That's where the documentation gets the  1999-01-01 04:30-08:00 value from). But that is not how it displays it.

Related

Update in Project default_time_zone not affecting timestamp

As part of setting GCP project level timezone to AEST, I have run the following command -
ALTER PROJECT `gcp-abc-def`
SET OPTIONS ( `region-us.default_time_zone` = 'Australia/Sydney')
Doing so, I see that current_datetime() is getting changed to AEST whereas timestamp remains UTC, as can be seen below.
Can someone help how this can be remedied? What other settings to be changed?
I see that current_datetime() is getting changed to AEST whereas timestamp remains UTC this is because the current_timestamp function shows time in timestamp type. A timestamp does not have a time zone; it represents the same instant in time globally. When querying for CURRENT_TIMESTAMP() it shows explicitly in UTC by having zero time zone offset. When you convert a timestamp to some other type that isn't tied to a particular timezone, you can specify the timezone for the conversion.You can use format_timestamp to convert the timestamp into your zone specific time.
Example:
ALTER PROJECT `gcp-abc-def`
SET OPTIONS ( `region-us.default_time_zone` = 'Australia/Sydney');
select current_datetime() as cdt, current_timestamp() as cts,format_timestamp('%c',current_timestamp(),'Australia/Sydney') as cts2

Converting a timestamp with a local timezone displayed in default BigQuery UTC format to actual UTC

I have an external data source automatically inserting data into my BigQuery table, this data source includes a timestamp field which does not have a timezone connected to it, however, I know this timestamp is in the Europe/Amsterdam timezone.
The problem here is that when this timestamp is inserted into BigQuery, BigQuery automatically defaults the timestamp to UTC, which it is not. And in my specific case, I want to convert this timestamp to UTC. However because BigQuery already defaulted the timestamp to UTC (while it is actually Europe/Amsterdam), I cannot easily convert it to the actual UTC timezone.
Is there any way to convert this timestamp, which BigQuery thinks is already UTC, to the actual UTC timezone within a query? I can't just give it a -02:00 offset due to Daylight Savings coming into play which changes this offset from 2 hours to only 1 hour depending on the time of year.
Any help would be appreciated, I have been kind of stuck on this :)
An example of the timestamp in BigQuery would be 2022-09-30 01:23:45 UTC
There is probably a better way but this should work
with
input as (select timestamp("2022-09-30 01:23:45 UTC") as ts)
select
ts,
timestamp(replace(cast(ts as string), '+00', " Europe/Amsterdam")) updated_ts
from input
ts
updated_ts
2022-09-30 01:23:45 UTC
2022-09-29 23:23:45 UTC

Getting UTC UNIX timestamp in Lua

An API returns a timestamp as UNIX timestamp at UTC and I would like to know if this timestamp was more than x seconds ago. As expected, this works fine with os.time() - x > timestamp in UTC, but blows up in other timezones.
Unfortunately I can't find a good way solve this in lua.
os.date helpfully has the ! prefix (e.g. os.date("!%H:%M:%S")) to return time at UTC, but it seems that despite the documentation stating it supports all strftime options, this does not support the %s option. I have heard people mention that this is caused by Lua compile time options for a similar issue, but changing these is not possible as the interpreter is provided by the user.
You can use
os.time(os.date("!*t"))
to get the current UNIX epoch.
Ok, so you want the UTC time. Keep in mind that os.time actually knows nothing about timezones, so for example:
os.time(os.date("!*t"))
Will get UTC time and populate table struct.
Will convert table struct according to current timezone to unix timestamp.
So you actually would get your UNIX_TIME - TIMEZONE_OFFSET. If you are in GMT+5 you will get timestamp at UTC-5.
The correct way to do time conversion in lua is:
os.time() -- get current epoch value
os.time{ ... } -- get epoch value for local date/time values
os.date("*t"),os.date("%format") -- get your local date/time
os.date("!*t") or os.date("!%format") -- get UTC date/time
os.date("*t", timestamp),os.date("%format", timestamp) -- get your local date/time for given timestamp
os.date("!*t", timestamp) or os.date("!%format", timestamp) -- get UTC date/time for given timestamp
Kudos to Mons at https://gist.github.com/ichramm/5674287.
If you really need to convert any UTC date to timestamp, there's a good description on how to do this in this question: Convert a string date to a timestamp
os.time() gives you the unix timestamp. The timestamp is seconds since 00:00:00 UTC on 1 January 1970, so it's the same across timezones.
For example, run this code:
print('timestamp', os.time())
print('local hour', os.date("*t").hour)
print('utc hour', os.date("!*t").hour)
Presumably, your local and utc hour are different. Also run it in an online repl. The server's local and utc hour are the same, but both your and the server's timestamp are about the same.

Output DateTime as String with predefined time zone shift

I have a DateTime in my .NET program that I need to print with particular value of time zone offset (for instance, +01:00 always). Output should contain full date time with timezone. It has to be unrelated to system timezone setting. How I could achieve this?
Example: I have a timestamp such as 12-03-2016T12:30:34+03:00 and I need to output it calculated for predefined TZ +1: 12-03-2016T10:30:34+01:00
Found some approach to it.
First of all, DateTime does not have time zone stored in it. Instead it has flag whether it is UTC or Local (without the idea what Local TZ shift is). So: first thing is to get your initial parsing of time from any string time stamp in UTC.
Once it is stored in DateTime object (with Kind=UTC), you have to convert it to the timezone you desire output for. I find examples here useful: datetime to string with time zone.
Note: if you need to convert London daylight-saving time, you have to know right names of timezones in NET so you get it right. See Difference between UTC and GMT Standard Time in .NET

How to schedule an Oracle dbms_scheduler Job timezone and DST safely

I am trying to setup a DBMS_SCHEDULER Job to run exactly at 1 AM on 1st of January every year on Oracle 11g. How to setup its attributes to be absolutely sure it wont get executed in wrong hour, because of timezone differences nor Daylight Savings Time.
I have spent plenty of time going through Oracle documentation, but I have still not reached the level of certainity.
Just btw, here are the rules which I found and consider relevant to the subject:
Job attributes
start_date This attribute specifies the first date on which this job is scheduled to start. If start_date and repeat_interval are left null, then the job is scheduled to run as soon as the job is enabled.
For repeating jobs that use a calendaring expression to specify the repeat interval, start_date is used as a reference date. The first time the job will be scheduled to run is the first match of the calendaring expression that is on or after the current date.
The Scheduler cannot guarantee that a job will execute on an exact time because the system may be overloaded and thus resources unavailable.
repeat_interval This attribute specifies how often the job should repeat. You can specify the repeat interval by using calendaring or PL/SQL expressions.
The expression specified is evaluated to determine the next time the job should run. If repeat_interval is not specified, the job will run only once at the specified start date. See "Calendaring Syntax" for further information.
Rules in Calendaring syntax
The calendaring syntax does not allow you to specify a time zone.
Instead the Scheduler retrieves the time zone from the start_date
argument. If jobs must follow daylight savings adjustments you must
make sure that you specify a region name for the time zone of the
start_date. For example specifying the start_date time zone as
'US/Eastern' in New York will make sure that daylight saving
adjustments are automatically applied. If instead the time zone of
the start_date is set to an absolute offset, such as '-5:00',
daylight savings adjustments are not followed and your job execution
will be off by an hour half of the year.
When start_date is NULL, the Scheduler will determine the time zone for the repeat interval as follows:
It will check whether the session time zone is a region name. The session time zone can be set by either:
Issuing an ALTER SESSION statement, for example: SQL> ALTER SESSION
SET time_zone = 'Asia/Shanghai'; Setting the ORA_SDTZ environment
variable.
If the session time zone is an absolute offset instead of a region name, the Scheduler will use the value of the DEFAULT_TIMEZONE Scheduler attribute. For more information, see the SET_SCHEDULER_ATTRIBUTE Procedure.
If the DEFAULT_TIMEZONE attribute is NULL, the Scheduler will use the time zone of systimestamp when the job or window is enabled.
You may use this to make sure you pass a timestamp with time zone and that the start date will have a timezone name (US/Eastern) instead of an offset (ex: +5:00). This way, as the above fragments from the oracle docs mention, the Scheduler will keep track of DST.
-- Create a SCHEDULE
declare
v_start_date timestamp with time zone;
BEGIN
select localtimestamp at time zone 'US/Eastern' into v_start_date from dual; --US/Eastern
DBMS_SCHEDULER.CREATE_SCHEDULE(
schedule_name => 'SAMPLE_SCHEDULE',
start_date => v_start_date,
repeat_interval => 'FREQ=DAILY; BYHOUR=10; BYMINUTE= 15',
comments => 'Runs daily at the specified hour.');
END;
To make sure you have set it properly you can run this:
ALTER SESSION SET nls_timestamp_tz_format = 'MM-DD-YYYY HH24:MI:SS tzr tzd';
Now, create two schedules, one as above and one using sysdate as the start_date parameter and execute the query below.
-- Check the TIMEZONE
select * from USER_SCHEDULER_SCHEDULES;
v1:
27-MAR-14 11.44.24.929282 AM **US/EASTERN**
v2:
27-MAR-14 05.44.54.000000 PM **+05:00**
I am unsure if this answer truly passes the rules of an answer on this site, but after spending a lot of time googling I came up with the following solution:
start_date => CAST(trunc(sysdate, 'YEAR')+2/24 AS TIMESTAMP) at time zone 'Europe/Berlin'
I believe this is closest to safest solution because:
It uses timestamp instead of date - i believe it forces the job to be truly executed on given time in given timezone, while ignoring DMBS_SCHEDULER default_timezone. I found also some suggestions that say that it is also unsafe to use directly timestamp, that only this cast is safe
I selected manually the timezone I need, with the hope, that it would not come to conflict with local settings. Altough it is unclear to me, whether it is now truly unrelated to SESSIONTIMEZONE, or DBTIMEZONE and whether it affects the proper time of run.
I have used a little hack, even though the request is that the job should start after midnight, I have set it to 2AM, with the hope that even in case of bad time zone and bad daylight savings it would get moved max +-2 hours.
I would be happier with the solution, if I would be absolutely clear on when the job actually gets executed with the respect of local time of a server, SESSIONTIMEZONE, DBTIMEZONE, start_date Time Zone and a DBMS_SCHEDULER time zone.
I am also unhappy with the Time Zone specification, since its has 4 abbreviations linked with it - LMT, CET, CEST, CEMT, where CEST seems to me like being completely wrong. My target is to use CET with Daylight savings(winter!=summer).
Actually I have never tried it with .CREATE_SCHEDULE method but .CREATE_JOB has also start_date parameter and what works for me is just plain
start_date => TO_TIMESTAMP_TZ('00:10 Europe/Rome','hh24:mi tzr'
It retains 'Europe/Rome' when I query dba_scheduler_jobs:
SELECT job_name, TO_CHAR(start_date) start_date,
TO_CHAR(next_run_date) next_run_date
FROM dba_scheduler_jobs;
To add a bit more info to this, when you want to check if modification was successful.
Run query: select * from all_scheduler_jobs where owner='schema_name'.
There you can see in the field start_date, which has type timestamp with timezone, that it contains data like: 2017-12-05 01:55:00,000000000 EUROPE/YOUR_CITY
Having time zone info at the end confirms that it is properly saved for the job.
Then, also, next_run_date is aligned with start_date and it should also show time zone details.
SELECT DBMS_SCHEDULER.STIME FROM DUAL;
Reference

Resources