diff --git a/docs/onebusaway-gtfs-transformer-cli.md b/docs/onebusaway-gtfs-transformer-cli.md index b5ea3b73..92873436 100644 --- a/docs/onebusaway-gtfs-transformer-cli.md +++ b/docs/onebusaway-gtfs-transformer-cli.md @@ -23,6 +23,7 @@ * [Trim a Trip](#trim-a-trip) * [Generate Stop Times](#generate-stop-times) * [Extend Service Calendars](#extend-service-calendars) + * [Remove Old Calendar Statements](#remove-old-calendar-statements) * [Deduplicate Calendar Entries](#deduplicate-calendar-entries) * [Truncate New Calendar Statements](#truncate-new-calendar-statements) * [Merge Trips and Simplify Calendar Entries](#merge-trips-and-simplify-calendar-entries) @@ -338,7 +339,27 @@ Calendars that have expired before the specified date will be considered inactiv _Note_: We don't make any effort to extend canceled service dates, as specified in `calendar_dates.txt` for holidays and other special events. It's too tricky to automatically determine how they should be handled. You may need to still handle -those manually. +those manually. + +#### Remove Old Calendar Statements + +RemoveOldCalendarStatements is an operation designed to remove calendar entries that are no longer valid on today's date. + +By default, it deletes entries from the calendar.txt file whose end_date field has passed. + +With the remove_today attribute added to the JSON transformer snippet, users can control whether calendar entries valid for today are included or excluded in the output GTFS. + + * If remove_today is set to true, the transformer will remove the calendar entries for the current date. + +``` + {"op":"transform", "class":"org.onebusaway.gtfs_transformer.impl.RemoveOldCalendarStatements", "remove_today":true} +``` + + * If remove_today is set to false or not specified, the transformer will retain the calendar entries for the current date. + +``` +{"op":"transform", "class":"org.onebusaway.gtfs_transformer.impl.RemoveOldCalendarStatements", "remove_today":false} +``` #### Deduplicate Calendar Entries diff --git a/onebusaway-gtfs-transformer/src/main/java/org/onebusaway/gtfs_transformer/impl/RemoveOldCalendarStatements.java b/onebusaway-gtfs-transformer/src/main/java/org/onebusaway/gtfs_transformer/impl/RemoveOldCalendarStatements.java index 434672c7..5fa49183 100644 --- a/onebusaway-gtfs-transformer/src/main/java/org/onebusaway/gtfs_transformer/impl/RemoveOldCalendarStatements.java +++ b/onebusaway-gtfs-transformer/src/main/java/org/onebusaway/gtfs_transformer/impl/RemoveOldCalendarStatements.java @@ -15,19 +15,32 @@ */ package org.onebusaway.gtfs_transformer.impl; +import java.util.HashSet; +import java.util.Set; + +import org.onebusaway.csv_entities.schema.annotations.CsvField; import org.onebusaway.gtfs.model.ServiceCalendar; import org.onebusaway.gtfs.services.GtfsMutableRelationalDao; import org.onebusaway.gtfs_transformer.services.GtfsTransformStrategy; import org.onebusaway.gtfs_transformer.services.TransformContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashSet; -import java.util.Set; +import org.onebusaway.gtfs_transformer.util.CalendarFunctions; +/** + * Remove calendar dates that are past. + * + * remove_today: delete today's calendar dates if true. Default value is false + */ public class RemoveOldCalendarStatements implements GtfsTransformStrategy { + @CsvField(optional = true) + private boolean removeToday = false; + + @CsvField(ignore = true) + private CalendarFunctions helper = new CalendarFunctions(); + + public void setRemoveToday(boolean removeToday) { + this.removeToday = removeToday; + } - private final Logger _log = LoggerFactory.getLogger(RemoveOldCalendarStatements.class); @Override public String getName() { return this.getClass().getSimpleName(); @@ -37,9 +50,14 @@ public String getName() { public void run(TransformContext transformContext, GtfsMutableRelationalDao gtfsMutableRelationalDao) { RemoveEntityLibrary removeEntityLibrary = new RemoveEntityLibrary(); Set serviceCalendarsToRemove = new HashSet(); - for (ServiceCalendar calendar: gtfsMutableRelationalDao.getAllCalendars()) { - java.util.Date today = new java.util.Date(); - if (calendar.getEndDate().getAsDate().before(today)){ + java.util.Date today = new java.util.Date(); + + if (!removeToday) { + today = helper.removeTime(today); + } + + for (ServiceCalendar calendar : gtfsMutableRelationalDao.getAllCalendars()) { + if (calendar.getEndDate().getAsDate().before(today)) { serviceCalendarsToRemove.add(calendar); } } diff --git a/onebusaway-gtfs-transformer/src/test/java/org/onebusaway/gtfs_transformer/impl/RemoveOldCalendarStatementsTest.java b/onebusaway-gtfs-transformer/src/test/java/org/onebusaway/gtfs_transformer/impl/RemoveOldCalendarStatementsTest.java new file mode 100644 index 00000000..3519bfc2 --- /dev/null +++ b/onebusaway-gtfs-transformer/src/test/java/org/onebusaway/gtfs_transformer/impl/RemoveOldCalendarStatementsTest.java @@ -0,0 +1,70 @@ +package org.onebusaway.gtfs_transformer.impl; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import java.io.IOException; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onebusaway.gtfs.services.GtfsMutableRelationalDao; +import org.onebusaway.gtfs.services.MockGtfs; +import org.onebusaway.gtfs_transformer.services.TransformContext; + +public class RemoveOldCalendarStatementsTest { + + private RemoveOldCalendarStatements removeOldCalendarStatements = new RemoveOldCalendarStatements(); + private TransformContext _context = new TransformContext(); + private MockGtfs _gtfs; + + @BeforeEach + public void setup() throws IOException{ + + _gtfs = MockGtfs.create(); + _gtfs.putAgencies(1); + _gtfs.putStops(1); + _gtfs.putRoutes(1); + _gtfs.putTrips(1, "r0", "sid0"); + _gtfs.putStopTimes("t0", "s0"); + + // Insert a calendar entry wtih start and end dates set to today's date + String startDate = getCurrentDateFormatted(-3); + String endDate = getCurrentDateFormatted(null); + + _gtfs.putCalendars( + 1, + "start_date="+startDate, + "end_date="+endDate + ); + } + + @Test + public void testRemoveCalendarForToday() throws IOException { + GtfsMutableRelationalDao dao = _gtfs.read(); + // Set removeToday to true to allow the removal of the calendar for today's date + removeOldCalendarStatements.setRemoveToday(true); + removeOldCalendarStatements.run(_context, dao); + // Verify that GtfsMutableRelationalDao object no longer contains any calendar entries after removing the calendar for today's date + assertEquals(0,dao.getAllCalendars().size()); + } + + @Test + public void testRemoveCalendar() throws IOException { + GtfsMutableRelationalDao dao = _gtfs.read(); + // Keep the default value as false and do not change it + removeOldCalendarStatements.run(_context, dao); + // Verify that GtfsMutableRelationalDao object still contain the initially added calendar entry + assertEquals(1,dao.getAllCalendars().size()); + } + + // Helper function to get today's date in the required format + public static String getCurrentDateFormatted(Integer daysOffset) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); + LocalDate date = LocalDate.now(); + if (daysOffset != null){ + date = date.plusDays(daysOffset); + } + // Format date as "yyyyMMdd" + return date.format(formatter); + } +} \ No newline at end of file