Converting moment.js to JSON shows incorrect time - javascript

I have a method which sets the created property of my token, like so:
const token = new Token();
console.log(moment().toDate());
token.created = moment().toDate().toJSON();
There's something I just can't get my head around and it's really confusing me.
The line console.log(moment().toDate()); prints Tue Sep 01 2020 14:11:39 GMT+0100 but when I check the property created on debugger although it's using the same moment object and methods (except from calling toJSON()) it produces a date time which is an hour behind like so: 2020-09-01T13:11:39.179Z
I store the moment date as a string in the created property because this will be stored in localStorage.
Does anyone know the reason for this?

The times are the same. Look closely.
One marks the time zone as Z, the other as GMT+1.
Those time zones are 1 hour apart.
You can specify the time zone

Related

Using moment.utc() incorrectly converting the date into utc format of "days" format-Moment Javascript

I'm using moment library to convert date into a utc format. here is my date string:
var dateString = "2019-01-31T11:33:16.952+0000";
new Date("2019-01-31T11:33:16.952+0000") // o/p: Thu Jan 31 2019 03:33:16 GMT-0800 (Pacific Standard Time)
since this date is less than a week from today's date, I'm trying to display a text saying "n days ago" instead of actual date. But for some reason I'm getting a future date displayed as "6 days ago" when I do this:
moment.utc("2019-01-31T11:33:16.952+0000").local().fromNow() // shouldnt this display "5 days ago"??
Not sure why moment is not converting the date correctly, any ideas what could be wrong here?
I guess(Considering use of local() converts to your local timezone so time is deducted because you might be in -ve TimeZone) this answer is a solution you're expecting:
Ideally, you would want to pass a UTC timestamp from your server to
the client. That doesn't mean you have to switch your whole server
over to UTC, it just means that you would convert from the time in
your database to UTC on the server before sending it over the web.
Sure, it would be even better if you actually stored times in UTC, but
you said you aren't in a position to make that sort of change right
now. But let's just work off the assumption that you can't change
anything at all on the server.
We'll also assume that your server is fixed to the UTC-07:00 offset.
In real life, this would only be true for places like Arizona that
don't follow daylight saving time. So if you are in Los Angeles and
are in Pacific Time, then some of your data is based on UTC-07:00, but
some of it is based on UTC-08:00. That requires a lot more work if you
want to do it in JavaScript.
Let's also assume that the input is already a string in ISO8601
format. (If it's not, then let me know and I will adjust this code.)
var s = "2013-09-11 18:00:00"; // from action.timeStamp
var actionTime = moment(s + "-07:00", "YYYY-MM-DD HH:mm:ssZ");
var timeAgo = actionTime.fromNow(); The reason your other code didn't
work is because in the first line, you are affected by the time zone
of the browser. The zone setter in the second line just changes the
zone for formatting, not changing the actual moment in time.
Also, when you dump a moment to the console for debugging, make sure
you format it for output. Otherwise you are just looking at its
internal property values, which may or may not make sense directly.

Date Handling Unix Date Incorrectly (or I'm using Date incorrectly?)

I have the following data structure. The first column is intervals. The first row of the interval datum is a unix time and the subsequent data are intervals (i.e. 300*1, 300*2, ect). The other column is the data values. Here is the head of the data:
a1521207300,555.45
1,554.53
2,554.07
3,553.9
4,552.67
And here I went about converting the unix time to a Date object. The a here is ornamental, so I slice() at 1 like so:
var rawTime = data[0].interval;
var timeValue = Math.round(rawTime.slice(1));
console.log(timeValue)
console.log(new Date(timeValue))
I also tried using parseInt() instead of round(). The console shows that this unix time is equivalent to: Jan 18 1970 which I had quite the guffaw at. Then I got to thinking, maybe I did something wrong. It's supposed to be a very recent date -- March 16th 2018. This is strange because my understanding is that javascript can be passed a unix date directly as per this answer.
I also checked the unix time at a conversion site: www.onlineconversion.com/unix_time.htm
Which confirmed that it's indeed a March 16th 2018 timestamp.
Question: Why is this unix date for my March 2018 data being treated like a 1970's date? Maybe the a is actually doing something after all... Anyway, what is the correct way to handle this time stamp? It's only 10 numerical digits, it does not seem to be a precision problem. Date can handle unix times up to 13 digits I believe.
As per the documentation, when you invoke new Date(value) with an integer value, it is used as the number of milliseconds since January 1, 1970. To get the date you want, the value 1521207300 appears to be number of seconds instead of milliseconds. That is, you missed a factor of 1000. new Date(1521207300000) gives Fri Mar 16 2018.
When I take away new from new Date it seems to be ok. Not sure why though.
The documentation mentions the different behavior:
Note: JavaScript Date objects can only be instantiated by calling JavaScript Date as a constructor: calling it as a regular function (i.e. without the new operator) will return a string rather than a Date object; unlike other JavaScript object types, JavaScript Date objects have no literal syntax.
It seems when called as a function Date(value), it treats the value as the number of seconds, instead of milliseconds. I didn't dig deep enough to confirm this, because it doesn't matter: the documentation says to not use it this way (and since it gives a string instead of a date object, it's not very useful anyway).

How to change only timezone without modifying the time in momentz

I have date and time in 2016-06-21T10:00:00-07:00 format which represets 06/21/2016 5 PM in PST, I just want to change this to 06/21/2016 5 PM in EST and vice versa. How can I do it with momentz?
JSFiddle
debugger;
var dateTime = moment('2016-06-21T10:00:00-07:00');
var newDateTime = dateTime.clone();
newDateTime.tz('US/Eastern');
//dateTime = dateTime.utc();
console.log(dateTime.utcOffset());
console.log(newDateTime.utcOffset());
console.log(newDateTime.utcOffset() - dateTime.utcOffset());
//console.log(utc.format());
dateTime = dateTime.add(newDateTime.utcOffset(), 'minutes');
console.log(dateTime.format());
console.log(new Date(Date.parse(dateTime.format())).toJSON());
EDIT:
given input = 2016-06-21T08:00:00-07:00 (PST)
expected output = 2016-06-21T08:00:00-04:00 (EST)
So when I convert that to UTC then it should become
2016-06-22T15:00:00Z for PST
2016-06-22T12:00:00Z for EST
I think you are confused about how ISO8601 format works. This format always represents local time with a time zone offset. Thus 2016-06-21T10:00:00-07:00 represents June 21 2016 at 10 AM in a timezone that is currently UTC-7 (this could be US pacific, among many others).
It sounds like you want to take the local time, but put it in a new timezone. This opens up some interesting questions about why you are receiving the date in the format that you are. If the date is meant to be interpreted as an exact point on the global timeline, then the format you are receiving it in is good. If however, the date is meant to be interpreted as a local time (not relative to UTC), it might be worth considering the possibility that the format of the date needs to be changed at the source. For instance, if you are making an ajax request to an API, and it is returning a date in this format, but that date actually has no relationship to UTC, it would be good to try to change that API to only send the local time (without the offset). If you were able to do that, then the following code would work:
moment.tz('2016-06-21T10:00:00', 'America/New_York').format()
"2016-06-21T10:00:00-04:00"
If you are unable to do that, or if the date is meant to be interpreted as an exact point on the global timeline, but you wish to ignore that in your specific use case, that can be done. You will need to specify a parse format that ignores the timezone offset on your initial time stamp. The code would be as follows:
moment.tz('2016-06-21T10:00:00-07:00', 'YYYY-MM-DDTHH:mm:ss', 'America/New_York').format()
"2016-06-21T10:00:00-04:00"
You might benefit from the material in this blog post, as it covers how ISO8601 format works, and how all of moment's constructor functions work.
Checkout moment().utcOffset() You can pass in the offset as parameter to this function and the date would use that locale.
Assuming you know beforehand the utcOffsets required which in your case are -420 and -240 or -300(EST with DayLightSaving). Below can be done
var dateTime = moment('2016-06-21T10:00:00-07:00');
dateTime.utcOffset(-420).format();
"2016-06-21T10:00:00-07:00"
dateTime.utcOffset(-240).format()
"2016-06-21T13:00:00-04:00"
NOTE: With -04:00, it should 13:00:00 and not 07:00:00 - http://www.timeanddate.com/time/zones/est
EDIT: This answer was posted to the earlier version of question, where same time was needed in different timezones. If it is incorrect, kindly please elaborate on how it is.
Thanks!

How do I append the user's timezone to a string in Javascript?

I found some code here on Stack Overflow that does exactly what I want, which is to take a GMT time string and convert it to the local time on the user's browser. Awesome.
However, I'm stuck on what should be a very small thing. When I display the time, I want the user's current local timezone to display along with the time. The goal is to output a string that looks something like:
2014/02/19 15:12 (PST)
I've looked at the parameters for the Javascript Date() function, but, unless I'm blind, I don't see one that outputs the user's timezone. There's getTimezoneOffset(), which returns a number, but not the code for the timezone.
I've got all the rest of the time displaying fine, except for that last part where I want it to say PST (or GMT or JST or wherever the user is). Is there a way to do that?
It can be done creating a date and then performing some operations on it. If you take a look at format in which newly created Date object is created it is e.g. like:
Wed Feb 19 2014 07:29:26 GMT+0100 (Central European Standard Time)
Now you may simply take the whole name like:
var myDate = new Date();
var userTmzn = myDate.substring(myDate.lastIndexOf('(')+1).replace(')','').trim()
and this should give you this in userTmzn
Central European Standard Time
Now to make it neat and have an abbreviation you may try some more operations:
// Take the part with timezone name and strip it from trailing ')'
var fullName = myDate.split("(")[1].replace(")","");
// Split into words
var words = fullName.split(" ");
// Take just first letters
var timezoneCode = "";
for(i = 0; i < words.length; i++)
{
timezoneCode += words[i].charAt(0);
}
That should give you (following the same example) this in timezoneCode variable:
CEST
This is highly custom, not a ready solution. You should verify in the code that default date's toString() returns date in TIME FORMAT, you should test on various browsers, etc. This is just a clue.

Using timezones with moment.js fromNow() or from()

I want to show users how long has been elapsed since they performed an action.
The date+time of the action happening is stored on the server, in the server's timezone. That's what's causing the trouble, since if the user's computer's timezone is 12 hours ahead of the server's timezone, then if the user adds something right now, moment.js will show '12 hours ago' as the output of fromNow() rather than just now.
To try to solve this, I'm trying the following method:
var actionTime = moment( action.timeStamp);//time of when user performed action
var serverTime = moment().zone('-07:00'); //current server time
console.debug( serverTime);//outputs Wed Sep 11 2013 15:19:51 GMT-0700
var timeAgo = serverTime.from( actionTime);
But despite of all this, timeAgo still shows the difference between the client's timezone and the server's timezone (i.e showing '12 hours ago' instead of 'now');
Anyone know how to fix this or what I'm doing wrong?
Ideally, you would want to pass a UTC timestamp from your server to the client. That doesn't mean you have to switch your whole server over to UTC, it just means that you would convert from the time in your database to UTC on the server before sending it over the web. Sure, it would be even better if you actually stored times in UTC, but you said you aren't in a position to make that sort of change right now. But let's just work off the assumption that you can't change anything at all on the server.
We'll also assume that your server is fixed to the UTC-07:00 offset. In real life, this would only be true for places like Arizona that don't follow daylight saving time. So if you are in Los Angeles and are in Pacific Time, then some of your data is based on UTC-07:00, but some of it is based on UTC-08:00. That requires a lot more work if you want to do it in JavaScript.
Let's also assume that the input is already a string in ISO8601 format. (If it's not, then let me know and I will adjust this code.)
var s = "2013-09-11 18:00:00"; // from action.timeStamp
var actionTime = moment(s + "-07:00", "YYYY-MM-DD HH:mm:ssZ");
var timeAgo = actionTime.fromNow();
The reason your other code didn't work is because in the first line, you are affected by the time zone of the browser. The zone setter in the second line just changes the zone for formatting, not changing the actual moment in time.
Also, when you dump a moment to the console for debugging, make sure you format it for output. Otherwise you are just looking at its internal property values, which may or may not make sense directly.
I have solved it in a different way, maybe this option was not possible back when the question was asked, but might be easier now.
I used moment-timezone.js (which requires moment.js 2.6.0+).
I set the default timezone to my server's timezone like this:
moment.tz.setDefault("America/New_York"); // "America/New_York" in my case
and then just use it normally. fromNow() will use the timezone in the client to calculate the time that has passed since that moment.
moment(myDatetime).fromNow();
i had the same issue and used the above comments to modify my code. I did the following to get it resolved:
transform(value: string) {
var time = moment(value).utc();
return moment(time, "YYYYMMDD").fromNow();
}
I was missing the .utc() to convert it before I applied the .fromNow()
Things to note this is being used within a Pipe for Ionic 3 and the above code is from the pipe logic.

Categories

Resources