When using Flutter package mysql1, my dates seem to drift by the amount of my time zone - flutter

I save my date as a local date, but when I read it back, it treats it as if it was a UTC date so it slips by several hours.
The dates are passed in as strings in the form '2020-03-05 09:05:23' as query parameters but when they are retrieved they might look like '2020-03-04 10:05:23' because I am 13 hours ahead of Greenwich.

For MariaDB (or MySQL):
Use DATETIME as a picture of the clock on the wall.
Use TIMESTAMP to adjust to the system's timezone.
Set the system's timezone according to where it lives in the world.

Related

How to deal with dates in global system

Let's say that I need to create 'chat-like' system. Of course I need to deal with dates somehow.
I read about it a lot and I have some knowledge but I really don't know how to use it.
I would like to store message date in UTC (postgres 12)
Each user should be able to select his time zone and this time zone should be saved into database (standard approach)
When message is retrieved from database I need to convert message date into valid local date based on user selected timezone.
This is really all I need to do and here problem starts:
In postgres date is stored with offset f.e 2020-05-01 00:00:00+02, but I want to store timezone in another table, not here
How can I store user timezone? I should use names like "EST5EDT" or use time offsets as integer?
Where can I find list of all timezones to present user? (Each global website f.e. facebook has list of timezones with offsets, where can I find list of all valid timezones?)
How can I select date with user appropriate timezone? f.e.
SELECT convert_to_user_date("Date", "timezonename??")
FROM "Messages"
Is this correct way to achieve my goal?
These days you don't have to resort to UTC. You can store full timestamps with time zone. This way e.g. you won't lose DST status at the moment the timestamp was recorded in the database.
https://www.postgresql.org/docs/current/datatype-datetime.html
You can easily select the timestamp stored with any time zone shifted to target user's time zone (assuming it's stored somewhere in user preferences). The syntax is SELECT ... AT TIME ZONE
https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-ZONECONVERT
You are very close to a workable setup.
First, use timestamp or timestamp without timezone column data type to store those UTC date/time stamps.
Second, store your users' preferred time zones in varchar(63) columns in the form Asia/Kolkata or America/Halifax.
Third, use postgresql's built in view pg_timezone_names to get a list of valid time zones. You can use it to populate a pulldown list of choices in your user-settings screen.
If you have time for some real excellence in your user-settings screen, you can suggest time zone settings you guess from the users' ip adresses and allow them to change them if your guess was wrong. Read this. How to get Time Zone through IP Address in PHP
Then, when your application starts using postgresql on behalf of any user, look up that user's chosen time zone in your users table, and use it in this SQL command. SET TIME ZONE 'America/Halifax'; (whatever the user's choice is).
Then when you retrieve your time stamps, they will be rendered in the user's local time, and when you store the they'll be in UTC.
The 'toobz are full of advice about this. Here's something that might be useful. How to get Time Zone through IP Address in PHP
Use the data type timestamp with time zone. Don't be worried by the name — that data type really represents an absolute point of time and does not store time zone information.
The only thing you have to do is to set the timezone parameter correctly for the time zone of the client connection, then the value will be represented correctly in that time zone. PostgreSQL does all the work for you.
If you don't like the string representation (e.g., you are disturbed by the time zone offset displayed), use to_char to format the output the way you like:
CREATE TABLE dates (x timestamp with time zone NOT NULL);
SET timezone = 'Europe/Vienna';
INSERT INTO dates VALUES ('2020-06-01 03:00:00');
SET timezone = 'Asia/Kolkata';
SELECT to_char(x, 'YYYY-MM-DD HH24:MI:SS') FROM dates;
to_char
---------------------
2020-06-01 06:30:00
(1 row)

What is the standard for encoding a date as a timestamp?

Is there a standard for encoding a date as a timestamp? My thoughts:
This should be 12:00pm UTC in local time, eg 9:00am at T-3, therefore anyone consuming the timestamp, regardless of their -12/+12 offset, will recognize the same date, regardless of whether they parse at the UTC timezone
It could be 12:00pm at UTC
It could be the start of the day (12:00am) at UTC
It could be start of the day (12:00am UTC) in local time eg 9:00pm at T-3
Is there an official spec or standard to adhere to?
It would be easy to point to this document and say 'this is the standard' as opposed to being unaware and having to change our logic down the line.
There isn't a standard for this, because a date and a timestamp are logically two very different concepts.
A date covers the entire range of time on that day, not a specific point in time.
It may be a different date for a person in another time zone at any given point in time, but dates themselves do not have any association with time zones. Visualize a date as just a square on a calendar, not a point on a timeline.
Many APIs will use midnight (00:00) as the default time when a date-only value is assigned to a date+time value. However:
Whether it is UTC based or local-time based is very dependent on that particular API. There is no standard for this, nor is one answer necessarily better than the other.
Assigning a local-time midnight can be problematic for time zones with transitions near midnight. For example, in Santiago, Chile on 2019-09-08, the day started at 01:00 due to the start of DST. There was no 00:00 on that day.
Also, you tagged your question with momentjs. Since a Moment object is basically a timestamp (not a date), then Moment.js will generally assign the start of the day if provided a date-only value. The time zone involved is key to deciding which moment that actually is, which illustrates my prior points.
For example:
// Parsing as UTC
moment.utc('2019-09-08').format() //=> "2019-09-08T00:00:00Z"
// Parsing as Local Time (my local time zone is US Pacific Time)
moment('2019-09-08').format() //=> "2019-09-08T00:00:00-07:00"
// Parsing in a specific time zone (on a day without midnight)
moment.tz('2019-09-08', 'America/Santiago').format() //=> "2019-09-08T01:00:00-03:00"
Also keep in mind that sometimes APIs can be misnamed. The JavaScript Date object is not a date-only value, but actually a timestamp, just like a moment.

