moment.js returns different timezones - javascript

I'm using this code to create 2 dates that represent a filter date range (in this case the last 3 months):
$ctrl.startDate = moment().utc().startOf('month').add(-2, 'months').toDate();
$ctrl.endDate = moment().utc().endOf('month').add(0, 'months').toDate();
However the first returned date is timezone CET (GMT+1) (which is my zone) and the second is CEST (GMT+2). I have no idea why! I have tried using utc() to get "neutral" dates without success.
Returned dates:
01.01.2017 01:00:00 CET
01.04.2017 01:59:59 CEST
I want either GMT or CET but the same zone! Where does moment take these 2 zones from?
I've come so far that I think it is a bug.
I use version 2.17.1
Any ideas?
JSFIDDLE:
https://jsfiddle.net/FLhpq/8807/

I don't know if you can consider it a bug, in your fiddle you are showing in the result of toDate() that as docs says:
get the native Date object that Moment.js wraps
If you look at momentjs the code you will see that toDate() implementation:
function toDate () {
return new Date(this.valueOf());
}
simply uses new Date() that returns a JavaScript date object in local time, see MDN Date:
Note: Where Date is called as a constructor with more than one argument, the specifed arguments represent local time. If UTC is desired, use new Date(Date.UTC(...)) with the same arguments.
If you use format() in your code you will always see +00:00 offset.
var divUtc = $('#divUTC');
var divLocal = $('#divLocal');
var startDate = moment.utc().startOf('month').add(-2, 'months').format('YYYY-MM-DDTHH:mm:ssZ');
var endDate = moment.utc().endOf('month').add(0, 'months').format('YYYY-MM-DDTHH:mm:ssZ');
//put UTC time into divUTC
divUtc.text(startDate);
divLocal.text(endDate);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.7/moment-timezone-with-data-2010-2020.min.js"></script>
UTC<br/>
<div id="divUTC"></div><br/>
Your Local Time with respect to above UTC time<br/>
<div id="divLocal">
</div>

Related

Moment.js resolve timezone offset

I'm working in an Angular 6 front end and receive from another system time stamps which have no time zones (C# backend, DateTime). I suspect that javascript is automatically adding the local time zone to Date objects.
Example:
Receiving from backend: 2018-10-15T07:53:00.000Z
When console logging: console.log(timestamp) // Mon Oct 15 2018 09:53:00 GMT+0200
I am using moment.js and already tried moment.utc() and moment(DATE).utc(). But it still adds the local time zone especially because I have to re-transform my moment objects back to the type Date with .toDate().
How can I resolve the time zone difference and get back a utc date to work with or the same structure as received?
try to format use as per desired.
let str = '2018-10-15T07:53:00.000Z';
let moment = moment(str).utcOffset(str)
console.log(moment.format('DD/MM/YYYY HH:mm'))
<script src="https://momentjs.com/downloads/moment.js"></script>
Second Snippet (to use the date object from string)
let str = '2018-10-15T07:53:00.000Z';
let moment = moment(str).utcOffset(str);
console.log(moment.toDate())
<script src="https://momentjs.com/downloads/moment.js"></script>
Your input is UTC and will be parsed just fine. Javascript Dates have no notion of timezone! The local timezone is applied by the static methods for serializing (Date.toString(), Date.toDateString() etc.) (Console.log(Date) uses Date.toString().)
Use Date.toLocaleString([],{timeZone:"UTC"}). Forcing UTC, you will see in the output the same time as the input. Much more details are here :-)
Here it is working:
console.log(new Date('2018-10-15T07:53:00.000Z').toLocaleString([],{timeZone:'UTC'}))

Javascript Date Function ISO8601

