Set custom timezone in Django/PostgreSQL (Indian Standard Time) - django

In Django documentation for setting timezone, the list of available choices for timezone are actually postgres timezone parameter strings. So it seems Django uses Postgres for retrieving time.
If so, then the problem is that IST is used to denote both Indian & Israel Standard Time, but postgres uses IST for Israel Standard Time (potentially confusing over a 6th of world's population) and there is NO timezone string for Indian Standard Time.
Not just that, Postgres also misses timezone for some other countries like Nepal (GMT+5:30) and some Pacific Islands.
So, is there any way by which I can set custom timezone string (like GMT+5:30 for India, GMT+5:45 for Nepal, etc.) in Postgres or Django?

For India:
SELECT now() AT TIME ZONE 'Asia/Calcutta';
SELECT now()::timestamp AT TIME ZONE 'Asia/Kolkata';
SELECT now()::timestamp AT TIME ZONE '5:30';
For Nepal:
SELECT now()::timestamp AT TIME ZONE 'Asia/Katmandu';
SELECT now()::timestamp AT TIME ZONE 'NPT';
To set the time zone for the whole session:
SET time zone 'Asia/Calcutta';
To reset it (to the time zone set in postgresql.conf:
RESET time zone;
Find more in the system views pg_timezone_names and pg_timezone_abbrevs
SELECT *
FROM pg_timezone_names
WHERE utc_offset BETWEEN '05:00:00' AND '06:00:00'
ORDER BY utc_offset;
SELECT *
FROM pg_timezone_abbrevs
WHERE utc_offset BETWEEN '05:00:00' AND '06:00:00'
ORDER BY utc_offset;
PostgreSQL manual about AT TIME ZONE construct. About time zones.

Related

Is current time zone detected by default if USE_TZ=True

It is mentioned in docs that the current time zone should be activated.
You should set the current time zone to the end user’s actual time zone with activate(). Otherwise, the default time zone is used
However, I see that the values are parsed in my local timezone in the forms correctly without activating it from my side, and TIME_ZONE is UTC which is different from my local timezone.
No, the user's current time zone is not detected automatically, as discussed here:
There’s no equivalent of the Accept-Language HTTP header that Django could use to determine the user’s time zone automatically.
The fact that time values are parsed according to your local timezone is not correct, since the end user is not necessarily in your time zone. That's why you need to figure out what time zone they're in and use activate().

Read datetime fields as UTC in Django

I have time zone support as active in my application settings USE_TZ = True
So, all my DateTimeFields in my models are transformed from my local time zone to UTC before being saved to database.
Question:
In some cases, the user enters a datetime field value with day precision only like 2022-10-24 without time part, and I already accepts this format as an input. But in such case, I want to save this value without time zone, so that it will be parsed later without time zone.
Why does this cause a problem?
If a user enters a value 2022-10-24 and his local time zone is UTC+2, it will be saved in database as 2022-10-23 22:00:00 UTC. Once another user opens the same instance and his local time zone is UTC+1, he will see the value as 2022-10-23 23:00:00 while I want him to see it with the same value that the initial user enters it, so it should be 2022-10-24 00:00:00.
Partially Failed Trial:
I have tried to handle this in my ModelForm by parsing the entered format, then replacing the time zone info to UTC if it is with day precision.
from pytz import UTC
datetime_value = datetime_value.astimezone().replace(tzinfo=UTC)
Now, the value is saved in database as 2022-10-24 00:00:00 UTC. But when I reads the value of this field, it will be parsed as 2022-10-24 02:00:00 as my local time zone is UTC+2, however I want it to be read as UTC.
How can I override the reading behavior of the datetime field to be shown as UTC?

How to stop django postgresql timestramp conversion

When I Insert timestamp into Postgres table in EST (2019-02-21 05:37:46) and in Postgresql table is stores in IST (2019-02-21 16:07:46). I want time to be stored only in EST. Can anyone help me to fix this issue?
In postgres, you can change the default format mask for datetimes using the set n postgres, you can change the default format mask for datetimes using the set datestyle
for more details follow this link
also refer this link
To my knowledge, there is no setting in PostgreSQL that would trim seconds from timestamp literals by default
In general you should handle all datetimes in UTC, because these are absolute timestamps that are always correct. Even if you are only going to have users in the EST time zone use your website, the EST time zone has daylight saving time (DST) in the summer, so you could get buggy behaviour when the time jumps (especially since there is an overlap of one hour when the clock goes back). This means:
Your code should use UTC timestamps to make calculations and pass around
Your database should store UTC datetime (which PostgreSQL does anyway).
You should only transform to a local time zone when presenting the data to the user. This is default behaviour in Django:
USE_TZ = True by default
TIME_ZONE = "America/New_York" to set default time zone, which will take into account DST
So when you're saving a time-aware datetime to the database (in EST say), the database stores it as UTC. When you fetch and display it, Django will show it in the current time zone of the user (EST in your case). When you query the database directly using a tool, PostgreSQL gives back the UTC, correct datetime, but your shell or tool might display it in the local time zone. You can format your query to use a different time zone using the links posted by #c.grey in the other answer.
Read up on the details here

Django - can I save DateTime objects that have different timezones in the same column?

If I have a DateTimeField() in a model in my app, can I sometimes store a date time with one timezone and sometimes a different timezone?
Short answer: Yes, you can.
When Django saves the timezone, it saves it as the UTC time in the database. When it goes to display it again in your app, it will look for the settings.TIME_ZONE and apply that time zone. If you need to convert it back to a particular time zone, you will also need to store the string of which time zone it is.
More about: Django Time Zones.

Django international site with UTC

I am writing a site to be served internationally across multiple timezones.
In the settings.py:
TIME_ZONE = 'UTC'
USE_TZ = True
I am wondering if someone from NZ puts in a datetime via models.DateTimeField, does it automatically picks up the current timezone and convert to UTC without any extra code?
I am a bit confused on this paragraph:
The current time zone is the equivalent of the current locale for
translations. However, there’s no equivalent of the Accept-Language
HTTP header that Django could use to determine the user’s time zone
automatically. Instead, Django provides time zone selection functions.
Use them to build the time zone selection logic that makes sense for
you.
So do I have to override the save method to add the get_current_timezone()?
The key sentence there is: "However, there’s no equivalent of the Accept-Language HTTP header that Django could use to determine the user’s time zone automatically."
So there's no way for Django to reliably figure out your NZ user's time zone. It's not going to give you the user's time zone - you have to tell it! Specifically, until you explicitly activate() a time zone, the current time zone is just UTC as you defined in your TIME_ZONE setting.
When it comes to user input, the documentation says: "Django interprets datetimes entered in forms in the current time zone and returns aware datetime objects." So, if you've activated the appropriate NZ time zone then the conversion will happen as you expect. But if not, the datetime will be interpreted as being in your default UTC timezone.
How do you figure out the user's timezone? The documentation gives an example of how you can set it based on a value explicitly chosen by the user. I'm sure there are also services out there that try to guess the time zone based on the IP address. Either way, though, Django won't do it for you.