Is there an issue with Central Africa Time (CAT) PostgreSQL TIMESTAMPTZ conversion? - postgresql

One of our PostgreSQL 11.4 deployments in Congo uses the CAT timezone (Africa/Kigali +02) and one of our function chokes when trying to convert human-input timestamps to actual TIMESTAMPTZ data.
For example:
SELECT '2019-10-17 00:00:00 CAT'::TIMESTAMPTZ;
ERROR: invalid input syntax for type timestamp with time zone: "2019-10-17 00:00:00 CAT"
LINE 2: SELECT '2019-10-17 00:00:00 CAT'::TIMESTAMPTZ
^
SQL state: 22007
Character: 9
But when I try with CEST (Central European, also +02) it works.
SELECT '2019-10-17 00:00:00 CEST'::TIMESTAMPTZ;
"2019-10-17 00:00:00+02"
Incidentally, converting from epoch to CAT also works
select to_timestamp(1571263200);
"2019-10-17 00:00:00+02"
Version:
"PostgreSQL 11.4 (Ubuntu 11.4-1.pgdg18.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0, 64-bit" on Ubuntu 18.04.2 LTS

For whatever reason, 'CAT' is not valid for input by default, presumably someone felt it was ambiguous or something. You could append the line
CAT 7200 # Central Africa Time
to the file "$SHAREDIR/timezonesets/Default" to make this work.
Or you could create a file "$SHAREDIR/timezonesets/Africa" with the contents:
#INCLUDE Default
#OVERRIDE
CAT 7200 # Central Africa Time
And then set the parameter timezone_abbreviations to 'Africa'.
I am not horologist, you might want to research why CAT is missing before blindly adding it. Also, if you go either of the above routes, you should document it clearly someplace. You will need to repeat the steps you took when you upgrade PostgreSQL, or restore or move your database.
Or, you could preprocess your user input to replace 'CAT' with 'Africa/Kigali'.
Incidentally, converting from epoch to CAT also works
select to_timestamp(1571263200);
"2019-10-17 00:00:00+02"
'CAT' does not appear in your example. So it is not clear what this is an example of.

Related

PostgreSQL dates function output to a french language

How can I output the result of PostgreSQL dates function as to_char to french language, for example the output of:
select to_char(current_date, 'Day') ;
should be (a french name for a day):
Mardi
instead of english of day (e.g. Monady)
You would need to set the display of date/time (LC_TIME) to french, and to query not the Day but rather the localizable day TMDay using the TM prefix.
show LC_TIME;
SET LC_TIME = 'French';
select to_char(current_date, 'TMDay') ;
to_char
---------
Mardi
(1 row)
The following works on Ubuntu 16.04 Server, with english language set-up
first we need to add system support for French templating with the command:
sudo locale-gen fr_FR.utf8
then restart postgresql service:
sudo systemctl restart postgresql
then log in to psql
SET LC_TIME = 'fr_FR.utf8';
select to_char(current_date, 'TMDay') ;
to_char
---------
Mardi
(1 row)

locale issue workaround in PostgreSQL data directory upgrade from 8.4 to 9.5

Desciption of the issue is given at link. It seems that it is a PostgreSQL bug only. To resolve this issue, there seems to be only a single workaround, which is to create a list of locale (map) with key as <Language>_<Country>.<CodePage>and value as <Language>, <Country>.
For example:
English_United States.1252 = English, United States
...
Since value of parameter --locale is accepted in the format of <Language>, <Country>whereas output of command SHOW LC_COLLATE is in the format of <Language>_<Country>.<CodePage>. So, during an ugrade I will get the value of lc_collate cmd and get the corresponding value from the list and provide it during PostgreSQL 9.5 installation.
How do I convert <Language>_<Country>.<CodePage> to appropriate format for successful installation ?

Convert "Thu Sep 22 3:50 2016" to "2016-09-22" in Solaris, without GNU date