I thought I had a standard ISO date and the Javascript Date() function should convert it with no parsing, but I get the following:
my date :
2015-12-08T13:42
Javascript date function result:
Tue Nov 12 2075 13:42:00 GMT+0100
Is my date in an incorrect format or have I misunderstood the Data function?
I should have added that I'm using Adobe Illustrator CS6. I've tried an examples from below and I get the same result:
My code:
var start = '2015-12-08T13:42';
var test0 = new Date(start);
var test1 = new Date(start+'Z').toString();
$.writeln(test0);
$.writeln(test1);
The result:
Tue Nov 12 2075 13:42:00 GMT+0100
Tue Nov 12 2075 13:42:00 GMT+0100
To specify UTC time as string, you need to add the Z part to it.
Quoted from Wikipedia:
If no UTC relation information is given with a time representation, the time is assumed to be in local time.
If the time is in UTC, add a Z directly after the time without a space. Z is the zone designator for the zero UTC offset.
I see that difference when running the following snippet in Firefox and in timezone GMT+01:00. But Edge and Chrome show the first output also as if the Z was there (which seems contrary to the above quotes), and so there is no difference visible:
var s = '2015-12-08T13:42';
console.log(new Date(s).toString());
console.log(new Date(s+'Z').toString());
Make sure the way you turn the Date value into string is correct. The toString() call (used in the snippet) will do this conversion into the current locale's date/time.
But if you use a custom function for that, you need to be aware of some pitfalls. For instance, if you use the getMonth or getUTCMonth methods to retrieve the month number of the given date, be aware that it is zero-based, and the month December is thus numbered 11. If your string conversion interprets this 11 as to mean November, you'll be one month off.
i think you u set the date to setUTCDate function if you pass the current date to setUTCDate function it get wrong date
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>
function myFunction() {
var d = new Date();
d.setUTCDate(2015-12-08);
document.getElementById("demo").innerHTML = d;
}
</script>
</body>
</html>
if you want get current date use Date() function
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>
document.getElementById("demo").innerHTML = Date();
</script>
</body>
</html>
I thought I had a standard ISO date and the Javascript Date() function should convert it with no parsing,
To convert a string to a Date, it must be parsed, you can't avoid that.
but I get the following:
my date :
2015-12-08T13:42
Javascript date function result:
Tue Nov 12 2075 13:42:00 GMT+0100
Is my date in an incorrect format or have I misunderstood the Data
function?
Apart from the year, that is the expected result. From ES5, ISO 8601 format date strings are parsed by the Date constructor (and Date.parse, they are equivalent for parsing).
A plain date string (e.g. 2015-12-08) should be parsed as UTC. A date and time should be parsed as either local if no timezone is provided, or using the provided timezone.
The string "2015-12-08T13:42" does not have a timezone, so it will be parsed using the host timezone settings to produce a date that is equivalent to a local date and time of 8 December, 2015 at 1:42 pm. So it will represent a different moment in time in each time zone with a different offset.
Parsing of strings with the Date constructor is strongly discouraged as it is largely implementation dependent, either write a simple function or use a library. You don't say whether you want the string parsed as local or UTC, a simple function to parse it as UTC is:
// 2015-12-08T13:42
function parseISOAsUTC(s) {
var b = s.split(/\D/);
return new Date(Date.UTC(b[0], --b[1], b[2], b[3], b[4], b[5]||0));
}
var d = parseISOAsUTC('2015-12-08T13:42');
console.log('Local: ' + d.toLocaleString() +
'\nUTC: ' + d.toISOString());
You should add some validation to deal with out of bounds values.

Displaying timezone-formatted date as UTC time

