Issue with time zone in react native app using moment js - javascript

I'm getting a 60-minute offset and I'm not sure why.
When I create a date, I get the following date:
Tue Feb 27 2018 11:30:28 GMT+0100
When I retrieve it from the database, I get the following date:
2018-02-27T11:30:28.000Z
I then display if with the following line of code:
moment(this.props.starttime).format('LT')
And get this in my view:
12:30
But I can see the value of the moment object being the following:
2018-02-27T11:30:28.000Z
Apparently, I have a 60 minutes offset from UTC time.
What's going on here? Because when the user select 11:30 in this case, it displays 12:30 in the view afterwards.
Edit 1: This is how I send the dates to my database
axios.post( `https://xxxxxx.ngrok.io/api/book?starttime=${moment(this.props.starttime).format()}`)
and this is how I save it in my database (Rails API)
def create
#request = Request.new(start_datetime: params[:starttime])
end

It looks like you're losing the offset from UTC somewhere between creating the date and saving it in your database, and that your server uses UTC while your client system uses UTC+0100.
Exactly how do you create the date and then save it so that you can retrieve it later?

Related

What do we mean when we say store time as UTC? [duplicate]

This question already has answers here:
When is it ok to store datetimes as local time rathen than UTC?
(1 answer)
How to store repeating dates keeping in mind Daylight Savings Time
(1 answer)
Managing timezone & DST issue for javascript application
(1 answer)
java Calendar, Date, and Time management for a multi-timezone application
(1 answer)
Closed 3 years ago.
I have a scheduling application, with a calendar that I build from scratch.
As a lawyer, you should be able to configure your available times for booking, like below:
A lawyer's availabilities in Australia
:
1- 10/01/2020, from 07:00am to 08:am
...
Here's what I do :
1- Get the epoch number of the entered date in Javascript :
const dateFrom = new Date(firstOfJanSevenAm).getTime() // 1578600000000
// Fri Jan 10 2020 07:00:00 GMT+1100 (Australian Eastern Daylight Time)
const dateTo = new Date(firstOfJanEightAm).getTime() // 1578603600000
// Fri Jan 10 2020 08:00:00 GMT+1100 (Australian Eastern Daylight Time)
2- Send this to NodeJS server and save it MongoDB
Mongoose.save({
from:dateFrom, //1578600000000
from:dateTo //1578603600000
})
3- Represent it inside the Calendar :
<div>{format(from, 'HH:mm')}</div>
Everything is working as expected.
Now, this lawyer is traveling to the US and he's in a coffee shop using the US local time ( any city), he opens the Calendar, he wants to add some availability, but in Sydney time. I need to provide him with a timezone dropdown so he can tell me that he wants the new date to be based on his home, Syndey.
Question :
1- Do I save the date as I'm doing ( as a number ), and save the timeZone separately next to it, and when representing it, just apply the timeZone?
Mongoose.save({
from:dateFrom, //1578600000000
from:dateFrom //1578603600000
currentTimeZone : 'America/Costa_Rica',
desiredTimeZone: 'Australia/Sydney'
})
<div>{formatWithTimeZone(from, 'HH:mm',desiredTimeZone)}</div>
Is this all I have to do? Or am I naively missing something that is going to trip me down the road?
And back to my original questions, where do I do the whole "always store time as UTC" thing?
All I've realized is, when I use the library that I'm using date-fns-tz and try to convert the user entered date to UTC, I get exactly the same output :
const dateFrom = new Date(firstOfJanSevenAm).getTime() // 1578600000000
const dateFromUTC = zonedTimeToUtc(dateFrom,currentTimeZone) // 1578600000000
// currentTimeZone is America/Costa_Rica, when he is in Costa Rica's caffee shop.
enter code here
1578600000000 === 1578600000000 = true
So why do I get the same output when converting the entered date, to it's UTC date?
I am going to give you an answer decoupled from the technical implementation.
Let's think by contradiction, you have a lawyer living in Australia and another living in Switzerland, what happens if you decide to store time in their preferred location?
You then need to save two information: the time of course (11 am) but it's relative so you also need to store the timezone (11 am in Australia) or (1 pm in Switzerland)
Now what happens if your lawyer travels to France? Do you want to update all his calendar information? 11 am is not 11 am anymore.
UTC solves this problem, you just need to store 11 am or 1 pm. UTC is arbitrary absolute, universal by convention.
So your backend/database should store this kind of information in UTC, always. And you need a way to know your user's timezone, maybe it's possible to update it using a web interface and it could be stored in a user database or just cookies. Maybe you want to derive it yourself by using your user's location, IP, browser's language, whatever.
Now that you know his timezone, your server can send UTC (absolute) time to the client and the client can seamlessly display the correct (relative) time.
The client deals with relative time, the server always makes it absolute.
So why do I get the same output when converting the entered date, to it's utc date?
The value returned by getTime is the number of milliseconds since 1 January 1970 00:00:00 according to universal time.
Therefore, UTC and getTime both represent a moment in time using the same universal timezone.
Do I save the date as I'm doing, and save the timeZone separately next to it, and when representing it, just apply the timeZone?
Don't save the timezone with the date. Just save the date in universal time. If you need to save timezone. That should go in user settings. However, you can guess the timezone; therefore, you don't need to save this information.
Saving the date
When you do save the date to the database, it should be represented by a UTC time string or by a UNIX timestamp, both options demonstrated below.
UNIX timestamp
UNIX timestamp should be in seconds. getTime returns milliseconds. You can just divide by 1000 to get the UNIX timestamp.
const unixTimestamp = new Date('December 17, 1995 03:24:00').getTime() / 1000;
UTC Date string
const utcDate = new Date('December 17, 1995 03:24:00').toUTCString();
Displaying the date
When you get the date from the back-end, then, converted it to the correct timezone.
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
const fromUnix = utcToZonedTime(1578423483, timezone)
const fromUtc = utcToZonedTime('Fri, 02 Feb 1996 03:04:05 GMT', timezone)
Closing thoughts
Dealing with timezones can be confusing. I am not to familiar with date-fns-tz. If you have the option, I would suggest migrating to Moment.js. Moment.js is the de facto standard JavaScript library these days - I highly recommend it.

