Use just date instead of datetime in Flutter, Firestore & Cloud Functions - firebase

I'm using a Flutter app with Cloud functions.
I understand from all the questions raised and answered here that Firestore stores DateTime. And in Cloud functions when I use Timestamp.toDate(), the value returned is in the server timezone which happens to be UTC.
The challenge I'm facing is:
Date sent to Firestore: 31 Jan 2021 from the app in IST timezone
It gets stored in Firestore as a timestamp: 30 Jan 2021 18:30:00UTC because the app actually sends 31 Jan 2021 00:00:00+5:30 which gets converted to UTC.
When I open the app in India, the date shows up correctly as 31 Jan 2021.
But when someone opens the app in (say) New York, the app shows the value as 30 Jan 2021 (I'm omitting the time in the display).
I understand why this is happening and probably a best practice for me is to convert the date in Flutter to 31Jan2021 00:00:00 UTC (instead of 00:00:00+5:30) before sending it to Firestore and then whenever displaying the value back to again ensure the date is shown in UTC instead of the local timezone.
My question is whether there is a package or means to globally enforce the dates in UTC in Flutter. The other option would be to do the conversion every time I read or write a DateTime value with Firestore!
Or maybe what is the best way to store a date in Firestore? I read in another post as someone storing it as a String instead of a Timestamp. Maybe that is the right way or maybe store as Number.

It is better to use String datatype if you want to store only date in the Firestore, to avoid the kind of confusion that you are encountering.
For detailed information, you can refer to this stackoverflow thread.

Related

Writing to firestore in firebase cloud-function shifts my dates

Working on flutter/dart project. Calling cloud function from client side and passing 2 dates which are converted toISO8601String.
Printing dates to console while executing cloud-function to double check. They are always valid. After creating document in firestore, the dates are shifted by 1 hour.
I guess because of my current timezone offset which is UTC+1. In summer I had same issue where firestore was shifting my dates by 2 hours because of summer time, resulting in offset UTC+2.
My cloud-functions are deployed at region: europe-west3, which according to firebase docs is Frankfurt. Same time zone as mine (Central European Standard Time). But when I create:
const now = new Date();
Result is one hour less than my local time. Why is that when we are in the same time zone with same offset?
Reading documents from firestore on client side results in inaccurate dates, which is pretty bad for me since I need it to be accurate.
I was searching everywhere but didn't find anything that really helped me. I was trying to construct the date object with many ways but the result was always the same, can somebody please explain me why and help me out? Thanks.
The Java Object Date does not actually contain timezone information, it's just a number of milliseconds since the "epoch" (01.01.1970 00:00:00 UTC) and thus an absolute point in time. It's converted into a valid time every time it's output to a user.
So it seems that the reason for the time shift is that your PC or the browser you are viewing your firestore documents from is set to the wrong timezone.
For further information, take a look at this question or the java documentation.

Timezone and date conversion problems

I have a simple system, which on node creation form, allows user to select start and end dates along with hours and minutes:
The problem is that the date gets messed up somewhere in the middle, or I don't know how to convert it.
In the database, two values gets saved as follows:
start: "2019-08-01T14:00:00.000Z"
end: "2019-08-01T16:00:00.000Z"
Seems correct, as in the datepicker I chose 2pm and 4pm. Then, using momentjs and react-big-calendar, I try to put that event into calendar. It seems that it puts +3 hours every time. I assume, it is because it saves it in UTC format, and I live in Eastern Europe, which is +3 hours from UTC.
What is strange, is that I already get back time converted to my own when I make a request to the database:
Thu Aug 01 2019 17:00:00 GMT+0300 (Eastern European Summer Time)
Could someone help me out? I would expect to have the same hours returned and displayed, as I save them, meaning if I select 2pm, it should be 2pm. I think the solution here would be to ignore timezones, and always display everything in UTC? But how to do that? I have access to momentjs if that helps. I tried something like this:
moment.utc(event.start);
But it still returns the same value, which is:
Thu Aug 01 2019 17:00:00 GMT+0300 (Eastern European Summer Time)
When you setup React-Big-Calendar, you define a localizer. By default, the calendar will display in the local timezone of the browser the user is using. Any and all dates given to the calendar will be converted to that local timezone. If your dates, coming from the db, use an offset of +5, but you're sitting in +3, it will automatically convert those times to display +3 (part of the beauty of UTC).
This is where it can get tricky. Say I want to get all values from my db between Sep 19th and Sep 21st. I have to remember those offsets when requesting data from the system. I could use moment and say moment('2019-09-19').startOf('day'), and it would give me 2019-09-19T00:00:00Z, but this isn't exactly correct for me, as I'm at an offset of -5, which means I actually needed 2019-09-18T19:00:00Z to get the start of my day. The same holds true for my end datetime, where I would say moment('2019-09-21').endOf('day') and it would give me 2019-09-21T23:59:59Z, when I would need 2019-09-21T18:59:59Z.
Now, I'm not positive of this (you'll have to do some testing), but if you use moment-timezone instead of moment it may handle all of this for you. You'll have to play around to know for sure.
FINAL EDIT: I worked out timezone handling with moment-timezone as my localizer. I put the entire thing in a GitHub project, as well as creating a CodeSandbox where people can play with it.
TRULY FINAL EDIT: The (0.36.0) latest version of RBC has full timezone support now, when using either the momentLocalizer or the new luxonLocalizer. Doc site isn't up to date yet, but if you run the 'examples' locally you'll find all the info.

Date timezones and Daylight saving time

