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/README.md CHANGED
@@ -62,6 +62,7 @@ Many transit agencies use `gtfs-to-html` to generate the schedule pages used on
62
62
  | Agency | Location |
63
63
  | ----------------------------------------------------------------------------- | ----------------------------------- |
64
64
  | [Basin Transit](https://basin-transit.com) | Morongo Basin, California |
65
+ | [Bayway Transit](https://www.baywaytransit.org) | Panama City, Florida |
65
66
  | [Brockton Area Transit Authority](https://ridebat.com) | Brockton, Massachusetts |
66
67
  | [Cape Ann Transportation Authority](https://canntran.com) | Gloucester, Massachusetts |
67
68
  | [Capital Transit](https://juneaucapitaltransit.org) | Juneau, Alaska |
package/dist/app/index.js CHANGED
@@ -39,11 +39,11 @@ function fromGTFSTime(timeString) {
39
39
  function toGTFSTime(time) {
40
40
  return time.format("HH:mm:ss");
41
41
  }
42
- function calendarToCalendarCode(c) {
43
- if (Object.values(c).every((value) => value === null)) {
42
+ function calendarToCalendarCode(calendar) {
43
+ if (Object.values(calendar).every((value) => value === null)) {
44
44
  return "";
45
45
  }
46
- return `${c.monday}${c.tuesday}${c.wednesday}${c.thursday}${c.friday}${c.saturday}${c.sunday}`;
46
+ return `${calendar.monday ?? "0"}${calendar.tuesday ?? "0"}${calendar.wednesday ?? "0"}${calendar.thursday ?? "0"}${calendar.friday ?? "0"}${calendar.saturday ?? "0"}${calendar.sunday ?? "0"}`;
47
47
  }
48
48
  function calendarCodeToCalendar(code) {
49
49
  const days2 = [
@@ -61,6 +61,35 @@ function calendarCodeToCalendar(code) {
61
61
  }
62
62
  return calendar;
63
63
  }
64
+ function calendarToDateList(calendar, startDate, endDate) {
65
+ if (!startDate || !endDate) {
66
+ return [];
67
+ }
68
+ const activeWeekdays = [
69
+ calendar.monday === 1 ? 1 : null,
70
+ calendar.tuesday === 1 ? 2 : null,
71
+ calendar.wednesday === 1 ? 3 : null,
72
+ calendar.thursday === 1 ? 4 : null,
73
+ calendar.friday === 1 ? 5 : null,
74
+ calendar.saturday === 1 ? 6 : null,
75
+ calendar.sunday === 1 ? 7 : null
76
+ ].filter((weekday) => weekday !== null);
77
+ if (activeWeekdays.length === 0) {
78
+ return [];
79
+ }
80
+ const activeWeekdaySet = new Set(activeWeekdays);
81
+ const dates = /* @__PURE__ */ new Set();
82
+ const date = moment(startDate.toString(), "YYYYMMDD");
83
+ const endDateMoment = moment(endDate.toString(), "YYYYMMDD");
84
+ while (date.isSameOrBefore(endDateMoment)) {
85
+ const isoWeekday = date.isoWeekday();
86
+ if (activeWeekdaySet.has(isoWeekday)) {
87
+ dates.add(parseInt(date.format("YYYYMMDD"), 10));
88
+ }
89
+ date.add(1, "day");
90
+ }
91
+ return Array.from(dates);
92
+ }
64
93
  function secondsAfterMidnight(timeString) {
65
94
  return moment.duration(timeString).asSeconds();
66
95
  }
@@ -430,7 +459,7 @@ function getAgencyGeoJSON(config2) {
430
459
  // package.json
431
460
  var package_default = {
432
461
  name: "gtfs-to-html",
433
- version: "2.12.2",
462
+ version: "2.12.3",
434
463
  private: false,
435
464
  description: "Build human readable transit timetables as HTML, PDF or CSV from GTFS",
436
465
  keywords: [
@@ -1188,9 +1217,9 @@ var getCalendarsFromTimetable = (timetable) => {
1188
1217
  }
1189
1218
  return db.prepare(`SELECT * FROM calendar ${whereClause}`).all();
1190
1219
  };
1191
- var getCalendarDatesServiceIds = (startDate, endDate) => {
1220
+ var getCalendarDatesForDateRange = (startDate, endDate) => {
1192
1221
  const db = openDb();
1193
- const whereClauses = ["exception_type = 1"];
1222
+ const whereClauses = [];
1194
1223
  if (endDate) {
1195
1224
  whereClauses.push(`date <= ${sqlString.escape(endDate)}`);
1196
1225
  }
@@ -1198,11 +1227,11 @@ var getCalendarDatesServiceIds = (startDate, endDate) => {
1198
1227
  whereClauses.push(`date >= ${sqlString.escape(startDate)}`);
1199
1228
  }
1200
1229
  const calendarDates = db.prepare(
1201
- `SELECT DISTINCT service_id FROM calendar_dates WHERE ${whereClauses.join(
1230
+ `SELECT service_id, date, exception_type FROM calendar_dates WHERE ${whereClauses.join(
1202
1231
  " AND "
1203
1232
  )}`
1204
1233
  ).all();
1205
- return calendarDates.map((calendarDate) => calendarDate.service_id);
1234
+ return calendarDates;
1206
1235
  };
1207
1236
  var getAllStationStopIds = (stopId) => {
1208
1237
  const stops = getStops({
@@ -1413,13 +1442,49 @@ var formatTimetables = (timetables, config2) => {
1413
1442
  timetable.warnings = [];
1414
1443
  const dayList = formatDays(timetable, config2);
1415
1444
  const calendars = getCalendarsFromTimetable(timetable);
1416
- let serviceIds = calendars.map((calendar) => calendar.service_id);
1445
+ const serviceIds = /* @__PURE__ */ new Set();
1446
+ for (const calendar of calendars) {
1447
+ serviceIds.add(calendar.service_id);
1448
+ }
1417
1449
  if (timetable.include_exceptions === 1) {
1418
- const calendarDatesServiceIds = getCalendarDatesServiceIds(
1450
+ const calendarDates = getCalendarDatesForDateRange(
1419
1451
  timetable.start_date,
1420
1452
  timetable.end_date
1421
1453
  );
1422
- serviceIds = uniq([...serviceIds, ...calendarDatesServiceIds]);
1454
+ const calendarDateGroups = groupBy(calendarDates, "service_id");
1455
+ for (const [serviceId, calendarDateGroup] of Object.entries(
1456
+ calendarDateGroups
1457
+ )) {
1458
+ const calendar = calendars.find(
1459
+ (c) => c.service_id === serviceId
1460
+ );
1461
+ if (calendarDateGroup.some(
1462
+ (calendarDate) => calendarDate.exception_type === 1
1463
+ )) {
1464
+ serviceIds.add(serviceId);
1465
+ }
1466
+ const calendarDateGroupExceptionType2 = calendarDateGroup.filter(
1467
+ (calendarDate) => calendarDate.exception_type === 2
1468
+ );
1469
+ if (timetable.start_date && timetable.end_date && calendar && calendarDateGroupExceptionType2.length > 0) {
1470
+ const datesDuringDateRange = calendarToDateList(
1471
+ calendar,
1472
+ timetable.start_date,
1473
+ timetable.end_date
1474
+ );
1475
+ if (datesDuringDateRange.length === 0) {
1476
+ serviceIds.delete(serviceId);
1477
+ }
1478
+ const everyDateIsExcluded = datesDuringDateRange.every(
1479
+ (dateDuringDateRange) => calendarDateGroupExceptionType2.some(
1480
+ (calendarDate) => calendarDate.date === dateDuringDateRange
1481
+ )
1482
+ );
1483
+ if (everyDateIsExcluded) {
1484
+ serviceIds.delete(serviceId);
1485
+ }
1486
+ }
1487
+ }
1423
1488
  }
1424
1489
  Object.assign(timetable, {
1425
1490
  noServiceSymbolUsed: false,
@@ -1437,7 +1502,7 @@ var formatTimetables = (timetables, config2) => {
1437
1502
  noPickupSymbol: config2.noPickupSymbol,
1438
1503
  interpolatedStopSymbol: config2.interpolatedStopSymbol,
1439
1504
  orientation: timetable.orientation || config2.defaultOrientation,
1440
- service_ids: serviceIds,
1505
+ service_ids: Array.from(serviceIds),
1441
1506
  dayList,
1442
1507
  dayListLong: formatDaysLong(dayList, config2)
1443
1508
  });