Вставка объекта momentjs в коллекции Meteor

У меня есть простая коллекция Meteor, и я пытаюсь вставить документ, в который есть свойство momentjs. Поэтому я:

docId = Col.insert({m: moment()});

Однако, когда я пытаюсь вернуть этот документ с помощью

doc = Col.findOne({_id: docId})

Я получаю "Недопустимая дата" для doc.m следующим образом:

Object {_id: "wnHzTpHHxMSyMxmu3", m: "Invalid date"}

Кто-нибудь?!

Ответ 1

Я настоятельно рекомендую хранить даты как объекты Date и использовать момент для их форматирования после их получения. Например:

Posts.insert({message: 'hello', createdAt: new Date});

Затем позже, когда вы хотите отобразить дату:

var date = Posts.findOne().createdAt;
moment(date).format('MMMM DD, YYYY');

Ответ 2

Моменты не предназначены для прямой сериализации. Они не переживут кругосветное путешествие в/из JSON. Лучшим подходом было бы сериализовать дату форматирования ISO8601, например, с помощью moment().toISOString() или moment().format(). (toISOString предпочтительнее, но будет хранить в UTC вместо локального + смещения).

Затем вы можете проанализировать эту строку с помощью moment(theString) и делать то, что вы хотите от нее.

Ответ Дэвида также верен. Хотя он будет полагаться на любой механизм по умолчанию Metor для сериализации объектов Date, поскольку Date также не может существовать непосредственно в JSON. Я не знаю особенностей Метеор, но, скорее всего, он либо хранит целую временную метку, либо просто использует Date.toString(). Формат ISO8601 намного лучше подходит для JSON, чем любой из них.

UPDATE

Я просто взглянул на документы для Метеор, которые объясняют, что они используют изобретенный формат под названием "EJSON". (Вы, наверное, знаете это, но это новое для меня.)

В соответствии с эти документы, Date сериализуется как целая временная метка:

{
  "d": {"$date": 1358205756553}
}

Итак - ответ Дэвида на месте (и должен оставаться принятым ответом). Но также, если вы делаете что-то другое, кроме как только получать текущую дату/время, тогда вы можете использовать для этого момент. Вы можете использовать yourMoment.toDate() и передать это так, чтобы Meteor обрабатывал его с типом $date в формате EJSON.

Ответ 3

Если вы хотите иметь объекты момента на find и findOne, сохраните его как дату, затем преобразуйте его при его обнаружении. Например:

Posts = new Mongo.Collection('posts', {
  transform: function (doc) {
    Object.keys(doc).forEach(field => {
      if (doc[field] instanceof Date) {
        doc[field] = moment(doc[field]);
      }
    });
    return doc;
  }
});

Posts.insert({
  title: 'Hello',
  createdAt: new Date()
});