gtfs-to-html 2.12.2 → 2.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -61,11 +61,11 @@ function fromGTFSTime(timeString) {
61
61
  function toGTFSTime(time) {
62
62
  return time.format("HH:mm:ss");
63
63
  }
64
- function calendarToCalendarCode(c) {
65
- if (Object.values(c).every((value) => value === null)) {
64
+ function calendarToCalendarCode(calendar) {
65
+ if (Object.values(calendar).every((value) => value === null)) {
66
66
  return "";
67
67
  }
68
- return `${c.monday}${c.tuesday}${c.wednesday}${c.thursday}${c.friday}${c.saturday}${c.sunday}`;
68
+ return `${calendar.monday ?? "0"}${calendar.tuesday ?? "0"}${calendar.wednesday ?? "0"}${calendar.thursday ?? "0"}${calendar.friday ?? "0"}${calendar.saturday ?? "0"}${calendar.sunday ?? "0"}`;
69
69
  }
70
70
  function calendarCodeToCalendar(code) {
71
71
  const days2 = [
@@ -83,6 +83,35 @@ function calendarCodeToCalendar(code) {
83
83
  }
84
84
  return calendar;
85
85
  }
86
+ function calendarToDateList(calendar, startDate, endDate) {
87
+ if (!startDate || !endDate) {
88
+ return [];
89
+ }
90
+ const activeWeekdays = [
91
+ calendar.monday === 1 ? 1 : null,
92
+ calendar.tuesday === 1 ? 2 : null,
93
+ calendar.wednesday === 1 ? 3 : null,
94
+ calendar.thursday === 1 ? 4 : null,
95
+ calendar.friday === 1 ? 5 : null,
96
+ calendar.saturday === 1 ? 6 : null,
97
+ calendar.sunday === 1 ? 7 : null
98
+ ].filter((weekday) => weekday !== null);
99
+ if (activeWeekdays.length === 0) {
100
+ return [];
101
+ }
102
+ const activeWeekdaySet = new Set(activeWeekdays);
103
+ const dates = /* @__PURE__ */ new Set();
104
+ const date = moment(startDate.toString(), "YYYYMMDD");
105
+ const endDateMoment = moment(endDate.toString(), "YYYYMMDD");
106
+ while (date.isSameOrBefore(endDateMoment)) {
107
+ const isoWeekday = date.isoWeekday();
108
+ if (activeWeekdaySet.has(isoWeekday)) {
109
+ dates.add(parseInt(date.format("YYYYMMDD"), 10));
110
+ }
111
+ date.add(1, "day");
112
+ }
113
+ return Array.from(dates);
114
+ }
86
115
  function secondsAfterMidnight(timeString) {
87
116
  return moment.duration(timeString).asSeconds();
88
117
  }
@@ -493,7 +522,7 @@ function formatTripNameForCSV(trip, timetable) {
493
522
  // package.json
494
523
  var package_default = {
495
524
  name: "gtfs-to-html",
496
- version: "2.12.2",
525
+ version: "2.12.3",
497
526
  private: false,
498
527
  description: "Build human readable transit timetables as HTML, PDF or CSV from GTFS",
499
528
  keywords: [
@@ -1251,9 +1280,9 @@ var getCalendarsFromTimetable = (timetable) => {
1251
1280
  }
1252
1281
  return db.prepare(`SELECT * FROM calendar ${whereClause}`).all();
1253
1282
  };
1254
- var getCalendarDatesServiceIds = (startDate, endDate) => {
1283
+ var getCalendarDatesForDateRange = (startDate, endDate) => {
1255
1284
  const db = openDb();
1256
- const whereClauses = ["exception_type = 1"];
1285
+ const whereClauses = [];
1257
1286
  if (endDate) {
1258
1287
  whereClauses.push(`date <= ${sqlString.escape(endDate)}`);
1259
1288
  }
@@ -1261,11 +1290,11 @@ var getCalendarDatesServiceIds = (startDate, endDate) => {
1261
1290
  whereClauses.push(`date >= ${sqlString.escape(startDate)}`);
1262
1291
  }
1263
1292
  const calendarDates = db.prepare(
1264
- `SELECT DISTINCT service_id FROM calendar_dates WHERE ${whereClauses.join(
1293
+ `SELECT service_id, date, exception_type FROM calendar_dates WHERE ${whereClauses.join(
1265
1294
  " AND "
1266
1295
  )}`
1267
1296
  ).all();
1268
- return calendarDates.map((calendarDate) => calendarDate.service_id);
1297
+ return calendarDates;
1269
1298
  };
1270
1299
  var getAllStationStopIds = (stopId) => {
1271
1300
  const stops = getStops({
@@ -1476,13 +1505,49 @@ var formatTimetables = (timetables, config) => {
1476
1505
  timetable.warnings = [];
1477
1506
  const dayList = formatDays(timetable, config);
1478
1507
  const calendars = getCalendarsFromTimetable(timetable);
1479
- let serviceIds = calendars.map((calendar) => calendar.service_id);
1508
+ const serviceIds = /* @__PURE__ */ new Set();
1509
+ for (const calendar of calendars) {
1510
+ serviceIds.add(calendar.service_id);
1511
+ }
1480
1512
  if (timetable.include_exceptions === 1) {
1481
- const calendarDatesServiceIds = getCalendarDatesServiceIds(
1513
+ const calendarDates = getCalendarDatesForDateRange(
1482
1514
  timetable.start_date,
1483
1515
  timetable.end_date
1484
1516
  );
1485
- serviceIds = uniq([...serviceIds, ...calendarDatesServiceIds]);
1517
+ const calendarDateGroups = groupBy(calendarDates, "service_id");
1518
+ for (const [serviceId, calendarDateGroup] of Object.entries(
1519
+ calendarDateGroups
1520
+ )) {
1521
+ const calendar = calendars.find(
1522
+ (c) => c.service_id === serviceId
1523
+ );
1524
+ if (calendarDateGroup.some(
1525
+ (calendarDate) => calendarDate.exception_type === 1
1526
+ )) {
1527
+ serviceIds.add(serviceId);
1528
+ }
1529
+ const calendarDateGroupExceptionType2 = calendarDateGroup.filter(
1530
+ (calendarDate) => calendarDate.exception_type === 2
1531
+ );
1532
+ if (timetable.start_date && timetable.end_date && calendar && calendarDateGroupExceptionType2.length > 0) {
1533
+ const datesDuringDateRange = calendarToDateList(
1534
+ calendar,
1535
+ timetable.start_date,
1536
+ timetable.end_date
1537
+ );
1538
+ if (datesDuringDateRange.length === 0) {
1539
+ serviceIds.delete(serviceId);
1540
+ }
1541
+ const everyDateIsExcluded = datesDuringDateRange.every(
1542
+ (dateDuringDateRange) => calendarDateGroupExceptionType2.some(
1543
+ (calendarDate) => calendarDate.date === dateDuringDateRange
1544
+ )
1545
+ );
1546
+ if (everyDateIsExcluded) {
1547
+ serviceIds.delete(serviceId);
1548
+ }
1549
+ }
1550
+ }
1486
1551
  }
1487
1552
  Object.assign(timetable, {
1488
1553
  noServiceSymbolUsed: false,
@@ -1500,7 +1565,7 @@ var formatTimetables = (timetables, config) => {
1500
1565
  noPickupSymbol: config.noPickupSymbol,
1501
1566
  interpolatedStopSymbol: config.interpolatedStopSymbol,
1502
1567
  orientation: timetable.orientation || config.defaultOrientation,
1503
- service_ids: serviceIds,
1568
+ service_ids: Array.from(serviceIds),
1504
1569
  dayList,
1505
1570
  dayListLong: formatDaysLong(dayList, config)
1506
1571
  });