Could someone please suggest a simple and short approach to convert "Thu Sep 22 3:50 2016" to "2016-09-22" in Solaris, through a shell script?
I do not have GNU date available on Solaris as discussed in below post:
Convert date String to number on Solaris shell script gives No such file or directory
I need to query an sql server db, where date is saved in the format, "2016-09-06", hence I need to convert it
Actually, you do have GNU date available but here is anyway one way to achieve this by scripting:
#!/bin/ksh
a="Thu Sep 22 3:50 2016"
echo $a | nawk '
BEGIN {
m=1
m2m["Jan"]=m++;
m2m["Feb"]=m++;
m2m["Mar"]=m++;
m2m["Apr"]=m++;
m2m["May"]=m++;
m2m["Jun"]=m++;
m2m["Jul"]=m++;
m2m["Aug"]=m++;
m2m["Sep"]=m++;
m2m["Oct"]=m++;
m2m["Nov"]=m++;
m2m["Dec"]=m++;
}
{
printf("%s-%02d-%02d\n",$5,m2m[$2],$3)
}'
output:
2016-09-22
Why not use Oracle's sysdate?
select * from your_table where saved_date >= to_char(sysdate,'yyyy-MM-dd')

perl DateTime incorrect timezone offset

I have several servers running under centos 6.3 and I faced issue that perl module DateTime treats Europe/Moscow timezone as UTC+3
[ulan#rt-virtual ~]$ perl -MDateTime -e 'print DateTime->now()->set_time_zone("Europe/Moscow"), "\n";'
2013-12-19T11:11:38
but in fact it is UTC+4 and system tools like zdump or date work correctly
[ulan#rt-virtual ~]$ zdump Europe/Moscow
Europe/Moscow Thu Dec 19 12:11:47 2013 MSK
I updated tzdata and DateTime module but it didn't help.
How can I amend this?
Thanks.
Well, DateTime module is doing its magic by following the rules specified in the TimeZone modules specific for each timezone. For Europe/Moscow, the module's is DateTime::TimeZone::Europe::Moscow. The problem is all the files are generated automatically corresponding to the rules existing when a specific version of DateTime module is released.
In this case one very important change - Russia's stopping following DST routines in 2011 - wasn't obviously reflected in that file. So updating - either the whole module or only the relevant TimeZone part - should have fixed the issue.
You can use your systems tzfile(5), using DateTime::TimeZone::Tzfile. Not only does it perform better than DateTime::TimeZone it also removes the need to have redundant data that needs to be in sync.
$tz = DateTime::TimeZone::Tzfile->new('/etc/localtime');
$dt = DateTime->now(time_zone => $tz);

How does the locale setting LC_NUMERIC work in PostgreSQL?

Could anybody give an insight on the locale and numeric types behaviour in PostgreSQL? We work with Italian locale. That is comma separation for decimal part. Setting in postgresql.conf
# These settings are initialized by initdb, but they can be changed.
lc_messages = 'it_IT.UTF-8' # locale for system error message
# strings
lc_monetary = 'it_IT.UTF-8' # locale for monetary formatting
lc_numeric = 'it_IT.UTF-8' # locale for number formatting
lc_time = 'it_IT.UTF-8' # locale for time formatting
.. does nothing! It behaves in a quite appropriate way with dates and so, BUT the numeric type remains DOT separated for decimal part.
root#server:~# uname -a
Linux server 2.6.32-36-generic-pae #79-Ubuntu SMP Tue Nov 8 23:25:26 UTC 2011 i686 GNU/Linux
root#server:~# dpkg -l | grep postgresql
ii postgresql-8.4 8.4.9-0ubuntu0.10.04 object-relational SQL database, version 8.4
ii postgresql-client 8.4.9-0ubuntu0.10.04 front-end programs for PostgreSQL (supported)
EDIT
Having problem with implementation of locale in different scopes: db, server script, os and client side. Decided to avoid any locale formatting and use en_EN locale. The locale formatting will be applied only at the moment of output and so.
I quote the manual:
lc_numeric (string)
Sets the locale to use for formatting numbers, for example with the to_char family of functions.
Concerns these type formatting functions. You should be able to reproduce the following demo:
SHOW lc_numeric;
de_AT.UTF-8
SELECT to_number('13,4','999D99')
13.4
SELECT to_char(13.4,'FM999D99')
13,4
SET lc_numeric = 'C';
SELECT to_number('13,4','999D99')
134
SELECT to_char(13.4,'FM999D99')
13.4
RESET lc_numeric;
Template patterns in the manual.
The format of numbers in SQL expressions does not change with locale settings. That would be madness.
On a different note: you are aware that you have to (at least) reload the server after changing postgresql.conf.
pg_ctl reload