Moment.js - Продолжительность в рабочие часы / часы работы / смены? - PullRequest
0 голосов
/ 26 апреля 2018

заранее спасибо за вашу помощь. Я пытаюсь рассчитать продолжительность между двумя датами с помощью moment.js, но не могу понять, как считать только время (в нашем случае минуты), когда оно находится в пределах нашего рабочего / рабочего времени.

С учетом этих рабочих часов:

  • M-F с 8:00 до 18:00
  • Са-Су с 10:00 до 14:00

простой пример продолжительности

Если работа начинается в четверг в 16:00 и заканчивается в пятницу в 9:30, то продолжительность составляет 210 минут (4-6 вечера = 120 минут, 8-9: 30а = 90 минут).

пример менее простой продолжительности

Если работа началась в четверг в 16:00 и закончилась в субботу в 9:30, продолжительность составляет 720 минут (4-6 вечера = 120 минут, 8a-6p = 600 минут, время между пятницей 6p и субботой 10a). не добавляет к продолжительности)

Ответы [ 3 ]

0 голосов
/ 26 апреля 2018

Как указал Cruril, есть библиотека для работы с этим, которая называется moment-business-time , и это плагин для Moment.js .

Проблема в том, что вы не можете запустить плагин в браузере, потому что это пакет Node. Я взял на себя смелость извлечь сценарий, чтобы избежать всей неприятной логики. Существует открытый билет для построения клиентского скрипта с использованием browserify .

Я задокументировал шаги по созданию клиентского скрипта здесь , но скомпилированный скрипт все еще не может найти функцию workingDiff. Поэтому я включил упрощенный; рабочая версия момента-бизнеса-времени приведена в скрипте ниже.

moment.updateLocale('en', {
  workinghours: {
    0: null,                       // Sun : CLOSED
    1: [ '12:00:00', '20:00:00' ], // Mon : 8am - 4pm  (local EDT)
    2: [ '12:00:00', '18:00:00' ], // Tue : 8am - 2pm  (local EDT)
    3: [ '12:00:00', '20:00:00' ], // Wed : 8am - 4pm  (local EDT)
    4: [ '12:00:00', '18:00:00' ], // Thu : 8am - 2pm  (local EDT)
    5: [ '12:00:00', '16:00:00' ], // Fri : 8am - 12pm (local EDT)
    6: null                        // Sat : CLOSED
  },
  holidays : []
});

moment.locale('en');
moment.tz.setDefault("America/New_York"); // Timezone plugin

var dateFormat = 'MM/DD/YYYY hh:mm:ss a';

// 0 + 8 + 6 + 8 + 6 + (4 - 1.5) + 0 = 30.5
var fromDate = moment('04/01/2018 00:00:00 am', dateFormat); // 2018-04-01T04:00:00.000Z
var toDate   = moment('04/06/2018 02:30:00 pm', dateFormat); // 2018-04-06T18:30:00.000Z

console.log(fromDate.workingDiff(toDate, 'hours'));       // 30 hours
console.log(fromDate.workingDiff(toDate, 'hours', true)); // 30.5 hours
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.16/moment-timezone.min.js"></script>
<script src="https://rawgit.com/ryankane/32084550b349eaebe7e78e46903084ce/raw/434cf510165a65c234a8cb1cb99641bc7ab15c16/moment-business-time.js"></script>

<!--

https://github.com/lennym/moment-business-time
https://www.npmjs.com/package/moment-business-days#how-to-use

-->
0 голосов
/ 27 апреля 2018

Как правило - не размещайте вопрос, не показывая, что у вас есть в данный момент. Не следует обращать внимание на просьбу о бесплатной работе. Сказав это, я также не думаю, что использование библиотеки для этого - обязательно путь, если вы относительно зеленый. Вы только поправляетесь, кодируя.

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

Попробуйте просмотреть код и написать собственную реализацию.

function isOutOfTimeRange(time, start, end) {
  var date = time.format('YYYY-MM-DD');
  var startDate = date + ' ' + start;
  var endDate = date + ' ' + end;
  if (!time.isBetween(startDate, endDate, 'minute')) {
    var timeFormatted = time.format('YYYY-MM-DD HH:mm');
    // If the time is exactly start or end time it should be ok to use
    if ((timeFormatted === startDate) || (timeFormatted === endDate)) {
      return false;
    }
    return true;
  }
  return false;
}

function isOutOfHours(time, businessHrs) {
  var day = time.day();
  var dayStart = businessHrs[day].start;
  var dayEnd = businessHrs[day].end;

  return isOutOfTimeRange(time, dayStart, dayEnd);
}

function getMinsWorked(startTime, endTime) {
  return moment.duration(endTime.diff(startTime)).as('minutes');
}

function minutesWorked(startJob, endJob, bizHrs) {

  var start = moment(startJob);
  var end = moment(endJob);

  // return early if the start and end time range is invalid
  if (end.isBefore(start, 'second')) {
    return 'A job cannot start after it has ended!';
  }
  // return early if start or end is not within business hours
  if (isOutOfHours(start, bizHrs) || isOutOfHours(end, bizHrs)) {
    console.log('The start and end date must not be out of hours');
  }

  var timeDiff = moment.duration(end.diff(start));
  var firstDay = start.day();
  var lastDay = end.day();

  // return early if we can make a quick calculation on the same day
  if (firstDay === lastDay) {
    // create a duration object by diffing the end and start dates and return as minutes
    return timeDiff.as('minutes');
  }

  var totalMinsWorked = 0;
  var endTime;
  var startTime;

  for (var i = firstDay; i <= lastDay; ++i) {
    var currentDay = start.add(i - firstDay, 'days');
    var dateStr = currentDay.format('YYYY-MM-DD');
    var dayStart = moment(dateStr + ' ' + bizHrs[i].start);
    var dayEnd = moment(dateStr + ' ' + bizHrs[i].end);

    // it's the last day so diff the end time from the start
    if (i === lastDay) {
      totalMinsWorked += getMinsWorked(dayStart, end);
    }

    // it's the first day so go from the start time
    if (i === firstDay) {
      totalMinsWorked += getMinsWorked(start, dayEnd);
    }

    // its a centre day so just get the dif of the start to the end
    totalMinsWorked += getMinsWorked(dayStart, dayEnd);
  }
  return totalMinsWorked;
}

console.log(minutesWorked('2018-05-16 10:00', '2018-05-16 12:30', [{ // index 0 is Sunday
    start: '10:00',
    end: '14:00'
  },
  {
    start: '08:00',
    end: '18:00'
  },
  {
    start: '08:00',
    end: '18:00'
  },
  {
    start: '08:00',
    end: '18:00'
  },
  {
    start: '08:00',
    end: '18:00'
  },
  {
    start: '08:00',
    end: '18:00'
  },
  { // index 6 is Sat
    start: '10:00',
    end: '14:00'
  }
]));
<script src="https://momentjs.com/downloads/moment.js"></script>
0 голосов
/ 26 апреля 2018

Существует библиотека, созданная в данный момент, для этой конкретной задачи. https://www.npmjs.com/package/moment-business-time.
Я считаю, что что-то вроде приведенного ниже примера будет работать для вас.

moment('2015-02-27T16:30:00Z').workingDiff(moment('2015-02-26T12:00:00Z'), 'hours');
// 12 
moment('2015-02-27T16:30:00Z').workingDiff(moment('2015-02-26T12:00:00Z'), 'hours', true);
// 12.5 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...