如何在javascript中正确存储和显示不同时区的工作时间?

时间:2019-04-01 10:58:42

标签: javascript angular firebase momentjs

因此,我正在尝试在提供在线服务的网站上进行预订(预定),我希望正确显示最终用户的日期和时间(工作日和小时数),同时考虑时区,夏令时和和所有棘手的东西。服务提供商的实际位置位于时区+5,工作时间为上午8点至下午5点。因此,例如,我希望实际用户在+4时区看到的工作时间是上午7点至下午4点。

暂时我正在使用Angular Material Datepicker存储日期,并使用带有硬编码小时数的Angular Material Select。

angular material form inputs working hours hardcoded

但这根本不是最佳选择,我只能通知用户显示的时间是指定的时区。

我也尝试遵循this guide,但无济于事。

我已经安装了矩和矩时区,但是还不能弄清楚。

我将预订的日期和时间存储在Firebase中,并像这样用角度/开火来检索它们

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 个答案:

答案 0 :(得分:1)

正如我在上面所说的,momentjs和moment-timezone都不理想,无法弄清楚它们。我最终使用了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});
        }
      });
    }
  }

如果有人有更好的解决方案,我将很高兴知道:)