Create moment.js date from milliseconds in local timezone - javascript

A response I'm getting from the server is a 'local' timestamp.
Which would mean my local time expressed as UTC milliseconds, but without the UTC offset.
For example: 1537747200000 is Mon Sep 24 2018 00:00:00 UTC
Mon Sep 24 2018 03:00:00 EEST (my local time), but in my context, this date is actually Mon Sep 24 2018 00:00:00 EEST, so the utc value with my timezone.
I would now like to display this using moment and moment-timezone if needed.
So what I would like to know is how to create a new moment object that takes in "LOCAL milliseconds"? so I'd pass 1537747200000 and my local time zone if needed, and I could display it as Mon Sep 24 2018 00:00:00 EEST
I found that using moment timezone + utcOffset does the trick, but I don't really know if this is a good approach. utc offset docs says this:
Setting the UTC offset by supplying minutes. Note that once you set an offset, it's fixed and won't change on its own (i.e there are no DST rules). If you want an actual time zone -- time in a particular location, like America/Los_Angeles, consider moment-timezone.
Another approach would be to format the moment to ISOString moment(1537747200000).toISOString() and then parse the resulting string, without the timezone information (the 'z'). When parsing a string, you can parse it in another timezone. moment.tz(moment(1537747200000).toISOString().slice(0, -1), tz). But this requires that I parse->format->parse the value, so it's a lot of extra operations.
const [one, two, thr] = ["exp","tr","appr"];
const display = (toAdd, id) => document.getElementById(id).innerHTML += `<br/> ${toAdd}`;
const formatString = "MMM D, YYYY HH:mm z";
const tz = moment.tz.guess();
const millis_24_sep_00_00_utc = moment.utc("24-09-2018", "DD-MM-YYYY", true).valueOf(); //1537747200000
const isoString = moment(millis_24_sep_00_00_utc).toISOString();
//exp
display(tz, one);
display(millis_24_sep_00_00_utc, one);
const ex = moment.tz(millis_24_sep_00_00_utc, tz).utc().format("MMM D, YYYY HH:mm")
display(`${ex} ${moment().tz(tz).zoneAbbr()} <- local tz`, one);
//tr
[
moment(millis_24_sep_00_00_utc).tz(tz),
moment.utc(new Date(millis_24_sep_00_00_utc)).tz(tz),
moment.tz(millis_24_sep_00_00_utc, tz).utc(),
moment.tz(isoString, tz),
]
.forEach(mom => display(mom.format(formatString), two));
//some approaches
[
//setting utcOffset to 0
moment.tz(millis_24_sep_00_00_utc, tz).utcOffset(0),
//iso string to transform millis -> string -> parse the string in another tz
moment.tz(isoString.slice(0, -1), tz),
]
.forEach(mom => display(mom.format(formatString), thr));
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.21/moment-timezone-with-data.js"></script>
<title>Test</title>
</head>
<body>
<div id="exp">EXPECTED</div>
<hr/>
<div id="tr">TRIES</div>
<hr/>
<div id="appr">APPROACHES</div>
</body>
</html>

It's unusual to provide a millisecond time value that has been offset. But if your time values are offset by +3 hours then you can subtract 3 hours worth of milliseconds (1.08e7) and use it as a UTC time value.
E.g. A time value of 1537747200000 typically represents 2018-09-24T00:00:00.000Z. If that time value actually represents 2018-09-24T00:00:00.000+0300, then the equivalent UTC time value is:
1537747200000 - 1.08e7 = 1537736400000;
Working example:
var d = new Date(1537747200000 - 1.08e7);
console.log(`Zulu: ${d.toISOString()}\nLocal: ${d.toString()}`);

Related

Moment TZ - Convert date into another timezone ISO string