on my UI, I try to display a date based on a specific timezone. In this example, I will use Americas/New_York as the timezone. This is how I did it.
$scope.getStartTime = function(){
var date = new Date();
return moment(date).tz("Americas/New_York").format('YYYY-MM-DD HH:mm:ss');
};
Afterwards, I want to send this data and send it to my server. In my server however, I want it so that it is always serialized into UTC time instead of in the New York Timezone (EST).
For example, if the time was 12:00 P.M. in New York, then the time would be serialized to 4:00 P.M. in UTC time before it was sent to the backend. This was my attempt:
var date = getStartTime();
....
// Display the date in the UI
....
$scope.revertStartTime(date);
$scope.revertStartTime = function(startTime) {
console.log("Start time: ", startTime);
console.log("Moment: ", moment(startTime).format());
console.log("Converted to utc time: ", moment().utc(startTime).format());
return moment.utc(startTime).format("YYYY-MM-DD'T'HH:mm:ss.SSSZ");
}
I tried to revert the start time by using the moment().utc() function and hoped that the date would change to a UTC based date but unfortunately it keeps turning my date into the localized date instead of UTC date and I'm not sure why. Any help would be appreciated. Thanks!
Edit:
Tried to follow the below method and here is what I did:
$scope.getStartTime = function(){
var date = new Date();
var startTime = new moment(date).tz($rootScope.userinfo.timeZone).format('YYYY-MM-DD HH:mm:ss');
$rootScope.offset = moment().utcOffset(startTime);
console.log("offset: ", $rootScope.offset);
return startTime;
};
$scope.revertStartTime = function(startTime) {
console.log("User Selected Time: ", moment().utcOffset(startTime).format('YYYY-MM-DD HH:mm:ss'));
return moment().utcOffset(startTime).format('YYYY-MM-DD HH:mm:ss');
}
But all I get is an error saying that revertStartTime returns an Invalid Date.
A few things:
Hoping it's a typo, but just to point out, the zone ID is America/New_York, not Americas/New_York.
You can pass a value as moment.utc(foo), or moment(foo).utc(), but not moment().utc(foo). The difference is that one interprets the input as UTC and stays in UTC mode, while they other just switches to UTC mode. You can also think of this as "converting to UTC", but really the underlying timestamp value doesn't change.
Yes, you can switch to UTC mode and call format, but you can also just call .toISOString() regardless of what mode you're in. That's already in the ISO format you're looking for.
Note that if you start with a unique point in time, and you end with converting to UTC, no amount of switching time zones or offsets in the middle will change the result. In other words, these are all equivalent:
moment().toISOString()
moment.utc().toISOString()
moment(new Date()).toISOString()
moment.utc(new Date()).toISOString()
moment(new Date()).utc().toISOString()
moment().tz('America/New_York').toISOString()
moment.tz('America/New_York').toISOString()
moment().utcOffset(1234).toISOString()
moment.utc().format('YYYY-MM-DD[T]HH:mm:ss.SSS[Z]')
moment().utc().format('YYYY-MM-DD[T]HH:mm:ss.SSS[Z]')
Only the last two even need to be in UTC mode, because the format function would produce different output if in local mode or in a particular time zone.
In order to accomplish this you'd want to use .utcOffset(). It is the preferred method as of Moment 2.9.0. This function uses the real offset from UTC, not the reverse offset (e.g., -240 for New York during DST). Offset strings like "+0400" work the same as before:
// always "2013-05-23 00:55"
moment(1369266934311).utcOffset(60).format('YYYY-MM-DD HH:mm')
moment(1369266934311).utcOffset('+0100').format('YYYY-MM-DD HH:mm')
The older .zone() as a setter was deprecated in Moment.js 2.9.0. It accepted a string containing a timezone identifier (e.g., "-0400" or "-04:00" for -4 hours) or a number representing minutes behind UTC (e.g., 240 for New York during DST).
// always "2013-05-23 00:55"
moment(1369266934311).zone(-60).format('YYYY-MM-DD HH:mm')
moment(1369266934311).zone('+0100').format('YYYY-MM-DD HH:mm')
To work with named timezones instead of numeric offsets, include Moment Timezone and use .tz() instead:
// determines the correct offset for America/Phoenix at the given moment
// always "2013-05-22 16:55"
moment(1369266934311).tz('America/Phoenix').format('YYYY-MM-DD HH:mm')

Stop Javascript DateTime adjusting to local time zone