MongoDB Date field and time zone handling

I will begin using MongoDB in a project and made the following observation:
A ‘Date’, e.g.: ISODate("2000-07-24T00:00:00.000Z") is stored in as UTC 0 (or Zulu).
Let’s assume that an end user submits a plain date, such as “2000-07-24” and his or her local timezone is -5.
Because of the ‘Z’ character in the time (indicates UTC 0), storing the following would be incorrect because the user’s 5 hour difference:
ISODate("2000-07-24T00:00:00.000Z")
I am assuming that it would be more proper to consider the end user’s local time zone into account and store the date as follows:
ISODate(“2000-07-23T19:00:00.000Z”)
By doing this, I can see that any queries would need a timezone adjustment for 'Date'.
By storing all ‘Date’ fields as UTC 0, we can guarantee that exact points in time from people posting from different continents is properly handled.
Does this seem like a good way to handle timezones in MongoDB?

How to fix dates lagging one day behind in calendar

I'm developing a Clio integration with access to the calendar, but there's been an issue with dates. While the documentation says they expect an ISO-8601 timestamp date, it seems like there's something adding offset to the timezone value in dates being sent to the system.
For example, if I send a date 2018-05-17T23:59:59.999999-04:00 on both start_at and end_at properties when creating a calendar entry for an all day event, the value returned when fetching this entry through the API is 2018-05-17T17:00:00-07:00, which is clearly wrong. Am I missing something here?
The expected result should be something like either 2018-05-17T23:59:59-04:00 or 2018-05-18T03:59:59Z if milliseconds are ignored.
All dates are based on UTC timezone. Could it be that your site/server/script is set to a local timezone and so the dates are off for part of the day?
Try setting your scripting environment to UTC time before making any date/time-based queries.

Time zone with daylight savings times in PostgreSQL

We're deploying our own stream gauges (a lot like this USGS gauge: http://waterdata.usgs.gov/usa/nwis/uv?site_no=03539600) so us kayakers know whether or not there's enough water to paddle the stream and don't waste time and gas to drive out there. We hope install a few of these across the southeast whitewater region which spans the eastern and central time zones.
I'm storing the time a record is inserted using the default value of current_time for the record. I'd like to later display the data using the MM/DD/YYYY HH12:MI AM TZ format, which outputs reading like 03/12/2012 01:00 AM CDT. I'd also like for the output to be aware of changes in day light savings time, so the last part of the previous sentence would change between CST and CDT when we 'spring forward' and 'fall back'. This change occurred on 3/11/2012 this year and I've included dates on both sides of this DST line below. I'm using my Windows 7 laptop for development and we will later be deploying on a Unix box. Postgres has apparently detected that my Windows computer is set to eastern US time zone. I'm trying this with a 'timestamp without time zone' field and a 'timestamp with time zone' field but can't get it to work.
I've tried using 'at time zone' in my selects and every thing is working until it's time to display the time zone. The actual hour is part of the time stamp is correctly subtracted by an hour when I ask for the time in CDT. But EDT is displayed in the output.
SELECT reading_time as raw,
reading_time at time zone 'CDT',
to_char(reading_time at time zone 'CDT',
'MM/DD/YYYY HH12:MI AM TZ') as formatted_time
FROM readings2;
"2012-04-29 17:59:35.65";"2012-04-29 18:59:35.65-04";"04/29/2012 06:59 PM EDT"
"2012-04-29 17:59:40.19";"2012-04-29 18:59:40.19-04";"04/29/2012 06:59 PM EDT"
"2012-03-10 00:00:00";"2012-03-10 00:00:00-05";"03/10/2012 12:00 AM EST"
"2012-03-11 00:00:00";"2012-03-11 00:00:00-05";"03/11/2012 12:00 AM EST"
"2012-03-12 00:00:00";"2012-03-12 01:00:00-04";"03/12/2012 01:00 AM EDT"
I'm storing the time zone that each of our gauges is located in a character varying field a separate table. I considered just appending this value to the end of the time output, but I want it to change from from CST to CDT without my intervention.
Thanks for your help.
Instead of using time zone abbreviations like CDT or CST, you could consider using full Olson-style time zone names. In the case of central time, you could choose a time zone. Either one that matches your location, such as America/Chicago, or just US/Central. This ensures PostgreSQL uses the Olson tz database to automatically figure out whether daylight saving time applies at any given date.
You definitely want a TIMESTAMP WITH TIME ZONE column (which is also known as timestamptz in PostgreSQL). That will store the timestamp in UTC, so that it represents a particular moment in time. Contrary to what the name suggests, it does not save a time zone in the column -- you can view the retrieved timestamp in the time zone of your choosing with the AT TIME ZONE phrase.
The semantics of TIMESTAMP WITHOUT TIME ZONE are confusing and nearly useless. I strongly recommend you don't use that type at all for what you are describing.
I'm really confused by the part of the question which talks about storing the timestamp in a CHARACTER VARYING column. That seems as though it might be part of the problem. If you can store it in timestamptz right from the start I suspect that you will have fewer problems. Barring that, it would be safest to use the -04 notation for offset from UTC; but that seems like more work to me for no benefit.
You can create a table of known timezones in the format suggested in Guan Yang's answer, and then use a foreign key column to this table. Valid timezones can be obtained from pg_timezone_names I've gone into more detail in this related answer.