I'm trying to convert a date in GMT to PST. The GMT date is 2022-11-16T00:00:00, therefore the PST date should be 2022-11-15T16:00:00.
My code is as follows:
const startDateGMT = moment(startTime).tz(myTimezone, true);
console.log('START DATE GMT IS', startDateGMT, startDateGMT.toISOString());
This outputs 8AM on the 16th, instead of 4PM on the 15th:
START DATE GMT IS Moment<2022-11-16T00:00:00-08:00> 2022-11-16T08:00:00.000Z
What am I doing wrong?
You can use the moment.tz constructor to parse the input time, using the timezone Etc/GMT as the timezone.
You can then call .tz() on the resulting date to convert to Pacific time.
The example below creates the dates and formats them along with the relevant UTC offset.
const gmtTime = '2022-11-16T00:00:00';
const gmtDate = moment.tz(gmtTime, 'Etc/GMT');
const pstDate = moment.tz(gmtTime, 'Etc/GMT').tz('US/Pacific');
console.log('GMT Date:', gmtDate.format('YYYY-MM-DD HH:mm:ssZ'))
console.log('PST Date:', pstDate.format('YYYY-MM-DD HH:mm:ssZ'))
<script src="https://momentjs.com/downloads/moment.js"></script>
<script src="https://momentjs.com/downloads/moment-timezone-with-data.js"></script>

Momentjs showing same date for all timezones

