8

In a Chrome Extension, I'm trying to save a Date object to storage then read it back. According to the official documentation,

Values with a typeof "object" and "function" will typically serialize to {}, with the exception of Array (serializes as expected), Date, and Regex (serialize using their String representation).

I'm saving to storage as:

 var value= new Date(Date.now());
 chrome.storage.sync.set({"testdate":value}, function(){
     console.log("saved testdate to storage:");
     console.log(value);

 });

The output of logging the value is

Tue Oct 16 2018 08:22:11 GMT-0700 (Pacific Daylight Time)

I'm later retrieving from storage as:

chrome.storage.sync.get("testdate", function(items){

        console.log("test date from storage:");
        console.log(items.testdate);
});

In this case, the value of logging items.testdate is:

Object proto: constructor: ƒ Object() hasOwnProperty: ƒ hasOwnProperty() isPrototypeOf: ƒ isPrototypeOf() propertyIsEnumerable: ƒ propertyIsEnumerable() toLocaleString: ƒ toLocaleString() toString: ƒ toString() valueOf: ƒ valueOf() defineGetter: ƒ defineGetter() defineSetter: ƒ defineSetter() lookupGetter: ƒ lookupGetter() lookupSetter: ƒ lookupSetter() get proto: ƒ proto() set proto: ƒ proto()

Can't figure out how to get my Date object back (or the string representation to convert back to a Date)

ted
  • 13,596
  • 9
  • 65
  • 107
Katie
  • 478
  • 2
  • 15
  • Only JSONifiable part of a value is stored. To view it, type `JSON.stringify(value)` and you'll see `{}` because Date isn't JSONifiable. You can store `d.valueOf()` which is a number then recreate the date like `new Date(items.testdate)`. – wOxxOm Oct 16 '18 at 17:41
  • Thanks, that worked in my example. In my "real" code, the date object is contained in a wrapper object (and I call JSON.stringify on the wrapper object), like `JSON.stringify(obj);`. If I'm stringifying the entire wrapper object like that, how do I override the Date object to call valueOf()? I tried `Date.prototype.toJSON = function(){ return this.valueOf(); }` but that doesn't seem to have an effect. – Katie Oct 16 '18 at 21:24
  • I don't know but I would make a wrapper for the storage set and get, that makes the necessary amendments in a deep copy of the object. – wOxxOm Oct 17 '18 at 04:45

2 Answers2

7

Setting side

const currentTime = (new Date()).toJSON();
const items = { 'testdate': currentTime }; 
chrome.storage.local.set(items, () => {
    if (chrome.runtime.lastError) {
        console.error(chrome.runtime.lastError.message);
    }
});

Getting side

chrome.storage.local.get(['testdate'], (result) => {
    if (chrome.runtime.lastError) {
        console.error(chrome.runtime.lastError.message);
    } else {
        const storedJSONDate = result['testdate'];
        const testdate = new Date(storedJSONDate);
        console.log(testdate);
    }
});

Sources

I based my code off of Date.prototype.toJSON which says

var jsonDate = (new Date()).toJSON();
var backToDate = new Date(jsonDate);

console.log(jsonDate); //2015-10-26T07:46:36.611Z

From the Chrome storage official documentation, I think it's saying that Date won't serialize as expected. Because it specifies how Array and Regex serialize to, but not how Date serializes, I think it serializes to {}, which is what I got when I didn't include the toJSON() parts.

An object which gives each key/value pair to update storage with. Any other key/value pairs in storage will not be affected. Primitive values such as numbers will serialize as expected. Values with a typeof "object" and "function" will typically serialize to {}, with the exception of Array (serializes as expected), Date, and Regex (serialize using their String representation).

artist_noodle
  • 71
  • 2
  • 4
  • 1
    Depending on whether you want to handle exceptions, you should consider using `toISOString()`. You may want to handle exceptions where you have no control over incoming date because if you convert back an invalid date that was stored using `toJSON()` you could possibly have dates from 1969 ;) (`new Date(null)`). More info: https://stackoverflow.com/a/16198620/452587 – thdoan May 09 '23 at 23:36
1

Can also use getTime():

//set
const currentTime = (new Date()).getTime();  //equals (new Date()).valueOf()
const items = {'testdate': currentTime};
chrome.storage.local.set(items);

//get
chrome.storage.local.get('testdate', (items) => {
    const time = items['testdate'];
    const testdate = new Date(time);
    console.log(testdate);
});
tdy
  • 36,675
  • 19
  • 86
  • 83
happynow
  • 11
  • 1