I'm working in a scheduler web application and my client (Angular) and server (Asp.net core) timezones are different.
The client is in any timezone. Let´s use (GMT-3).
The server is UTC.
Let´s suppose this case:
One user schedule an event to it´s local time at 08:00AM.
When send this information to serve, it will save 11:00AM in database.
So, when user retrieve this information, client will convert back to 08:00AM due to -3 hours timezone.
But, if this schedule was made to a date in future, when client's country will be in daylight saving, it will convert back to -2 hours. So it will converted to 09:00AM to the client, and that is wrong.
How to deal with daylight saving time when I get dates from server?
Simply, date and times should be stored in UTC. You can always get from UTC back to the user's time. The problem with storing a datetime with an offset is that the offset is not contextual. For example, let's assume that the user is in DST with a timezone that is normally -3 offset from UTC. As such, their current offset is -2. You store the -2 offset, and now what? Is it -2 because they're in a zone that's -2 or is it -2 because it's a -3 zone in DST. There's no way to know. In effect, you've failed to capture critical information.
You don't have this issue with datetimes stored in UTC. You can simply get the user's current time, including their current offset (DST or not) and compare that with the times in your data store. You may need to convert the user time to UTC first, but in many case you do not. For example, the DateTimeOffset type is smart enough to be able to compare taking offset into account. Many databases support this as well for offset-capable column types.
If I understand the issue correctly, you want to keep the server using UTC stored date/times and have the client display local time while handling the DST. I recommend using the angular2-moment, Moment & Momemt-Timezone npm packages. This package will be able to automatically handle the DST when you provide the iana_timezone like America\Chicago.
moment.tz(<utc-date-time>, <iana-timezone>).format()
This will handle all the necessary conversions you need in the client.
See Stackblitz example
Also checkout the Moment Timezone Docs

Regarding storing and showing date and time as per user time zone

How many online forum like StackOverflow and forum.asp.net show questions and posted answers with date and time?
How do they store date and time into sql server table?
Do they store date and time in UTC format?
Sometimes a forum shows a question asked 8 hours ago and also an answer posted 6.10 minutes ago.
How they diff stored utc date and time from current date and time?
And how they diff stored utc date and time from user time zone time?
Suppose my website and database is hosted in an USA server.
Suppose someone asked a question in the morning of Aug 21 at 9:34 from India and an answer was posted from USA on AUG 20 at night but forum shows the infos like:
question posted Aug 21 at 9:34
and answer posted Aug 21 at 9:38
How it is possible?
Is it showing right date and time?
Please discuss how we should store date and time in sql server db in UTC format and how to display results which will not create confusion in readers mind.
Guide me using concepts and examples. People can visit any forum question without any login. So how server will know from which country the user is coming and what is user timezone? In asp.net can we know what is user time zone from server side?
When user requests a page then from the code being file can we know what is user timezone?
I saw forum generate posted question and answer's date and time info at server end before transfer html to client. So how any web site know from which time zone a user requesting a page. If it is possible then we can convert date and time to user timezone.
Looking for guide lines. Thanks
Generally speaking, dates and times should be stored in UTC and only displayed to local time in the UI layer.
StackOverflow uses client-side JavaScript to transform this:
<span title="2015-08-28 09:19:09Z" class="relativetime" />
into
<span title="2015-08-28 09:19:09Z" class="relativetime">24 mins ago</span>
(timeago is an example of a jQuery plugin that does this trick).
This made possible by the fact that JavaScript is executing client-side, and as such it knows what is the time zone of the "browser", as it were.
Determining time zone from within an ASP.NET web application is tricky.

How to implement timezone in a web application?

I want to implement timezone in my web application. I researched and saw most web app use a GMT dropdown, here is the link to that dropdown http://www.attackwork.com/BlogEntry/6/Time-Zone-Dropdown-Select-List/Default.aspx
Then I saw this article suggesting UTC is the way to go when it comes to implement timezone. https://web.archive.org/web/20210513223048/http://aspnet.4guysfromrolla.com/articles/081507-1.aspx Basically it's saying don't use DateTime.Now instead use DateTime.UtcNow
My questions are,
Is there a dropdown of the timezones in UTC, like the first link I showed there is one on GMT?
Should I really use UTC or GMT?
.NET 3.5 provides the TimeZoneInfo class which should make it relatively simple for you to populate a dropdown with time zones. GMT came before UTC and UTC was officially instituted on January 1, 1972. See this link for more information. For today's purposes, the two are pretty much synonymous, though they have different historical origins. Use whichever looks and functions better for your purposes.
I'm not sure if this is what you intended to ask, but in your database you should always store timestamps in UTC/GMT (as noted by others they mean essentially the same thing). For each user of your web app, store the time zone preference.
Then whenever you display the timestamp for something to a user, convert the UTC time in the database to the user's timezone.
GMT (Greenwich Mean Time) is the same as UTC (Universal Coordinated Time). This isn't an either/or choice - use it :)
Use Localization settings, functions and features anywhere possible.
If you aren't running against SQL Server 2008 or don't want to abstract timezone management to the database, you should store all times as UTC/GMT and apply the timezone difference based off the user's profile setting, so that users from all around the world can see timestamps on events in their local time.
The distinction between UTC and GMT is probably too fine to bother with in your code. However, it's probably a good idea to always save and process times internally with zero timezone offset, and deal with it as a presentation concern.
It's also possible to use JavaScript to determine the user's probable timezone: examine the timezone offsets for some pair of Date objects reasonably close to the solstices (even January 1 and July 1 makes a suitable approximation) to obtain a coarse timezone identification. Feel free to use this information to determine a default timezone, but do allow it to be changed by the user: JavaScript doesn't provide sufficient detail to select the exact timezone with national and regional historical shifts, and it may not be enabled by the user anyway.

Resources