Получить первый день этого месяца из массива объектов

Если сегодня 2018-11-28, у меня есть массив таких объектов:

  const dataset = [
  {
    "timestamp": "2018-11-28T16:38:07.610Z",
    "value": 751.998557581834
  },
  {
    "timestamp": "2018-11-27T16:38:07.610Z",
    "value": 644.9987628195244
  },
  {
    "timestamp": "2018-11-26T16:38:07.610Z",
    "value": 766.9985288101943
  },
  {
    "timestamp": "2018-11-25T16:38:07.610Z",
    "value": 953.9981701237627
  },
  {
    "timestamp": "2018-11-24T16:38:07.610Z",
    "value": 912.9982487662423
  },
  {
    "timestamp": "2018-11-23T16:38:07.610Z",
    "value": 402
  },
  {
    "timestamp": "2018-11-22T16:38:07.610Z",
    "value": 914.9982449300243
  },
  {
    "timestamp": "2018-11-21T16:38:07.610Z",
    "value": 769.9985230558668
  },
  {
    "timestamp": "2018-11-20T16:38:07.610Z",
    "value": 772.9985173015398
  },
  {
    "timestamp": "2018-11-19T16:38:07.610Z",
    "value": 176
  },
  {
    "timestamp": "2018-11-18T16:38:07.610Z",
    "value": 978.9981221710306
  },
  {
    "timestamp": "2018-11-17T16:38:07.611Z",
    "value": 342
  },
  {
    "timestamp": "2018-11-16T16:38:07.611Z",
    "value": 498.9990428634777
  },
  {
    "timestamp": "2018-11-15T16:38:07.611Z",
    "value": 326
  },
  {
    "timestamp": "2018-11-14T16:38:07.612Z",
    "value": 649.9987532289786
  },
  {
    "timestamp": "2018-11-13T16:38:07.612Z",
    "value": 70
  },
  {
    "timestamp": "2018-11-12T16:38:07.612Z",
    "value": 349
  },
  {
    "timestamp": "2018-11-11T16:38:07.612Z",
    "value": 191
  },
  {
    "timestamp": "2018-11-10T16:38:07.612Z",
    "value": 154
  },
  {
    "timestamp": "2018-11-09T16:38:07.613Z",
    "value": 109
  },
  {
    "timestamp": "2018-11-08T16:38:07.613Z",
    "value": 237
  },
  {
    "timestamp": "2018-11-07T16:38:07.613Z",
    "value": 398
  },
  {
    "timestamp": "2018-11-06T16:38:07.613Z",
    "value": 606.9988357076774
  },
  {
    "timestamp": "2018-11-05T16:38:07.614Z",
    "value": 131
  },
  {
    "timestamp": "2018-11-04T16:38:07.614Z",
    "value": 397
  },
  {
    "timestamp": "2018-11-03T16:38:07.614Z",
    "value": 583.9988798241893
  },
  {
    "timestamp": "2018-11-02T16:38:07.614Z",
    "value": 362
  },
  {
    "timestamp": "2018-11-01T16:38:07.614Z",
    "value": 686.998682258936
  },
  {
    "timestamp": "2018-10-31T16:38:07.614Z",
    "value": 131
  },
  {
    "timestamp": "2018-10-30T16:38:07.614Z",
    "value": 212
  }
]

Объекты создаются с использованием этого кода:

  import { DateTime } from 'luxon'

  const timestamp = startDate.minus({ days: i }).toJSDate()
  return { timestamp: timestamp, value: randomValue }

Я хочу, чтобы объект содержал первый день этого месяца, поэтому в этом примере я хочу:

  {
    "timestamp": "2018-11-01T16:38:07.614Z",
    "value": 686.998682258936
  }

Вот что я попробовал:

const date = new Date()
const firstDayOfThisMonth = new Date(date.getFullYear(), date.getMonth(), 1)
const firstDayOfThisMonthSub = firstDayOfThisMonth.toString().substring(0, 15)
const bo = dataset.map((d, i) => {
  const sub = d.toString().substring(0, 15)
  if (sub === firstDayOfThisMonthSub) return d
})

Это не работает (я получаю массив undefined) и я надеюсь, что есть более разумный способ сделать это. Я могу использовать Javascript Date объект или библиотека Luxon.

Спасибо

3 ответа

Решение

С люксоном:

const firstDayOfThisMonth = DateTime.local().startOf('month')
const firstDayRecord = dataset.find(record => {
 return DateTime.fromISO(record.timestamp).hasSame(firstDayOfThisMonth, 'day')
})

Это должно сделать свое дело

У вас есть метки времени UTC, но мне не ясно, хотите ли вы указать местный первый день месяца или первый день месяца UTC. Если вы хотите использовать UTC, получение первого дня месяца в качестве даты ISO 8601 можно упростить до:

let date = new Date().toISOString().slice(0,8) + '01';

Отмечая, что месяц UTC будет отличаться от местного месяца для периода смещения часового пояса хоста в начале или конце месяца, в зависимости от того, находится ли он к востоку или западу от Гринвича соответственно. Затем вы можете использовать фильтр, чтобы получить соответствующие элементы, например

