0

I have an AngularJS where I get the date value from the backend service call. Date I receive from back end is a String. E.g. "2017-04-13". When I try to show this on UI, javascript is converting it to local time "2017-04-12 17:00:00 CST" due to this on UI it's shown by a day off. What I'm trying to achieve is to show "2017-04-13 12:00:00 EST" or "2017-04-13 12:00:00 PST" or "2017-04-13 12:00:00 CST" etc. based on the client's timezone. So that the date is not changed and a day off is not shown on UI. How can I achieve this in Javascript. Do Moment.js and moment-timezone.js are required to achieve this?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Koushik Ravulapelli
  • 1,140
  • 11
  • 30

3 Answers3

1

You can try using the timezone offset which gives you the number of minutes offset from UTC of the local timezone.

let myDate = new Date('2017-04-13');
myDate = new Date(myDate.getTime() + (myDate.getTimeZoneOffset() * 60 * 1000));

Alternatively I refactored an old function I'd used before to work with your use case, it may be a little overkill here but it works:

Date.prototype.format = function(format) {
    var result = "";

    format = format.replace("mm", this.getUTCMonth() + 1 < 10 ? "0" + (this.getUTCMonth() + 1) : this.getUTCMonth() + 1);
    format = format.replace("m", this.getUTCMonth() + 1);
    format = format.replace("dd", this.getUTCDate() < 10 ? "0" + this.getUTCDate() : this.getUTCDate());
    format = format.replace("d", this.getUTCDate());
    format = format.replace("yyyy", this.getUTCFullYear());
    format = format.replace("yy", String(this.getUTCFullYear()).substring(String(this.getUTCFullYear()).length - 2));

    format = format.replace("HH", this.getUTCHours() < 10 ? "0" + this.getUTCHours() : this.getUTCHours());
    format = format.replace("H", this.getUTCHours());
    format = format.replace("hh", this.getUTCHours() == 0 ? "12" : this.getUTCHours() < 10 ? "0" + this.getUTCHours() : this.getUTCHours());
    format = format.replace("h", this.getUTCHours() == 0 ? "12" : this.getUTCHours());
    format = format.replace("nn", this.getUTCMinutes() < 10 ? "0" + this.getUTCMinutes() : this.getUTCMinutes());
    format = format.replace("n", this.getUTCMinutes());
    format = format.replace("ss", this.getUTCSeconds() < 10 ? "0" + this.getUTCSeconds() : this.getUTCSeconds());
    format = format.replace("s", this.getUTCSeconds());
    format = format.replace("p", this.getUTCHours() >= 12 ? "PM" : "AM");
    format = format.replace("t", new Date().toString().match(/\(([A-Za-z\s].*)\)/)[1]);

    return format;
};

let myDate = new Date('2017-04-13');
myDate.format('yyyy-mm-dd HH:mm:ss t');
// Output -> 2017-04-13 00:00:00 EDT
Ryan
  • 6,756
  • 13
  • 49
  • 68
1

No, Moment.js is not required. I had the same issue and decided to use $filter to change the format of the date to allow the Javascript date parser to parse it differently:

var correctDate = new Date($filter('date')(backEndDate, 'MMMM d, yyyy'));

So instead of parsing:

new Date('2017-04-13') // Wed Apr 12 2017 19:00:00 GMT-0500 (Central Daylight Time)

You are parsing:

new Date('April 13, 2017');  //Thu Apr 13 2017 00:00:00 GMT-0500 (Central Daylight Time)
Pop-A-Stash
  • 6,572
  • 5
  • 28
  • 54
1

For the reason why the date appears to be incorrect, set Why does Date.parse give incorrect results. That answer also points out why you should not parse strings with the Date constructor or Date.parse.

To reliably parse an ISO 8601 format date as local requires a simple function. The following also validates the values and returns an invalid date if the month or day are out of range. If you want the time to be noon, then set the hours to 12.

function parseISOLocal(s) {
  var b = s.split(/\D/);
  var d = new Date(b[0], --b[1], b[2]);
  return d && d.getMonth() == b[1]? d : new Date(NaN);
}

var d = parseISOLocal('2017-04-13');
d.setHours(12);
console.log(d.toString());
Community
  • 1
  • 1
RobG
  • 142,382
  • 31
  • 172
  • 209