How do I deal with dates-only in javascript when it keeps appending a time value?

I have a bunch of date fields (not datetime) in SQL Server. When they are fetched by the web server and sent to the client as JSON a time stamp is appended automatically. So instead of receiving just 2016-09-27 I get 2016-09-27T00:00:00.
When the user interacts with the uiBootstrap calendar control it automatically parses that string into a javascript date object and applies a 4 hour offset for the timezone. When this is sent back to the server it's sent as 2016-09-26T20:00:00. Now my date is off by a day. Also the next time it's fetched it will happen again. But this time it will start at 2016-09-26T00:00:00 and will roll back to 2016-09-25T20:00:00. Each cycle between client and server loses a day.
How do I keep my dates from changing? I'm looking at moment.js but so far haven't really figured out how it can help me.
EDIT
I've setup a test function to try different methods of converting datetimes back and forth.
console.log('JSONDate: ' + JSONDate);
var dt = new Date(JSONDate);
console.log('JS Converted Date: ');
console.log(dt);
console.log('Date converted back to string: ' + dt.toISOString());
Here's the output:
JSONDate: 2016-10-02T00:00:00
JS Converted Date: Sun Oct 02 2016 00:00:00 GMT-0400 (Eastern Daylight Time)
Date converted back to string: 2016-10-02T04:00:00.000Z
In this example the date is now 4 hours ahead.
EDIT 2
Web server is running .net, specifically WebAPI 2. I'm using Entity Framework 6 to communicate between web server and SQL Server 2012.
Ideally, your dates would be serialized in the JSON as just dates. Instead of 2016-10-02T00:00:00, you'd have 2016-10-02. The problem is that .NET doesn't have a built in Date type. It only has DateTime. There are alternatives, such as LocalDate in Noda Time, as discussed in this answer.
However, assuming you don't want to change anything on the back-end, the way to handle this is just to make sure the input date/time is treated as local time, and never converted to/from UTC. This should be the default behavior when you parse the string into a Date object when the string is like 2016-10-02T00:00:00, but the behavior has changed a few times over the years, so if you are potentially dealing with older browsers, you may get some that interpret it as UTC instead.
As far as output goes, the toISOString method of the Date object always outputs in UTC - which is the source of your conversion error. If you want an ISO8601 string in local time - you'd have to construct one yourself using the various accessor functions (getFullYear, etc.), handling zero-padding, and ensuring months are incremented to be 1-based instead of 0-based.
The easier solution is to use moment.js, which can handle this for you.
var d = moment('2016-10-02T00:00:00').toDate(); // now you have a `Date` object
var s = moment(d).format("YYYY-MM-DD[T]HH:mm:ss"); // now you have a string again
Of course, if you don't need the time portion, you can omit it from the format string and the rest should still work out ok.
You could try getting the offset and applying it back to the date. Something like this:
var d = new Date('2016-09-27'); //Mon Sep 26 2016 20:00:00 GMT-0400 (EDT)
new Date(d.getTime() + d.getTimezoneOffset() * 60 * 1000) //Tue Sep 27 2016 00:00:00 GMT-0400 (EDT)

How to specify Local Date and Time in JavaScript

