typescript 要计划的日期和格式的组数组

ewm0tg9j  于 2023-02-05  发布在  TypeScript
关注(0)|答案(2)|浏览(137)
    • bounty将在13小时后过期**。回答此问题可获得+50声望奖励。player1ykt希望引起更多人关注此问题。

我需要对一个日期数组进行分组,然后将这组日期格式化为日程格式。

    • 可能的标签包括:**
  • 平日(星期一至五)
  • 周末(周六和周日)
  • 星期一至星期二(具有相同计划的日期范围)
  • 星期三(具有唯一计划的特定日期)
  • 星期四、星期六(具有相同计划的特定日期组)
    • 例如:**
    • 输入数据**
[
  {
    day: "monday",
    start_time: "09:00",
    end_time: "18:00"
  },
  {
    day: "tuesday",
    start_time: "09:00",
    end_time: "18:00"
  },
  {
    day: "wednesday",
    start_time: "09:00",
    end_time: "18:00"
  },
  {
    id: 25,
    day: "thursday",
    start_time: "09:00",
    end_time: "18:00"
  },
  {
    day: "friday",
    start_time: "09:00",
    end_time: "18:00"
  },
  {
    day: "saturday",
    start_time: "10:00",
    end_time: "17:00"
  },
  {
    day: "sunday",
    start_time: "10:00",
    end_time: "17:00"
  }
]

预期输出

[
  {
    label: 'All weekdays', // Mon-Fri
    value: '09:00 - 18:00',
  },
  {
    label: 'Weekend', // Sat-Sun
    value: '10:00 - 17:00',
  },
];

如果每天的start_time和end_time不同,则输出如下所示

[
  {
    label: 'Monday', // one day
    value: '09:00 - 20:00',
  },
  {
    label: 'Tuesday, Thursday', // specific days with same schedule
    value: '10:00 - 19:00',
  },
  {
    label: 'Wednesday', // one day
    value: '12:00 - 20:00',
  },
  {
    label: 'Friday - Sunday', // range of days with same schedule
    value: '10:00 - 17:00',
  },
];

带模板的代码沙箱-link

uubf1zoe

uubf1zoe1#

解决OP问题的方法分为......

  • 分组/收集特定时间表/范围的所有项目(或日期名称)
  • 以及基于该第一分组和聚集的数据创建最终结果,

......可以通过reducemap ping任务直接实现,该任务将伴随一些辅助函数,例如......

  • 规范化任何工作日的名称
  • 按名称比较工作日
  • 通过例如唯一工作日名称的有序列表来获取时间表的正确标签。

reduce任务将创建一个对象,其中每个键都已经表示最终结果的value,表示时间范围的字符串,例如'09:00 - 18:00',其中每个这样的键值是每个已处理项的day值的数组(后者是表示工作日名称的字符串,既不具有特定的也不具有可靠的后者大小写,例如'monday''Monday')。
map任务将处理上述对象的entries,每个条目的与时间表相关的key被赋值为最终项的value属性,并且每个条目的与工作日相关的值(工作日名称的数组)是计算最终项的label属性的基础。

执行情况.

// helpers.
function normalizeNameOfWeekday(value) {
  return value
    .toLowerCase()
    .replace(/^(\p{L})(.*)$/u, (_, first, last) =>
      [first.toUpperCase(), last].join('')
    );
}
function compareWeekdaysByName(a, b) {
  const lookup = {
    monday: 0, tuesday: 1, wednesday: 2, 
    thursday: 3, friday: 4,
    saturday: 5, sunday: 6,
  };
  return lookup[a.toLowerCase()] - lookup[b.toLowerCase()];
}
function getTimeScheduleLabel(days) {
  const lookup = {
    monday_tuesday: 'Monday & Tuesday',
    monday_tuesday_wednesday: 'Monday - Wednesday',
    monday_tuesday_wednesday_thursday: 'Monday - Thursday',
    monday_tuesday_wednesday_thursday_friday: 'All working days',
    monday_tuesday_wednesday_thursday_friday_saturday: 'Monday - Saturday',
    monday_tuesday_wednesday_thursday_friday_saturday_sunday: 'Every day of the week',
    tuesday_wednesday: 'Tuesday & Wednesday',
    tuesday_wednesday_thursday: 'Tuesday - Thursday',
    tuesday_wednesday_thursday_friday: 'Tuesday - Friday',
    tuesday_wednesday_thursday_friday_saturday: 'Tuesday - Saturday',
    tuesday_wednesday_thursday_friday_saturday_sunday: 'Tuesday - Sunday',
    wednesday_thursday: 'Wednesday & Thursday',
    wednesday_thursday_friday: 'Wednesday - Friday',
    wednesday_thursday_friday_saturday: 'Wednesday - Saturday',
    wednesday_thursday_friday_saturday_sunday: 'Wednesday - Sunday',
    thursday_friday: 'Thursday & Friday',
    thursday_friday_saturday: 'Thursday - Saturday',
    thursday_friday_saturday_sunday: 'Thursday - Sunday',
    friday_saturday: 'Friday & Saturday',
    friday_saturday_sunday: 'Friday - Sunday',
    saturday_sunday: 'All weekend',
  };
  const scheduleFingerprint = [
    // set of unique day-names.
    ...new Set(days)
  ]
  // ordered list (of unique day-names).
  .sort(compareWeekdaysByName)
  // comparable schedule-fingerprint.
  .join('_').toLowerCase();

  return lookup[scheduleFingerprint] ?? days.map(normalizeNameOfWeekday).join(', ');
}

