Как правильно хранить и отображать рабочее время для разных часовых поясов в javascript? - PullRequest
0 голосов
/ 01 апреля 2019

Поэтому я пытаюсь осуществить бронирование (резервирование) на веб-сайте, который предлагает онлайн-услуги, и я хочу, чтобы даты и время (рабочие дни и часы) для конечного пользователя отображались правильно с учетом часовых поясов, летнего времени ии все эти хитрые вещи.Фактическое местонахождение поставщиков услуг находится в часовом поясе +5, а рабочее время с 8:00 до 17:00.Итак, что я хочу, чтобы фактический пользователь, например, в часовом поясе +4, видел рабочие часы с 7:00 до 16:00.

В настоящее время я использую Angular Material Datepicker для хранения дат и Angular Material Selectс жестко закодированными часами.

angular material form inputs working hours hardcoded

Но это совсем не оптимально, и я мог только сойти с ума, уведомив пользователей, что показанное время имеет указанный часовой пояс.

Я также пытался следовать этому руководству , но безрезультатно.

Я установил момент и момент-время, но пока не могу понять.

Я сохраняю забронированные даты и часы в базе данных и извлекаю их с помощью angular / fire, например,

table: Table;
this.db.list('timetable').valueChanges()
      .subscribe(table => this.table = table);

Затем я беру значение из ввода DatePicker и проверяю, какие рабочие часы доступны

selectedDate: string;
hours = hours; // a list of objects with hardcoded working hours in it, like {hour: "8:00", booked: false}, {hour: "9:00", booked: true} etc.
selectDate(e: MatDatepickerInputEvent<Date>) {
    this.selectedDate = new Date(e.target.value).toLocaleDateString();
    const bookedHours: string[] = [];
    this.table.forEach((booking) => {
      if (this.selectedDate === booking.date) {
        bookedHours.push(booking.hour);
      }
    });

    this.hours.forEach(time => {
      if (bookedHours.includes(time.hour)) {time.booked = true;
      } else { time.booked = false; }
    });
  }

И если, например, 10 утра забронировано, это выглядит так: hour unavailable

Я знаю, что реализация плохая и хакерская, и я открыт для предложений по этому вопросу.

1 Ответ

1 голос
/ 07 апреля 2019

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

Помимо обычной установки npm, также необходимо набирать файлы:

npm i luxon --save
npm i @types/luxon --save-dev

Я создал вспомогательный сервис в своем угловом приложении, добавил luxon:

import {DateTime, Interval} from 'luxon';

и функцию, которая получает дату JS и возвращает рабочие часы по местному времени пользователя.

getHours(date: Date) {
  const hours: DateTime[] = [];
  // Convert user date to local date
  const userSelectedDate = this.userDate(date);
  const serviceLocalTime = userSelectedDate.toUTC().setZone(service_ZONE),
        // Set working hours for the date
        serviceWorkStart = serviceLocalTime.set(service_OBJECT),
        serviceWorkEnd = serviceLocalTime.set(service_OBJECT).plus({hour: TOTAL_WORKING_HOURS});
        // Convert back to user date with hours
  const userWorkStart = serviceWorkStart.toLocal(),
        userWorkEnd = serviceWorkEnd.toLocal(),
        userWorkingHours = Interval.fromDateTimes(userWorkStart, userWorkEnd).divideEqually(TOTAL_WORKING_HOURS);
  userWorkingHours.forEach(hour => {
    if (hour.start.day < userSelectedDate.day) {
      const dayUp = hour.start.plus({day: 1});
      if (dayUp.toUTC().setZone(service_ZONE).weekday === 3 || dayUp.toUTC().setZone(service_ZONE).weekday === 7) {
        // Day-offs are not added to the list
      } else { hours.push(dayUp); }
    } else {
      if (hour.start.toUTC().setZone(service_ZONE).weekday === 3 || hour.start.toUTC().setZone(service_ZONE).weekday === 7) {
        // Day-offs are not added to the list
      } else { hours.push(hour.start); }
    }
  });
  return hours.sort((a, b) => a.hour - b.hour);
}

Код компонента также был переработан.

selectDate(e: MatDatepickerInputEvent<Date>) {
    this.selectedDateHours = [];
    if (this.bookForm.controls.date.invalid) {
      this.bookForm.controls.hours.reset();
      this.selectDisabled = true;
    } else {
      this.selectDisabled = false;
      const dateInput = this.dtService.getHours(e.target.value);
      dateInput.forEach(hour => {
        if (this.table.some(booking => booking.hour === hour.toUTC().toISO())) {
          this.selectedDateHours.push({hour: hour, booked: true});
        } else {
          this.selectedDateHours.push({hour: hour, booked: false});
        }
      });
    }
  }

Если у кого-нибудь есть более элегантное решение, я был бы рад узнать:)

...