How would you convert a UTC date to an epoch in DB2? - db2

I can do this to get UTC
select CURRENT TIMESTAMP - CURRENT TIMEZONE AS utc
FROM SYSIBM.SYSDUMMY1;
one would imagine something like
select GetEpoch(CURRENT TIMESTAMP - CURRENT TIMEZONE) AS utc
FROM SYSIBM.SYSDUMMY1;
what would be the logic for GetEpoch?

If your Db2-database lives either on Linux/Unix/Windows or i-series and is currently supported by IBM, then you can use the EXTRACT function which accepts an EPOCH parameter (among other things).
For EPOCH, Extract Returns The number of seconds since 1970-01-01 00:00:00.00 for the supplied date/timestamp expression.
Example values extract(epoch from current timestamp) or select extract(epoch from current timestamp) from sysibm.sysdummy1
Db2-LUW documentation here.
Db2-for-i documentation here.
Although the EXTRACT function is available on Db2-for-Z/OS, it does not appear to accept the EPOCH parameter, unless undocumented, documentation here.

The following query returns the same result in both rows:
VALUES
extract(epoch from current timestamp)
, (days(current timestamp) - days(timestamp('1970-01-01'))) * 86400 + midnight_seconds(current timestamp)

Related

How to store mmyy in Postgres?

There are two variables:
$mm = "01";
$yy = "22";
I need to store it in one column Postges mmyy.
What is type mmyy must be if there is not day?
Or I can use the first day of month always like: 010122.
Eventually, I want to filter rows with where mmyy > now().
If you want to treat it like a date/time value, preferably store it as date. That would be:
date '2022-01-01'
Occupies only 4 bytes, same as int4.
Always use ISO format, which is unambiguous regardless of your locale settings. More in the manual.
To convert your variables, you might use the Postgres function to_date():
test=> SELECT to_date('2201', 'YYMM');
to_date
------------
2022-01-01
(1 row)
test=> SELECT to_date('22'::text || '01'::text, 'YYMM');
to_date
------------
2022-01-01
(1 row)
Or prepare a date literal in ISO format.
When compared to now() (which returns timestamp with time zone) the date value is coerced to the first instant of Jan 1st, 2022 at the time zone determined by the current setting of your session. See:
Difference between now() and current_timestamp
So it works as intended out of the box - except that you possibly haven't thought about time zones, yet ...
For other tasks with date arithmetic, an integer might be a good choice. See:
How do you do date math that ignores the year?

date_trunc at time zone with original timestamptz

I have a single timestamptz that I want to date_trunc so it removes the hours:
2019-01-01T17:43-03 => 2019-01-01T00:00-03.
However, because date_trunc removes the timezone, I need to do it like this:
date_trunc('day', '2019-01-01T17:43-03'::timestamptz) at time zone '-03'
However, I do not want to hardcode the time zone, since the query is run with timestamptz in many different timezones (these are input to the query and not stored). So I want the timezone to be extracted from the original timestamp. I tried to do something like this, but it does not work:
date_trunc('day', '2019-01-01T17:43-03'::timestamptz) at time zone EXTRACT(...)
Related, I am trying to extract the timezone from a timestamptz, but just getting 0.
SELECT EXTRACT(timezone FROM TIMESTAMP WITH TIME ZONE '2019-01-01T00:00+03')
0
Can anybody help me with this?
I believe you may have a misconception about how timestamps and timezones are stored in PostgreSQL (because you seem to expect the -03 to be preserved when calling date_trunc and that you "want the timezone to be extracted from the original timestamp"). According to the documentation:
When a timestamp with time zone value is output, it is always converted from UTC to the current timezone zone, and displayed as local time in that zone. To see the time in another time zone, either change timezone or use the AT TIME ZONE construct (see Section 9.9.3).
Therefore, the statement that "different clients [that] have timestampts in many different timezones," while true, are all translated to UTC for storage, and then displayed in your local timezone (or the timezone you specify) for output. As such, calling date_trunc() will essentially truncate the UTC timestamp, and if you want it displayed in a specific timezone, you will need to add the AT TIME ZONE clause.
UPDATE: An example is here:
edb=# select date_trunc('day', '2019-01-01T17:43-03'::timestamptz) ;
date_trunc
------------------------
2019-01-01 00:00:00+00
(1 row)
edb=# set timezone to 'US/Pacific';
SET
edb=# select date_trunc('day', '2019-01-01T17:43-03'::timestamptz) ;
date_trunc
------------------------
2019-01-01 00:00:00-08
(1 row)
As you can see, date_trunc will append the timezone that I defineā€”it is not omitted.