I am trying to convert the DateTime by the user's browser using momentjs.
What is happening here:
let timezone = moment.tz.guess();
console.log('timezone:', timezone);
let iso_date = moment('06-04-2020 12:22:05 PM', 'MM-D-YYYY hh:mm:ss A').toISOString();
console.log('iso_date:', iso_date)
console.log('from timezone:', moment(iso_date).tz(timezone).format('lll'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://momentjs.com/downloads/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.31/moment-timezone-with-data.min.js"></script>
I would like to convert the datetime as per user's browser. But no matter what I try, I am getting the same datetime without the change. How do I get different datestimes for different timezones?
Inputted date: 06-04-2020 12:22:05 PM', 'MM-D-YYYY hh:mm:ss A
Inputted timezone: America/Los_Angeles
Expected Output: Jun 4, 2020 12:22 PM
Inputted date: 06-04-2020 12:22:05 PM', 'MM-D-YYYY hh:mm:ss A
Inputted timezone: Asia/Calcutta
Expected Output: Jun 5, 2020 12:52 AM
Here is what is going on.
let iso_date = moment('06-04-2020 12:22:05 PM', 'MM-D-YYYY hh:mm:ss A').toISOString();
Creates a date from '06-04-2020 12:22:05 PM', treating the values as local, then returns an ISO 8601 string for the UTC version of that date, e.g. 2020-06-04T06:52:05Z.
console.log('from var:', moment(iso_date).tz(timezone).format('lll'));
Takes the ISO formatted string and parses it as UTC, then creates a timestamp for the local timezone. So it should produce the same date and time as the original timestamp.
All the code does is parse a timestamp as local, generate an equivalent UTC timestamp, then reverse the process by converting the UTC timestamp to a local timestamp.
How do I get different datestimes for different timezones?
Use a different location for parsing and formatting. If you use the same location for both, or locations with the same offset, then you'll get the same date and time back. It's exactly the same as doing:
let s = 'Fri Jun 05 2020 10:41:25';
let d = new Date(s);
let utc = d.toISOString();
console.log(
'Started with : ' + s +
'\nConverted to : ' + utc +
'\nBack to local: ' + new Date(utc).toString()
);

Unable to get the first day of the Month in Angular 2/4

I'm calculating the dates for my application like date,week,month.
First I am defining day,week,month,custom like:
this.reportTypes = [{TypeId: 1, Type: 'Day'}, {TypeId: 6, Type: 'Week'}, {TypeId: 30, Type: 'Month'}, {
TypeId: 10,
Type: 'Custom'
}]
Next I'm defining dates like:
var currdate = new Date();
if(reportType==1){
// this.reportDataFromDate=currdate;
// this.reportDataToDate=currdate;
//This is for setting the current date
this.reportDataFromDate= currdate;
this.reportDataToDate= currdate;
}
else if(reportType==30){
var First = new Date(currdate.getFullYear(),currdate.getMonth(),1);
this.reportDataFromDate=First;
this.reportDataToDate=currdate;
}
else if(reportType!=10){
var last = new Date(currdate.getTime() - (reportType * 24 * 60 * 60 * 1000));
this.reportDataFromDate=last;
this.reportDataToDate=currdate;
}
}
The problem is after selecting reportType == 30 then it has to get the first day of the month.
It is showing the date as 1-Dec-2017 but it is getting the data of till 30th November 2017?
This is screenshot of the SQL server. I'm sending the date as 1st Dec 2017 but it is getting 30-11-2017.
When the Date() constructor is invoked with integers, the result is a date object with that date assumed your systems (read browser/os) timezone.
Example:
let d = new Date(2017);
// returns Thu Jan 01 1970 01:00:02 GMT+0100 (W. Europe Standard Time)
// and with d.toUTCString(): Fri, 30 Dec 2016 23:00:00 GMT
Which may end up in an entire different year when sending to the server
Using the string constructor and specifying timezone will help you overcome this.
Example:
let d = new Date('2017z');
// returns Sun Jan 01 2017 01:00:00 GMT+0100 (W. Europe Standard Time)
// and with d.toUTCString(): Sun, 01 Jan 2017 00:00:00 GMT
The latter which is what you should pass to a server, and normally do calculations on.
However, note that calculations with dates are a complicated matter best left to a library like moment.js. To get a feel of what you are dealing with have a look at this great talk from the WebRebel conference.
So to actually give an answer to your title, try this example which creates the date in a simple string using UTC:
let d = new Date(currdate.getUTCFullYear() + ' ' +(currdate.getUTCMonth() + 1) + ' 1z');
d.getUTCDay(); // returns the day as an integer where Monday is 0.
Note that we add 1 month due to getUTCMonth() returns January as 0.
Why the difference?
The new Date(x,y,z) constructor treats the parameters as local date values.
See MDB Web Docs - 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.
But, under the hood the date is stored as UTC (milliseconds since 1 Jan 1970).
const date = new Date(2017, 11, 29);
console.log('valueOf()', date.valueOf()) // 1514458800000
and the UTC date is different to your local date (see trailing 'Z' indicates UTC)
const date = new Date(2017, 11, 29);
console.log('date', date) // "2017-12-28T11:00:00.000Z" (trailing 'Z' means UTC)
// The difference in minutes between browser local and UTC
console.log('getTimezoneOffset()', date.getTimezoneOffset() )
and when you send it to the server, JSON sends it as UTC
const date = new Date(2017, 11, 29);
console.log('JSON', date.toJSON())
// JSON will yield string version of UTC === 2017-12-28T11:00:00.000Z
How to fix it
Well, you might decide that you actually want the date/time in local, and conclude it's not broken.
But if you want to send UTC to the server, wrap the parameters in Date.UTC()
const date = new Date(Date.UTC( 2017, 11, 29 ))
console.log('date.toJSON()', date.toJSON() ) // 2017-12-29T00:00:00.000Z
What about month parameter === 11?
From the MDB page referenced above,
Note: The argument month is 0-based. This means that January = 0 and December = 11.
If you are using .Net Web API as backend, you can config the timezone in Web API WebApiconfig.cs like below. It will serialize the time in UTC.
public static void Register(HttpConfiguration config)
{
config.Formatters.JsonFormatter.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
}
Or use
config.Formatters.JsonFormatter.SerializerSettings.DateTimeZ‌​oneHandling = Newtonsoft.Json.DateTimeZoneHandling.RoundtripKind; //Time zone information should be preserved when converting.

UTC date convert to local timezone

I have a date in UTC format.
"2016-10-12 05:03:51"
I made a function to convert UTC date to my local time.
function FormatDate(date)
{
var arr = date.split(/[- :T]/), // from your example var date = "2012-11-14T06:57:36+0000";
date = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4], 00);
var newDate = new Date(date.getTime()+date.getTimezoneOffset()*60*1000);
var offset = date.getTimezoneOffset() / 60;
var hours = date.getHours();
newDate.setHours(hours - offset);
return newDate;
}
My Local timezone is GMT +0530.
My code produced this output:
Tue Oct 11 2016 10:33:00 GMT+0530 (IST)
I converted the date with an online tool to get the correct date and time.
Wednesday, October 12, 2016 10:30 AM
My code matches the online tool on time but not on date.
How can I correct my code's output, preferably using moment.js?
UTC is a standard, not a format. I assume you mean your strings use a zero offset, i.e. "2016-10-12 05:03:51" is "2016-10-12 05:03:51+0000"
You are on the right track when parsing the string, but you can use UTC methods to to stop the host from adjusting the values for the system offset when creating the date.
function parseDateUTC(s){
var arr = s.split(/\D/);
return new Date(Date.UTC(arr[0], arr[1]-1, arr[2], arr[3], arr[4], arr[5]));
}
console.log(parseDateUTC('2016-10-12 05:03:51').toLocaleString());
If you want to use moment.js, you can do something like the following. It forces moment to use UTC when parsing the string, then local to write it to output:
var d = moment.utc('2016-10-12 05:03:51','YYYY-MM-DD HH:mm:ss');
console.log(d.local().format());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.0/moment.js"></script>
Since you have tagged moment, I'm assuming you are using moment.
In such cases, you should keep your approach consistent and not mix moment and date object.
var dateStr = '2016-10-12 05:03:51';
var timeZone = "+0530";
var date = moment.utc(dateStr).utcOffset(dateStr + timeZone)
console.log(date.toString())