var data = 
  [{"timestamp": "2018-11-02T16:38:07.614Z","value": 362},
   {"timestamp": "2018-11-01T16:38:07.614Z","value": 686.998},
   {"timestamp": "2018-10-31T16:38:07.614Z","value": 131},
   {"timestamp": "2018-10-30T16:38:07.614Z","value": 212}];
   
var s = new Date().toISOString().slice(0,8) + '01';
var d = data.filter(o => o.timestamp.slice(0,10) == s);
console.log(d);

Однако, если вы хотите найти временную метку для местного первого дня месяца, вам следует преобразовать временные метки в даты и сравнить с началом и концом местного первого дня месяца, например

var data = 
  [{"timestamp": "2018-11-02T16:38:07.614Z","value": 362},
   {"timestamp": "2018-11-01T16:38:07.614Z","value": 686.998},
   {"timestamp": "2018-10-31T16:38:07.614Z","value": 131},
   {"timestamp": "2018-10-30T16:38:07.614Z","value": 212}];
    
var d = new Date();
d.setDate(1);
let firstOfMonthStart = d.setHours(0,0,0,0);
let firstOfMonthEnd   = d.setHours(23,59,59,999);
let t = data.filter(o => {
  let d = new Date(o.timestamp);
  return d >= firstOfMonthStart && d <= firstOfMonthEnd;
});
console.log(t);

Обратите внимание, что firstOfMonthStart и firstOfMonthEnd будут значениями времени, а не датами, но сравнение работает, потому что < а также > приведите значения к числу, чтобы сравнение работало точно так же, как если бы они были датами.

Для кого-то, чей местный часовой пояс, скажем, +10:00, возвращенный массив в ноябре 2018 года:

[{timestamp: "2018-10-31T16:38:07.614Z", value: 131}]

так как их местное начало месяца 2018-10-31T14:00:00Z.

map() не правильный инструмент. Это даст вам значение для каждого элемента в исходном массиве, даже если это undefined, Чтобы получить подмножество массива, используйте filter(),

Так как это хорошие строки даты ISO 8601. Вы можете создать строку даты, например "2018-11-01", и фильтровать ее по тому, с чего начинается дата:

let a = [  {"timestamp": "2018-11-28T16:38:07.610Z","value": 751.998557581834},{"timestamp": "2018-11-27T16:38:07.610Z","value": 644.9987628195244},{"timestamp": "2018-11-26T16:38:07.610Z","value": 766.9985288101943},{"timestamp": "2018-11-25T16:38:07.610Z","value": 953.9981701237627},{"timestamp": "2018-11-24T16:38:07.610Z","value": 912.9982487662423},{"timestamp": "2018-11-23T16:38:07.610Z","value": 402},{"timestamp": "2018-11-22T16:38:07.610Z","value": 914.9982449300243},{"timestamp": "2018-11-21T16:38:07.610Z","value": 769.9985230558668},{"timestamp": "2018-11-20T16:38:07.610Z","value": 772.9985173015398},{"timestamp": "2018-11-19T16:38:07.610Z","value": 176},{"timestamp": "2018-11-18T16:38:07.610Z","value": 978.9981221710306},{"timestamp": "2018-11-17T16:38:07.611Z","value": 342},{"timestamp": "2018-11-16T16:38:07.611Z","value": 498.9990428634777},{"timestamp": "2018-11-15T16:38:07.611Z","value": 326},{"timestamp": "2018-11-14T16:38:07.612Z","value": 649.9987532289786},{"timestamp": "2018-11-13T16:38:07.612Z","value": 70},{"timestamp": "2018-11-12T16:38:07.612Z","value": 349},{"timestamp": "2018-11-11T16:38:07.612Z","value": 191},{"timestamp": "2018-11-10T16:38:07.612Z","value": 154},{"timestamp": "2018-11-09T16:38:07.613Z","value": 109},{"timestamp": "2018-11-08T16:38:07.613Z","value": 237},{"timestamp": "2018-11-07T16:38:07.613Z","value": 398},{"timestamp": "2018-11-06T16:38:07.613Z","value": 606.9988357076774},{"timestamp": "2018-11-05T16:38:07.614Z","value": 131},{"timestamp": "2018-11-04T16:38:07.614Z","value": 397},{"timestamp": "2018-11-03T16:38:07.614Z","value": 583.9988798241893},{"timestamp": "2018-11-02T16:38:07.614Z","value": 362},{"timestamp": "2018-11-01T16:38:07.614Z","value": 686.998682258936},{"timestamp": "2018-10-31T16:38:07.614Z","value": 131},{"timestamp": "2018-10-30T16:38:07.614Z","value": 212}]

let now =  new Date()
 // start of month is always 01
 // month is zero indexed
let pattern = `${now.getUTCFullYear()}-${now.getUTCMonth()+1}-01`   
let filtered = a.filter(item => item.timestamp.startsWith(pattern))
console.log(filtered)

Другие вопросы по тегам