I have an Android App and I wanted to display notification at a given date and time (all local). However if I use UTC format like this which I fetch from server thru json:
2016-04-14T11:30:00Z
the message gets displayed at the same time across the globe using this functions:
var mTime = new Date( element.dateNtime );
What I want is to display the message at 11:30 AM of local time everywhere. Like 11:30 AM in UK all the users will get the notification, but the users in the US will get the notification 5 hours later, i.e. 11:30 local time (EST or whatever).
Update
I think I have found a solution, but from the answers below it appears that the question is either not too clear or is not understood. Here is the scenario:
a. My Cordova App is opened by the user on his mobile
b. The App reads a string date and message from the server at startup in this format "2016-04-14T11:30:00Z". So there is no question of getting current date using new Date() function.
c. Based on this the App sets up a notification for the given date and time using notification plugin of Cordova.
d. When the time comes the notification pops up
The solution is to use NON-ISO format for date, i.e. "'Wed, 09 Aug 1995 00:00:00'" along with Date.parse() function. Using the above example the code will become:
var mTime = Date.parse( element.dateNtime );
If the date is provide in this format ('Wed, 09 Aug 1995 00:00:00') variable mTime will contain exactly the same value. However if the datetime is provided in ISO format ( 2016-04-14T11:30:00Z ) then mTime will contain the time converted to the user's Locale.
If you are using PHP server you can easily achieve by using below code:
$serverdate = date("d m Y");
$indiantime = date('d/m/Y h:i:s A', time()+19800);
Here variable 'serverdate' returns the current date of server , and variable 'indian time' stores the time as Indian Standard Time
For converting time to proper zones use this formula
x * 60 * 60
Where 'x' is the GMT difference, In the case of India its 5.30
so 5.5 * 60 * 60 = 19800
Just instantiate a new Date object
var now = new Date();
That will create a new Date object with the client's local time. To display like 8:30 AM, use
var time = new Date().toString("hh:mm tt");
You can use new Date().getTimezoneOffset()/60 for the timezone. There is also a toLocaleString() method for displaying a date using the user's locale.

DateTime Filter AngularJS not Giving Correct Date?

I am using backend as Tomcat which gives me timestamp as follows :-
1448966450000 If I use the website to convert this time to datetime it gives me something like below :-
1448966450000 -> Wed, 02 Dec 47885 00:33:20 GMT
But when I use a Filter for AngularJS it gives me something like this:-
{{1448966450000 | date: "MMM dd,yyyy '#' hh:mma"}} -> Dec 01,2015 # 04:10PM
I am living at India and according to IST the time which I receive with the filter is pretty wrong. I am not able to understand where the problem lies.
NOTE: Date Shown by angular is wrong while the former one is the correct one.
Take a look at your timestamp, your site needs timestamp in seconds, but angular filter accepts milliseconds, so you need to multiply your timestamp in filter on 1000, you need to enter 1448966450000000, not 1448966450000
Check the timezone: add timezone to output format (Z)
If timezone is not suitable for you, set preferred timezone
{{1448966450000 | date: "MMM dd,yyyy '#' hh:mma" : '+0530'}}
For more information see https://docs.angularjs.org/api/ng/filter/date
The timestamp you are using is in milliseconds since 1/1/1970
The angular filter does it right.
The website you test it wants the timestamp in seconds.

MVC, JsonResult, DateTime and the Timezone

Good Day my fellow programmers,
I now have spent 2 days looking for a solution, and are about to go crazy..
That's the Problem:
On The WebPage, the User modifies an object, and i need to store the time without timezone info.
[ i just care about hours and minutes ]
the object is postet to the Server [ asp.net mvc 5] via ajax as a JsonResult.
Let's say, Server has Timezone UTC + 1 , User selects 09:00 on the webpage, json is ajax't to my controller, and boom - the resulting Object in my mvc controller has a DateTime Object with a time of 10:00 ;
What i have done: Client-side: Store Time Info in UTC Format [so a dateobjet.toUTCString() gives me the correct date i want to have, just before postig to the controller]
So is there a way to tell the JsonResult-Converter to just ignore the Timezone-Info and use the UTC-Time?
Thanks,
Mr.Muh
OK, i hope to describe it in a better (and shorter):
ClientSite: JavaScript date with the time i need in UTC (but still with some timezone information, which i don't need), let's say e.g. 'Fri, 01 Feb 1980 09:00:00 GMT' as a result from .toUTCString()
Get's wrapped up together with other variables in some Json & posted via ajax to my asp.net mvc 5 controller
ServerSide: Controller has my C# - Class as Argument (so automatically converting Json-Object to C# - Class), but the resulting DateTime part now says 10:00:00 due to my server TimeZone set to UTC+1.
So, How can i get the correct UTC time stored to my C# DateTime ?
Thanks :)
If I understand you correctly, you want to ignore the timezone. You can "reset" your DateTime object to UTC (without affecting the actual value) using DateTime.SpecifyKind:
DateTime utcTime = DateTime.SpecifyKind(originalDateTime, DateTimeKind.Utc);

Categories

Resources