JSON.stringify(objExtraParam) giving wrong date

I'm having a javascript object as below.
var obj = { pageSize:"25",asOfDate:"Thu Sep 25 00:00:00 UTC+0530 2014"};
when i stringify it,
var d = JSON.stringify(obj);
its giving me result as
{"pageSize":"25","asOfDate":"2014-09-24T18:30:00Z"}
what could be the reason that its giving date 2014-09-24 than 2014-09-25 ?
EDIT:
My deployment server is located in US (Eastern Time UTC -5:00).when i check the site from my local machine in india its giving me date as 24 Sept 2014
UTC+0530 declares a UTC time offset. Seems that 5:30 is around the India or Sri Lanka area.
"2014-09-24T18:30:00Z" is the same as "Thu Sep 25 00:00:00 UTC+0530 2014" in two different formats. The Z in the first format is resolving to UTC (GMT) time, which in this case is -5:30. So 18:30 is 24:00 - 5:30.
So, if you are stringify-ing in a timezone that is negative offset (say in the United States UTC−08:00) then it could push the date back by one day when parsing.
I think this is what you are seeing.
Related SO Question: JSON Stringify changes time of date because of UTC
Try this
var obj = { pageSize:"25",asOfDate:"Thu Sep 25 00:00:00 UTC+0530 2014"};
obj.asOfDate = reverseUTC(obj.asOfDate);
var d = JSON.stringify(obj);
function reverseUTC(updatedDate) {
if ($.isEmptyObject(updatedDate)) {
var offset = updatedDate.getTimezoneOffset();
var currentDateTime = new Date();
updatedDate.setHours((currentDateTime.getHours() * 60 + currentDateTime.getMinutes() - offset) / 60);
updatedDate.setMinutes((currentDateTime.getHours() * 60 + currentDateTime.getMinutes() - offset) % 60);
return updatedDate;
}
}
There is no standard format for passing dates in JSON, so JSON.stringify is just calling the default date.prototype.toString() method and that is taking the timezone into account.
You need to ensure that the date is converted into a string to your particular requirements and only convert to JSON format.

Categories

Resources