I am receiving the correct unix time that I use in my html page in my javascript. However, when I view or alert the unixtime, what happens is that the date is adjusted based on my desktop's current timezone, but I need the DateTime to be without the timezone.
This is how I pass the data in my javascript, one of the many ways I use the unixtime:
<script type="text/javascript">
$(document).ready(function(){
var a = <?php echo "1434203820"; // an example only?>;
var date = new Date(a);
alert(date);
});
</script>
what the unix time should show is:
Jun 13 2015 13:57 (if it was converted)
but it is showing this date:
Jun 13 2015 21:57 malay peninsula time
What basically happens is that the javascript gets my local time zone and converts that date to that time zone. How could I force it(and all other javascript functions that I use) to use the original time it supposed to be showing?
If you want the UTC format you can use one of the many UTC methods. For instance you could use Date.prototype.toUTCString:
var unixTS = 1434203820 * 1000; // JS date is in millseconds
var date = new Date(unixTS);
document.write(date.toUTCString());
Maybe what you want is converting back the timestamp to UTC format ?
How do you convert a Javascript timestamp into UTC format?

Moment.js Convert Local time to UTC time does work

I would like to use Moment.js to convert a local time to UTC equivalent. I believe that I have the correct method in place, but it does not alter the time.
I'm in Sydney Australian +11 and expect the UTC time to be 11 hours earlier.
Internally on the moment object the isUTC flag changes from false to true, but the time does NOT shift, am I meant to use a different technique for this.
How do I actually get the current UTC date out of this object
Before Conversion
var val = '18/03/2015';
var selectedDate = moment(val, 'DD/MM/YYYY');
After Conversion
var a = selectedDate.utc()
I just tried this code and it seems like I get the correct UTC time. I guess I just want to confirm that what I am doing is correct way to access the UTC time from moment.js
a.format("YYYY-MM-DD HH:mm:ssZ")
I found that my usage pattern of in my application was incorrect
selectedDate.utc().format(fullFormat)
It should have been
moment.utc(selectedDate).format(fullFormat)
This works
moment(date_to_convert).utc().format("YYYY-MM-DD HH:mm:ss");
The question is old, but I also faced it. It may be useful to someone:
Using the method of utcOffset() to calculate the UTC time:
selectedDate = (moment(selectedDate).add(-(moment().utcOffset()), 'm'));
And explicitly specify UTC:
selectedDate = moment.parseZone(selectedDate).utc().format();
This is how you do it using moment-timezone
moment.tz(localDate, localTimeZone).utc()
This worked for me !!
selectedDate = moment(selectedDate).add(moment(selectedDate).utcOffset(), 'm').utc().format()
Create a local moment object from you local time and convert it to UTC then format it, then create a new UTC moment from that formatted UTC string
var localDateString = '24/04/2019';
var localDateStringFormat = 'DD/MM/YYYY';
var utcMoment = moment.utc(moment(localDateString, localDateStringFormat ).utc().format('YYYY-MM-DD HH:mm:ssZ'))
console.log(utcMoment);
<script src="https://momentjs.com/downloads/moment.js"></script>
After few frustrating hours, I found what was the problem
Short Answer: To convert time to utc, we need to use format()
Long Answer: Take the example
moment.utc(1559586600000).format('LLL')
.utc sets the isUTC flag to true.
When logging the date, the d key always shows the time in local timezone. (Which makes us believe its not working properly - as shown in your screenshot)
But we need to use .format to get the date/time in UTC format.
The above code returns June 3, 2019 6:30 PM which is the correct UTC time.
const moment = require('moment-timezone');
const dateTime='2020-12-21'
const timezone='America/Anchorage'
const dateTimeInUtc = moment(dateTime).tz(timezone).utc().format();
console.log('dateTimeInUtc',dateTimeInUtc);
const moment = require('moment-timezone');
const dateTime='2020-12-21'
const timezone='America/Anchorage'
const dateTimeInUtc = moment(dateTime).tz(timezone).utc().format();
console.log('dateTimeInUtc',dateTimeInUtc);
After few frustrating hours, I found what was the problem
Short Answer: To convert time to utc, we need to use format()
Long Answer: Take the example
moment.utc(1559586600000).format('LLL')
.utc sets the isUTC flag to true.
When logging the date, the d key always shows the time in local timezone. (Which makes us believe its not working properly - as shown in your screenshot)
But we need to use .format to get the date/time in UTC format.
The above code returns June 3, 2019 6:30 PM which is the correct UTC time.

Categories