Date and time in UTC - how to store them in postgres?

I am getting my data: date and time in UTC, in a csv file format in separate columns. Since I will need to convert this zone to date and time of the place where I live, currently in summer to UTC+2, and maybe some other zones I was wondering what is the best practice to insert data in postgres when we are talking about type of data. Should I place both of my data in a single column or keep them separate as types: date and time, and if not should I use timestamp or timestampz (or something else).
use timestamptz it will store your time stamp in UTC. and will display it to the client according to it's locale.
https://www.postgresql.org/docs/current/static/datatype-datetime.html
For timestamp with time zone, the internally stored value is always in
UTC (Universal Coordinated Time, traditionally known as Greenwich Mean
Time, GMT). An input value that has an explicit time zone specified is
converted to UTC using the appropriate offset for that time zone. If
no time zone is stated in the input string, then it is assumed to be
in the time zone indicated by the system's TimeZone parameter, and is
converted to UTC using the offset for the timezone zone.
When a timestamp with time zone value is output, it is always
converted from UTC to the current timezone zone, and displayed as
local time in that zone. To see the time in another time zone, either
change timezone or use the AT TIME ZONE construct (see Section 9.9.3).
updated with another good point from Lukasz, I had to mention:
Also in favor of single column is the fact that if you would store
both date and time in separate columns you would still need to combine
them and convert to timestamp if you wanted to change time zone of
date.
Not doing that would lead to date '2017-12-31' with time '23:01:01' would in other time zone in fact be not only different time, but different date with all YEAR and MONTH and DAY different
another update As per Laurenz notice, don't forget the above docs quote
An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. Which means you have to manage the input dates carefully. Eg:
t=# create table t(t timestamptz);
CREATE TABLE
t=# set timezone to 'GMT+5';
SET
t=# insert into t select '2017-01-01 00:00:00';
INSERT 0 1
t=# insert into t select '2017-01-01 00:00:00' at time zone 'UTC';
INSERT 0 1
t=# insert into t select '2017-01-01 00:00:00+02';
INSERT 0 1
t=# select * from t;
t
------------------------
2017-01-01 00:00:00-05
2017-01-01 05:00:00-05
2016-12-31 17:00:00-05
(3 rows)

How to convert date time into unix epoch value in Postgres?

How do I convert the following format to UNIX timestamps?
A value like: 01-02-2015 10:20 PM should be converted to: 1418273999000
I did try to_timestamp function but its not working for me.
If your data is stored in a column called ts, in a table called data, do this:
select extract(epoch from ts) from data
To add Joe's answer, you can use date_part, i think it's syntax is clearer than 'extract'.
select date_part('epoch', ts) from data;
Adding to haoming answer,
for UNIX epoch this was my approach.
I also added a 180 day interval which can be changed/removed upon requirements.
date_part('epoch', (column_name + INTERVAL '180 day')) * 1000

timezone aware date_trunc function

The following query
SELECT the_date FROM date_trunc('day', timestamp with time zone
'2001-01-1 00:00:00+0100') as the_date
results to
the_date
2000-12-31 00:00
Is there a way to tell date_trunc to do day/month/year conversions based on the timezone it is feeded with?
The expected output would be: 2001-01-1 00:00+0100
You need to specify at which time zone you want it to show
select
date_trunc(
'day',
timestamp with time zone '2001-01-1 00:00:00+0100' at time zone '-02'
) as the_date;
the_date
---------------------
2001-01-01 00:00:00
AT TIME ZONE
While the marked answer might be correct for the OP's weird circumstances it is more likely incorrect for others. You need to convert the timestamp returned by date_trunc to the proper timezone.
select
date_trunc(
'day',
some_timestamp at time zone users_timezone
) at time zone users_timezone as the_date;
The important thing to understand is date_trunc returns a timestamp with no timezone attached to it. You need to convert the timestamp to the proper timezone because the database client or whatever downstream might have a different timezone.
#Adam's answer is definitely more helpful. Although I think we can improve on it again because if we're truncating a Timestamp to a single day (or week/month/etc), then we want to make sure that we're dealing with a Date object, not a Timestamp. Otherwise we may give other pieces of code the impression that something just actually happened to occur at midnight (or potentially some other misleading time of day).
So I would use:
SELECT date_trunc('day', some_timestamp AT TIME ZONE users_timezone)::date AS the_date;
which casts the result to a Date, rather than Timestamp.
The result will be something like:
the_date
------------
2019-09-14
instead of the more misleading result of:
the_date
---------------------
2019-09-14 00:00:00