Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Json Stringify date produces a wrong date compared to javascript date

When i create a javascript date and then stringify it and send it to the server, i get two different dates. The stringified date is always one day behind.

So currently i increment my javascript date by 1 day so that i receive the same date on the server.

my current code:

var dt = $(.datepicker).datepicker('getDate');//Fri Aug 26 2016 00:00:00 GMT+0200 (South Africa Standard Time)
var result = Json.stringify(dt); //"2016-08-25T22:00:00.000Z"

Is this the correct approach or am i missing something?

like image 868
JustLearning Avatar asked Aug 26 '16 09:08

JustLearning


2 Answers

This is due to the timezone component in the Date. The work around I did was:

var date = $(.datepicker).datepicker('getDate');
var utcDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes()))
var result = Json.stringify(utcDate);

The removes the timezone component.

like image 55
Arun Ghosh Avatar answered Oct 17 '22 08:10

Arun Ghosh


You don't seem to understand that both of your datetimes are actually the same and are correct. You haven't explained why you think that you need to manually alter the one sent to the server. Here is an example that demonstrates that they are in fact the same, just displayed in different formats in different timezones.

// Values from the local datetime string
var local = {
  year: 2016,
  month: 7,
  day: 26,
  hours: 0,
  minutes: 0,
  seconds: 0,
  milliseconds: 0
};

// Values from the UTC ISO 8601 datetime string
var utc = {
  year: 2016,
  month: 7,
  day: 25,
  hours: 22,
  minutes: 0,
  seconds: 0,
  milliseconds: 0
};

// Create Date object as local
var date1 = new Date(
  local.year,
  local.month,
  local.day,
  local.hours,
  local.minutes,
  local.seconds,
  local.milliseconds
);

// Create Date object as local from UTC
var date2 = new Date(Date.UTC(
  utc.year,
  utc.month,
  utc.day,
  utc.hours,
  utc.minutes,
  utc.seconds,
  utc.milliseconds
));

var pre = document.getElementById('out');
// Display Date1 as local
pre.appendChild(document.createTextNode(date1.toString() + '\n'));
// Display Date2 as local
pre.appendChild(document.createTextNode(date2.toString() + '\n'));
// Display Date2 as UTC
pre.appendChild(document.createTextNode(date2.toUTCString() + '\n'));
// Test if Date1 and Date2 display the same datetime
pre.appendChild(document.createTextNode(
  'Date1 === Date2: ' + (date1.getTime() === date2.getTime())
));
<pre id="out"></pre>

JSON converts Date objects to ISO 8601 (by specification), but let's see what happens if you use the solution that you chose.

// Values from the local datetime string
var local = {
  year: 2016,
  month: 7,
  day: 26,
  hours: 0,
  minutes: 0,
  seconds: 0,
  milliseconds: 0
};

// Create Date object as local
var date = new Date(
  local.year,
  local.month,
  local.day,
  local.hours,
  local.minutes,
  local.seconds,
  local.milliseconds
);

// Your solution
var utcDate = new Date(Date.UTC(
  date.getFullYear(),
  date.getMonth(),
  date.getDate(),
  date.getHours(),
  date.getMinutes()));

var pre = document.getElementById('out');
// Display Date as local format
pre.appendChild(document.createTextNode(date.toString() + '\n'));
// Display utcDate as local format
pre.appendChild(document.createTextNode(utcDate.toString() + '\n'));
// Test if Date and utcDate display the same datetime
pre.appendChild(document.createTextNode(
  'Date1 === Date2: ' + (date.getTime() === utcDate.getTime())
));
<pre id="out"></pre>

You end up with 2 dates that are no longer the same. Don't like ISO 8601 for transmission and storage of datetimes? Well the alternative would be to use the number of milliseconds UTC since the epoch (getTime). You can't make JSON do this conversion instead of ISO 8601, not even using a replacer function. So any conversion would be necessary before using JSON.stringify. So you really need to explain what it is you are trying to achieve and why you think what you have now is incorrect.

like image 20
Xotic750 Avatar answered Oct 17 '22 06:10

Xotic750