Добавьте длительность ко времени начала повторяющегося события, чтобы его конец всегда был одинаковым (т.е. с 14:00 до 16:00). - PullRequest
1 голос
/ 16 июня 2019

У меня есть набор правил (реализован в rrule.js ), который дает мне массив времени начала события (см. Демоверсию 1004 *).rrule.js на самом деле не обеспечивает концепцию продолжительности события или endtime ... Таким образом, он может сообщить мне точную дату, когда начнется миллионное повторение повторяющегося события, но не когда это произойдет.конец.Оказывается, я действительно хочу знать, когда мероприятие заканчивается, поэтому мне придется проявить творческий подход.Насколько я вижу, у меня есть два варианта

  1. DB SIDE: сохранить строку правила + событие duration.

    CLIENT SIDE: восстановить начало событиймассив дат из строки правила.Будет известен только start times, а end times будет рассчитываться путем добавления продолжительности как смещения к каждому времени начала в массиве.

  2. СТОРОНА БД: Хранить измененную строку правила, которая кодирует endtime.

    СТОРОНА КЛИЕНТА: Специальная функция-оболочка считывает измененную строку правила и восстанавливает ее как двемассивы дат;один представляет время начала события, а другой - время окончания.

Вариант 1 кажется более простым, но я подозреваю, что у него возникнут проблемы с переходом на летнее время.Например, скажем, у меня мероприятие, которое проводится каждый вторник с 18:00 до 02:00 по средам.В этом случае я бы сохранял в своей базе данных продолжительность 8 часов вместе с этим строгим правилом.Теперь давайте перенесемся в любой 6 вечера вторника в будущем.Всегда ли мое мероприятие заканчивается в среду в 2 часа ночи (или из-за этой продолжительности 8 часов мое мероприятие заканчивается в 1 или 3 часа ночи)? Как сделать так, чтобы оно всегда заканчивалось в 2 часа ночи?

... Если вы знаете ответ, просто перестаньте читать здесь.

Как я видел, как другие справляютсясмещение длительности

Согласно Кипу в Как добавить 30 минут к объекту JavaScript Date? smart способ смещения даты и времени состоит в использовании такой необычной библиотеки, какmoment.js.

Он подчеркивает этот момент, показывая, как легко все идет не так, используя необычные библиотеки времени и даты (показывая, как функция смещения наивной минуты не работает из-за перехода на летнее время)

function addMinutes(date, minutes) {
    return new Date(date.getTime() + minutes*60000);
}
addMinutes(new Date('2014-11-02'), 60*24) //In USA, prints 11pm on Nov 2, not 12am Nov 3!

Но что-то странное происходит со мной.Предполагалось, что вышеприведенная функция выдает 11pm on Nov 2 - это неправильный ответ, т. Е. Она должна была потерпеть неудачу из-за перехода на летнее время.Когда я запускаю его, он на самом деле выводит правильное время 12am on Nov 3 (примечание: я нахожусь в Чикаго / Центральное время).

Когда я сравниваю вывод его наивной функции с выводом moment.js иluxon.js, я получаю тот же ответ, который вы видите в этом наблюдаемом блокноте .

Почесываете голову

Более того, если вы используете Luxon или момент, когда выдобавьте количество дней в минутах к 2014-11-02, вы получите 2014-11-03T00:00:00.000Z, но если вы просто добавите день к 2014-11-02, вы получите 2014-11-03T01:00:00.000Z - это час отдыха.

Так что мне лучше продолжитьвариант 2?

Ответы [ 2 ]

1 голос
/ 26 июня 2019

Я написал оригинальный ответ, на который вы ссылаетесь около десяти лет назад.Семь лет спустя я сделал правку, изменив new Date(2014, 10, 2) на new Date('2014-11-02').Я думал, что это будет легче читать (потому что вам не нужно объяснять, что месяцы в этой версии конструктора начинаются с 0 вместо 1).Но , как указал @RobG , форматирование таким образом вызывает его синтаксический анализ как UTC.Я вернулся и исправил это сейчас (спасибо, что указал на это).

Чтобы перейти к вашей "чесать голову" часть вашего вопроса:

Что еще, еслииспользуя luxon или момент, когда вы добавляете количество дней в минутах к 2014-11-02, вы получаете 2014-11-03T00:00:00.000Z

Z в конце этой отметки времени означает, что оно в UTC, а UTC делаетне соблюдайте летнее время.Поэтому, если вы начнете с 2014-11-02T00:00:00.000Z и добавите 24 часа, вы получите 2014-11-03T00:00:00.000Z.Когда вы добавляете часы / минуты / секунды, вам не нужно беспокоиться о переходе на летнее время.

, но если вы просто добавите день непосредственно к 2014-11-02, вы получите 2014-11-03T01:00:00.000Z - это на час.

В этом случае происходит то, что вы начинаете с 2014-11-02T00:00:00.000Z, но когда вы говорите библиотеке добавить один день, и вы не указываете часовой пояс, библиотека предполагаетВы находитесь в вашем местном часовом поясе, поэтому он добавляет один местный день.Поскольку вы пересекаете границу летнего времени, этот день длится 25 часов, а когда вы печатаете его как метку времени ISO в UTC, в итоге вы получите 2014-11-03T01:00:00.000Z (25 часов спустя).

Временной пояс сложен, даже если вы используете библиотеку.Большинство людей могут долго обходиться, не зная или не заботясь о том, что для многих пользователей один день в году длится 25 часов.Но если эти крайние случаи будут иметь для вас значение, лучше всего поиграть с ними, как вы, и убедиться, что вы действительно понимаете, что происходит и почему.

1 голос
/ 16 июня 2019

Теперь давайте перенесемся в любой вторник в 18:00.Всегда ли мое мероприятие заканчивается в среду в 2 часа ночи (или из-за этой продолжительности 8 часов мое мероприятие заканчивается в 1 или 3 часа ночи)?Как мне заставить его всегда заканчиваться в 2 часа ночи ?

Стандартный объект Javascript Date автоматически обрабатывает переход на летнее время для вас.Даже если вы добавите 8 часов к дате в 18:00 дня, предшествующего переходу на летнее время, новая дата закончится в 2:00 следующего дня.

Кстати, я включил поддержку продолжительности в rSchedule ипоскольку он поддерживает как стандартные javascript Date, так и moment / luxon даты, вы можете протестировать повторяющееся событие с продолжительностью, используя любую библиотеку, и увидеть, что они оба дают одинаковый результат.

Этот пример может быть замечен на стеке .

import { Schedule } from '@rschedule/rschedule';
import { StandardDateAdapter } from '@rschedule/standard-date-adapter';

// This example will also work with `moment`, `moment-timezone`, and `luxon`
// (assuming you import the proper date adapter -- see rSchedule docs)

const schedule = new Schedule({
  rrules: [
    {
      start: new Date(2019,9,10,18),
      frequency: "DAILY",
      duration: 1000 * 60 * 60 * 8,
      count: 30
    }
  ],
  dateAdapter: StandardDateAdapter,
});

schedule.occurrences().toArray().forEach(adapter => {
  console.log(
      {
        start: adapter.date.toLocaleString(),
        end: adapter.end.toLocaleString(),
      }
    )
})

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

Чтобы узнать когдаэто событие заканчивается, вы можете сделать:

const iterator = schedule.occurrences({ reverse: true })

const { end } = iterator.next().value

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...