// reducer.
function collectDayOfSameTimeSchedule(index, { day, start_time, end_time }) {
  const scheduleKey = `${ start_time } - ${ end_time }`;

  // create and/or access the array of
  // day-names of the same time-schedule
  // and push another matching name into it.
  (index[scheduleKey] ??= []).push(day);
  
  return index;
}
// mapper.
function createTimeScheduleFromEntry([scheduleKey, listOfSameTimeScheduleDays]) {
  return {
    label: getTimeScheduleLabel(listOfSameTimeScheduleDays),
    value: scheduleKey,
  }
}

const sampleData_01 = [{
  day: "monday", start_time: "09:00", end_time: "18:00",
}, {
  day: "tuesday", start_time: "09:00", end_time: "18:00",
}, {
  day: "wednesday", start_time: "09:00", end_time: "18:00",
}, {
  id: 25, day: "thursday", start_time: "09:00", end_time: "18:00",
}, {
  day: "friday", start_time: "09:00", end_time: "18:00",
}, {
  day: "saturday", start_time: "10:00", end_time: "17:00",
}, {
  day: "sunday", start_time: "10:00", end_time: "17:00",
}];

const sampleData_02 = [{
  day: "monday", start_time: "09:00", end_time: "20:00",
}, {
  day: "tuesday", start_time: "10:00", end_time: "19:00",
}, {
  day: "wednesday", start_time: "12:00", end_time: "20:00",
}, {
  id: 25, day: "thursday", start_time: "10:00", end_time: "19:00",
}, {
  day: "friday", start_time: "10:00", end_time: "17:00",
}, {
  day: "saturday", start_time: "10:00", end_time: "17:00",
}, {
  day: "sunday", start_time: "10:00", end_time: "17:00",
}];

console.log(
  'sample-data with 2 time-schedules ...',
  Object
    .entries(
      sampleData_01
        .reduce(collectDayOfSameTimeSchedule, {})
    )
    .map(createTimeScheduleFromEntry)
);
console.log(
  'sample-data with 4 time-schedules ...',
  Object
    .entries(
      sampleData_02
        .reduce(collectDayOfSameTimeSchedule, {})
    )
    .map(createTimeScheduleFromEntry)
);
console.log('\n');

console.log(
  'intermediate reducer-step of ... sample-data with 2 time-schedules ...',
  sampleData_01
    .reduce(collectDayOfSameTimeSchedule, {})
);
console.log(
  'intermediate reducer-step of ... sample-data with 4 time-schedules ...',
  sampleData_02
    .reduce(collectDayOfSameTimeSchedule, {})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
e3bfsja2

e3bfsja22#

我有一个类似的解决方案对我的一个项目,你可以尝试作出任何必要的更改代码,如果你不喜欢的结果。
您使用周末和工作日数组给予一个初始常量,然后比较输入的日期数据,生成所需的输出。

function formatDates(dates) {
const result = [];
const weekdays = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'];
const weekends = ['saturday', 'sunday'];
let start = 0;
let end = 0;

while (start < dates.length) {
let label = '';
let value = '';
let same = true;

end = start;
while (end < dates.length - 1 && same) {
  end++;
  same = dates[end].start_time === dates[end - 1].start_time && dates[end].end_time === dates[end - 1].end_time;
}

if (weekdays.includes(dates[start].day) && weekdays.includes(dates[end].day)) {
  label = 'All weekdays';
  value = `${dates[start].start_time} - ${dates[start].end_time}`;
} else if (weekends.includes(dates[start].day) && weekends.includes(dates[end].day)) {
  label = 'Weekend';
  value = `${dates[start].start_time} - ${dates[start].end_time}`;
} else if (same) {
  if (weekdays.includes(dates[start].day)) {
    label = `${dates[start].day[0].toUpperCase()}${dates[start].day.slice(1)} - ${dates[end].day[0].toUpperCase()}${dates[end].day.slice(1)}`;
  } else if (weekends.includes(dates[start].day)) {
    label = `${dates[start].day[0].toUpperCase()}${dates[start].day.slice(1)} - ${dates[end].day[0].toUpperCase()}${dates[end].day.slice(1)}`;
  } else {
    label = `${dates[start].day[0].toUpperCase()}${dates[start].day.slice(1)}`;
  }
  value = `${dates[start].start_time} - ${dates[start].end_time}`;
} else {
  for (let i = start; i <= end; i++) {
    result.push({
      label: `${dates[i].day[0].toUpperCase()}${dates[i].day.slice(1)}`,
      value: `${dates[i].start_time} - ${dates[i].end_time}`
    });
  }
}

if (label) {
  result.push({ label, value });
}

start = end + 1;
}

return result;
}

相关问题