Moment.js resolve timezone offset - javascript

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'}))

Related

Moment unable to convert in different timezone

My server is returning me dates in UTC and I want to convert them to the timezone of the server (even if the customer browser is in a different timezone !)
Here is one example, my server is in Europe/Berlin.
var dateAsString = '2022-04-11T22:00:00.000Z'; // 2022-04-12 00:00:00 in Europe/Berlin
var utcDate = moment.utc(dateAsString);
console.log(utcDate.format());
var serverTzDate = utcDate.clone().tz('Europe/Berlin');
console.log(serverTzDate.format());
console.log(serverTzDate.format());
var test = moment.utc('2022-04-11T22:00:00.000Z').tz('Europe/Berlin').format();
console.log(test);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.34/moment-timezone-with-data-10-year-range.js"></script>
If my browser is in the Europe/Berlin timezone the output is correct:
2022-04-11T22:00:00Z
2022-04-12T00:00:00+02:00
2022-04-12T00:00:00+02:00
But if I change my timezone (for my example I took Pacific/Niue), then the result is totally wrong, I suppose moment is doing something with the timezone of the browser but how to avoid this ? Here is the output:
2022-04-11T09:00:00Z
2022-04-11T11:00:00+02:00
2022-04-11T11:00:00+02:00
I need to have the date in the timezone of the server and not in the timezone of the browser
With another timezone: Pacific/Kiritimati (-840)
2022-04-12T10:00:00Z // Wanted 2022-04-11T22:00:00Z (UTC Date as entered)
2022-04-12T12:00:00+02:00 // Wanted 2022-04-12T00:00:00Z (Converted in Europe/Berlin)
2022-04-12T12:00:00+02:00 // Wanted 2022-04-12T00:00:00Z (Converted in Europe/Berlin)
2022-04-12T12:00:00+02:00 // Wanted 2022-04-12T00:00:00Z (Converted in Europe/Berlin)
Again all the dates are wrong, moment seems not able to parse my date as an UTC date ? It apply the timezone offset of the browser even if I'm using the utc method
moment.utc('2022-04-11T22:00:00.000Z').tz('Europe/Berlin').format()
please check this document. https://momentjs.com/timezone/docs/#/using-timezones/
below is my code result, whatever timezone you changed, the result is '2022-04-12T00:00:00+02:00'

angular $http.post changing date to UTC date

I was trying to post some data to my REST api which has date.
Now while I debug, my date parameter is a JS Date object with correct date in my timezone: Tue Apr 04 2017 00:00:00 GMT+0530
after it leaves my code, and I see the same in network tab, it is converted to UTC date: "2017-04-03T18:30:00.000Z"
I searched for the solution according to which I need to include locale file of angular in my index.html which I did:
<script type="text/javascript" src="resources/js/angular/angular-locale_en-in.js"></script>
but it doesn't help.
I've seen solutions like adding date format to filter or something, but I want a global solution.
Any help?
Thanks :)
Handling date, time, and timezone have confused me too. May be this answer gives you some insight on how you can handle them.
Try the following code in Chrome's developer console and see how same date is presented in different formats:
var date = new Date();
date.toISOString(); // "2017-04-29T09:54:28.714Z"
date.toGMTString(); //"Sat, 29 Apr 2017 09:54:28 GMT"
date.toLocalString(); //"4/29/2017, 3:24:28 PM"
Any date that you create on client always records the date at zero timezone offset i.e. UTC+/-00:00 Z. For simplicity you may think UTC and GMT as same. When it comes to display purpose the same date is presented as per the browser's timezone. If you do console.log (date) it'll output Sat Apr 29 2017 15:24:28 GMT+0530 (IST) but that doesn't mean that the internal recording of the date is as per browser's timezone. It's just presented on screen/console as per browser's timezone.
Look at date representations not as being converted from one timezone to another but look at them as different representation of the same date. In your browser it is represented as GMT+0530 offset and when it is sent to server it is the same date at zero timezone offset.
As per your comment, if you choose 4th Apr at 00:00 AM in GMT+0530 timezone, internally it'll be 3rd Apr at 18:30 PM in at GMT+0 i.e. zero timezone offset. Let it go to server as it is. When you need to use this date, it comes back from server as 3rd Apr and it'll be displayed in browser as per the browser's timezone offset. There is no conversion involved, it is one date with different representation.
I once asked a related question, may be this adds more clarification.
And overall, this answer is still same as #geminiousgoel and #charlietfl answers.
Scenario :
Send date from UI into API call as an epoch time (UNIX Time) instead of date string. You can use getTime() method to convert the date into epoch time.
var dateStr = "Tue Apr 04 2017 00:00:00 GMT+0530";
var dateEpoch = new Date(dateStr).getTime();
console.log(dateEpoch); // 1491244200000 (Local Time)
At receiver end, they have to convert this epoch time (UNIX time) into Date again.It will give the same local date\time that pass from the UI.
Sample screenshot
Like charlietfl suggested, probably the global hack would be to override Date.prototype.toJSON() method, but that's not a good practice.
Where are you using your $http.post call? The best place to submit an $http request would be in a service. If you use a service, then I suggest you to enwrap your public service API, so that you could have "public" and "private" methods: these could be utilities to perform common operations, such as data transformations, validations..
angular.service('bookStoreService', ['$http'], function($http) {
var normalizeBooks = function(booksArray){
booksArray.forEach(function(book){
// do something on the book
});
};
var updateBooks = function(books){
normalizeBooks(books);
$http.post('myurl', books);
};
return {
updateBooks : updateBooks
};
});
Passing UTC date to server is desired behavior. The client APIs are supposed to handle UTC time instead of assuming the dates are all local dates.
But anyways, you can convert the date to string based on local time zone, and pass the string to server.
i think you just can pass it as string (if the api you use accept strings) with the format you need, let say "Tue Apr 04 2017 00:00:00 GMT+0530" and save it in back-end as string and then when you retrieve it, it will be string and so it will not be changed in any way.
Jindal saab, It will work like this. When we select any date with date picker or just pass any value it takes the original local date but when we pass that value further it converts it into UTC, thereafter it needs to convert to local zone again at receiving end. Database saves date-time in UTC format.
Did you added the angular-locale_en-in.js library to your app? Something like this....
angular.module('myAngularApp', [
'ngLocale'])
Otherwise, the js library won't have any effect in your angular application.
Append UTC at the end so that Browser converts it into UTC date
var dateToServer =new Date(dateFromUser+" UTC");
now the dateToServer will be UTC DateTime format.
Json serializer parse date from string. On a client the date properties are stored as local date in browser time zone. When you are posting your object to server all date properties converts to utc string. In most cases it is a properly behavor. But sometimes you need set and send date in a server time zone. Often it is need when you should set only date whitout time. In that case you should define string propertie and set it manualy. I usaly apply this trick.
class Obj{
d: Date
}
class ObjDto{
constructor(obj: Obj){
this.d= dateTimeToIsoLocalDateString(obj.d)
}
d: string
}
...
export function DateTimeToDate(date) {
return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
}
export function dateTimeToIsoLocalDateString(dateTime: Date): string {
if (dateTime === null) {
return null;
}
let date = DateTimeToDate(dateTime);
let res = date.toISOString().replace("Z", "");
return res;
}
For more understanding this theme you may learn this topic
//in res data of rest service in x the value is date in y value of y-axis
for (const i in res) {
console.log(i);
const a = {x: new Date(this.mimikatzlog[i].x), y: this.mimikatzlog[i].y};
this.policies.push(a);

moment.js returns different timezones

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>

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