1

I have code below:

var startTime = moment("2020-09-08 16:00:00").toDate();
console.log(startTime) 

const data = {start: startTime}
console.log(JSON.stringify(data)

when I run .It has result:

Tue Sep 08 2020 16:00:00 GMT+0700 (Indochina Time)
{"start":"2020-09-08T09:00:00.000Z"}

I don't know why result show different timezone? Anyone help me explain and fix it ?

Thanks !

Java Dev Beginner
  • 349
  • 1
  • 5
  • 14
  • "2020-09-08 16:00:00" has no associated timezone so it's treated as local, hence "Tue Sep 08 2020 16:00:00 GMT+0700", which infers that your system is set to Indochina Time and is UTC+7. The timestamp for *start* is the UTC equivalent (i.e.UTC+0, so the time is 7 hours earlier), which is the default for [stringified dates in JSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Description). – RobG Sep 08 '20 at 13:34

1 Answers1

1

By default, JSON.stringify will convert Dates to a timestamp as if toISOString was called on the date.

If you want dates in some other format, you can use a replacer function that tests for a value that is a timestamp in the same format as that produced by JSON.stringify (i.e. YYYY-MM-DDTHH:mm:ss.sssZ) and instead stringify it to some other format, e.g. using Date.prototype.toString.

Note that you have to test for a formatted string as the value will be stringified before being passed to the replacer function.

// Test if value is a string in the same format as that produced
// by toISOString
function isTimestamp(value) {
  return /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ$/.test(value);
}

// Replace timestamps in toISOString format with 
// timestamps in toString format
function replacer (key, value) {
  console.log(Object.prototype.toString.call(this[key]));
  if (isTimestamp(value)) {
    return this[key].toString();
  } else {
    return value;
  }
}

// Sample date
let startTime = new Date(2020,8,8,16);
// Sample object
let data = {start: startTime};
// Stringify date using toString
console.log(JSON.stringify(data, replacer))

Alternatively, you can test the value of this[key] within the the replacer and not use the isTimestamp function, e.g.:

if (Object.prototype.toString.call(this[key]) == '[object Date]') {
  // return custom format
}

Using moment.js you might do:

// Replace timestamps in toISOString format with 
// timestamps in some other format
function replacer(key, value) {
  // Strict parse of value
  let d = moment(value, 'YYYY-MM-DDTHH:mm:ss.sssZ', true);
  // If it's a valid Date
  if (d.isValid()) {
    // Return whatever format you like
    return moment(this[key]).format('YYYY-MM-DD HH:mm ZZ');
  } else {
    // Otherwise just return the default value
    return value;
  }
}

// Sample date
let startTime = new Date(2020, 8, 8, 16);
// Sample object
let data = {start: startTime};
// Stringify date using toString
console.log(JSON.stringify(data, replacer))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
RobG
  • 142,382
  • 31
  • 172
  • 209