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!
Related
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.
I receive the following date from the server:
"2018-11-21 07:00:00 UTC"
Then, I convert it using userTimzone variable (since I wish the editor would use the user timezone):
dateOfAction: moment(dateOfLoss, 'YYYY-MM-DD HH:mm Z').tz(userTimzone).unix(), So dateOfAction is 1542776400. That is: Wednesday, November 21, 2018 5:00:00 AM - and so far so good. That is the dateOfAction in UTC with after right offset
I'm using react-datetime as the calendar the edit the date, using UTC.
When performing the save action, without touching the date, the calendar output is still 1542783600, but I wish to be 1542783600 - i.e the same value as in the beginning, reverting the offset at the other direction.
How can I achieve that?
A few things:
Moment doesn't map the Z token to the string "UTC". Since you're parsing in local mode, you are actually getting a moment based on the local computer's time zone rather than UTC. Thus, change the first part of your code to:
moment.utc(dateOfLoss, 'YYYY-MM-DD HH:mm [UTC]')
The brackets are to treat UTC as a literal string, which isn't strictly required so you can omit it if you like and the result will be the same.
moment.utc(dateOfLoss, 'YYYY-MM-DD HH:mm')
There's no need to call .tz(userTimezone) if you're just going to call .unix() subsequently. Unix timestamps are always UTC based. Though it's not clear why you're asking for a Unix timestamp, as react-datetime doesn't need one.
The two values you gave in the last paragraph of your question are identical, so I'm not sure specifically what you were looking for. The time you gave is indeed 1542783600, not 1542776400.
The readme file of react-datetime describes all the options you can use. You can simply pass the moment object obtained above to the value prop. You might need to use the utc or displayTimeZone props if you want to change the behavior. You might also need to call .local() or .tz(userTimezone) on the moment object before passing it in, but I'm not certain if that is required or not for this particular component.
I need to set a datetime-local picker's default value to the current local time. Native JS seems to output in local time by default:
new Date($.now()); // "Sat Nov 12 2016 22:36:52 GMT+1100 (AEDT)"
However functions like toISOString() output in UTC, and although I can pull out individual components locally, I don't really want to fiddle around with padding and such. So I try this using moment.js:
moment().local().format(); // "2016-11-12T22:34:05+11:00"
Cool! Now I just need to adjust the format to a tiny bit:
moment().local().format('YYYY-MM-DThh:mm'); // "2016-11-12T10:39"
Waaaaaaait. Now it's in UTC again, even though I specified local.
In this particular case I could use string manipulation to just drop the end off for the date-time picker, but surely I'm going to reach a point where I want to output the local time in an arbitrary format. Am I missing something here?
Your second example isn't UTC, it's just using 12h format.
hh = 12h, HH = 24h. Try this instead:
moment().local().format('YYYY-MM-DTHH:mm')
In a nutshell I want moment to respect server's timezone. I've set my machine's timezone to Alaska but I'm passing a Brisbane timezone string to moment. Now I need moment.toDate to return a date instance in the same timezone as the one I pass in the moment constructor; e.g.
m = moment("2016-11-20T08:00:00+10:00")
m.format() // "2016-11-20T08:00:00+10:00"
m.toDate() // Sat Nov 19 2016 13:00:00 GMT-0900 (AKST)
I want to get a Date instance from moment that's in the input timezone; e.g. somehow get toDate to return Sun Nov 20 2016 08:00:00 GMT+1000 (AEST).
FWIW I have tried the same code with and without moment.tz.setDefault and while it correctly changes the format result, toDate always uses the machine's timezone!
Update
The reason I need this behaviour is that some JavaScript libraries and controls don't understand moment and only work with Date and the time/date gets skewed when presented back by them. One example, the one I'm currently dealing with, is jQuery UI date picker control. I want the date picker to show the current date as it's on the server (or on a specific timezone).
Thanks in advance.
The Date object represents the time in UTC internally, and can only use the time zone of the machine its running on when projected.
There's absolutely no way to produce a Date object that uses an arbitrary time zone. Any examples you may come across that try to manipulate the Date object (such by adding or subtracting time zone offsets) are fundamentally flawed.
Moment itself has great time zone support, including the moment-timezone extension for working with named time zones instead of just time zone offsets. But once you go back to a Date object - you're back at the mercy of the behavior of that object.
Sorry, but there's no way to achieve what you are asking. Perhaps you could elaborate as to why you wanted to do this, and I could recommend a workaround.
Update: With regards to your update, usually there is a mechanism for getting the value from a date picker as text, rather than as a date object. With the example of the jQuery UI date picker control, the onSelect event gives it to you as text already, or you can simply call .val() instead of .datepicker('getDate') to get the text out of the field. Once you have a textual value, you can then parse it with moment however you like.
Similarly, when setting the value, you don't necessarily need a Date object. You could just set the value of the textbox as a string, or you can pass a string to the setDate function.
In most cases, you won't have to go through a Date object. But if for some reason you do, then you'll need to artificially construct one with something crazy like:
var d = new Date(m.format('YYYY/MM/DD'));
Normally, I'd be against that - but if it's just there to get the pass a value to a UI control, then it's probably ok.
This will get you a moment in the same timezone as the moment string, but toDate is always in the local timezone.
d = "2016-11-20T08:00:00+10:00"
m = moment(d).utcOffset(d)
m.format()
m.toDate()
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.