diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index c948d61..deeedef 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -1,20 +1,21 @@ add_definitions(-DSOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}") ecm_add_test(jnisignaturetest.cpp LINK_LIBRARIES Qt5::Test) ecm_add_test(pkpassmanagertest.cpp LINK_LIBRARIES Qt5::Test itinerary) ecm_add_test(reservationmanagertest.cpp LINK_LIBRARIES Qt5::Test itinerary) ecm_add_test(applicationcontrollertest.cpp LINK_LIBRARIES Qt5::Test itinerary) ecm_add_test(tripgrouptest.cpp LINK_LIBRARIES Qt5::Test itinerary) +ecm_add_test(locationinformationtest.cpp LINK_LIBRARIES Qt5::Test itinerary) ecm_add_test(timelinemodeltest.cpp modelverificationpoint.cpp TEST_NAME timelinemodeltest LINK_LIBRARIES Qt5::Test itinerary) ecm_add_test(tripgroupproxytest.cpp modelverificationpoint.cpp TEST_NAME tripgroupproxytest LINK_LIBRARIES Qt5::Test itinerary) ecm_add_test(tripgroupinfoprovidertest.cpp TEST_NAME tripgroupinfoprovidertest LINK_LIBRARIES Qt5::Test itinerary) ecm_add_test(publictransporttest.cpp TEST_NAME publictransporttest LINK_LIBRARIES Qt5::Test itinerary) ecm_add_test(timelinedelegatecontrollertest.cpp TEST_NAME timelinedelegatecontrollertest LINK_LIBRARIES Qt5::Test itinerary) ecm_add_test(documentmanagertest.cpp TEST_NAME documentmanagertest LINK_LIBRARIES Qt5::Test itinerary) ecm_add_test(statisticstest.cpp LINK_LIBRARIES Qt5::Test itinerary) ecm_add_test(favoritelocationtest.cpp LINK_LIBRARIES Qt5::Test itinerary) ecm_add_test(transfertest.cpp LINK_LIBRARIES Qt5::Test itinerary) ecm_add_test(weathertest.cpp LINK_LIBRARIES Qt5::Test itinerary-weather) target_include_directories(weathertest PRIVATE ${CMAKE_BINARY_DIR}) diff --git a/autotests/data/timeline/daychange-r2.model b/autotests/data/timeline/daychange-r2.model index 96504c9..29d9341 100644 --- a/autotests/data/timeline/daychange-r2.model +++ b/autotests/data/timeline/daychange-r2.model @@ -1,318 +1,322 @@ [ { "isToday": false, "locationInformation": { "@context": "http://schema.org", "@type": "LocationInformation", "drivingSide": "Left", "drivingSideDiffers": true, "isoCode": "GB", "powerPlugCompatibility": "Incompatible", "powerPlugTypes": "Europlug, Schuko", - "powerSocketTypes": "Type G" + "powerSocketTypes": "Type G", + "timeZoneDiffers": false, + "timeZoneName": "Greenwich Mean Time" }, "rangeType": 0, "sectionHeader": "Wednesday, 4 Jan 2017", "type": 5 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "UA", "name": "United Airlines" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "GB" }, "geo": { "@type": "GeoCoordinates", "latitude": 51.477500915527344, "longitude": -0.4613890051841736 }, "iataCode": "LHR", "name": "Heathrow" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-01-04T08:25:00+00:00", "timezone": "Europe/London" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Tegel" }, "departureDay": "2017-01-04", "departureTime": { "@type": "QDateTime", "@value": "2017-01-04T07:20:00+01:00", "timezone": "Europe/Berlin" }, "flightNumber": "9668" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Wednesday, 4 Jan 2017", "type": 6 }, { "isToday": false, "locationInformation": { "@context": "http://schema.org", "@type": "LocationInformation", "drivingSide": "Right", "drivingSideDiffers": false, "isoCode": "US", "powerPlugCompatibility": "Incompatible", "powerPlugTypes": "Europlug, Schuko", - "powerSocketTypes": "Type A, Type B" + "powerSocketTypes": "Type A, Type B", + "timeZoneDiffers": true, + "timeZoneName": "Pacific Standard Time" }, "rangeType": 0, "sectionHeader": "Wednesday, 4 Jan 2017", "type": 5 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "UA", "name": "United Airlines" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 37.618900299072266, "longitude": -122.375 }, "iataCode": "SFO", "name": "San Francisco International" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-01-04T14:45:00-08:00", "timezone": "America/Los_Angeles" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "GB" }, "geo": { "@type": "GeoCoordinates", "latitude": 51.477500915527344, "longitude": -0.4613890051841736 }, "iataCode": "LHR", "name": "Heathrow" }, "departureDay": "2017-01-04", "departureTime": { "@type": "QDateTime", "@value": "2017-01-04T11:40:00+00:00", "timezone": "Europe/London" }, "flightNumber": "900" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Wednesday, 4 Jan 2017", "type": 6 }, { "isToday": true, "isTodayEmpty": false, "rangeType": 0, "sectionHeader": "Today", "type": 1 }, { "isToday": true, "rangeType": 0, "sectionHeader": "Today", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 23, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Sunday, 16 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Monday, 17 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Tuesday, 18 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Wednesday, 19 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Thursday, 20 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Friday, 21 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Saturday, 22 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Sunday, 23 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } } ] diff --git a/autotests/data/timeline/daychange-r3.model b/autotests/data/timeline/daychange-r3.model index e190b5d..b84ccc8 100644 --- a/autotests/data/timeline/daychange-r3.model +++ b/autotests/data/timeline/daychange-r3.model @@ -1,318 +1,322 @@ [ { "isToday": false, "locationInformation": { "@context": "http://schema.org", "@type": "LocationInformation", "drivingSide": "Left", "drivingSideDiffers": true, "isoCode": "GB", "powerPlugCompatibility": "Incompatible", "powerPlugTypes": "Europlug, Schuko", - "powerSocketTypes": "Type G" + "powerSocketTypes": "Type G", + "timeZoneDiffers": false, + "timeZoneName": "Greenwich Mean Time" }, "rangeType": 0, "sectionHeader": "Wednesday, 4 Jan 2017", "type": 5 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "UA", "name": "United Airlines" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "GB" }, "geo": { "@type": "GeoCoordinates", "latitude": 51.477500915527344, "longitude": -0.4613890051841736 }, "iataCode": "LHR", "name": "Heathrow" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-01-04T08:25:00+00:00", "timezone": "Europe/London" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Tegel" }, "departureDay": "2017-01-04", "departureTime": { "@type": "QDateTime", "@value": "2017-01-04T07:20:00+01:00", "timezone": "Europe/Berlin" }, "flightNumber": "9668" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Wednesday, 4 Jan 2017", "type": 6 }, { "isToday": false, "locationInformation": { "@context": "http://schema.org", "@type": "LocationInformation", "drivingSide": "Right", "drivingSideDiffers": false, "isoCode": "US", "powerPlugCompatibility": "Incompatible", "powerPlugTypes": "Europlug, Schuko", - "powerSocketTypes": "Type A, Type B" + "powerSocketTypes": "Type A, Type B", + "timeZoneDiffers": true, + "timeZoneName": "Pacific Standard Time" }, "rangeType": 0, "sectionHeader": "Wednesday, 4 Jan 2017", "type": 5 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "UA", "name": "United Airlines" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 37.618900299072266, "longitude": -122.375 }, "iataCode": "SFO", "name": "San Francisco International" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-01-04T14:45:00-08:00", "timezone": "America/Los_Angeles" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "GB" }, "geo": { "@type": "GeoCoordinates", "latitude": 51.477500915527344, "longitude": -0.4613890051841736 }, "iataCode": "LHR", "name": "Heathrow" }, "departureDay": "2017-01-04", "departureTime": { "@type": "QDateTime", "@value": "2017-01-04T11:40:00+00:00", "timezone": "Europe/London" }, "flightNumber": "900" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Wednesday, 4 Jan 2017", "type": 6 }, { "isToday": true, "isTodayEmpty": false, "rangeType": 0, "sectionHeader": "Today", "type": 1 }, { "isToday": true, "rangeType": 0, "sectionHeader": "Today", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 4, "symbolIconName": "weather-few-clouds-night", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Monday, 17 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Tuesday, 18 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Wednesday, 19 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Thursday, 20 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Friday, 21 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Saturday, 22 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Sunday, 23 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } }, { "isToday": false, "rangeType": 0, "sectionHeader": "Monday, 24 Oct 2196", "type": 4, "weatherForecast": { "@context": "http://schema.org", "@type": "WeatherForecast", "maximumTemperature": 37.618900299072266, "minimumTemperature": -122.375, "precipitation": 23, "range": 24, "symbolIconName": "weather-few-clouds", "valid": true, "windSpeed": 0 } } ] diff --git a/autotests/data/timeline/multi-traveler-merge-with-countryinfo.model b/autotests/data/timeline/multi-traveler-merge-with-countryinfo.model index 5698887..cadd47d 100644 --- a/autotests/data/timeline/multi-traveler-merge-with-countryinfo.model +++ b/autotests/data/timeline/multi-traveler-merge-with-countryinfo.model @@ -1,378 +1,380 @@ [ { "isToday": true, "isTodayEmpty": true, "rangeType": 0, "sectionHeader": "Today", "type": 1 }, { "isToday": false, "rangeType": 1, "sectionHeader": "Saturday, 1 Jan 2000", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2000-01-01T13:00:00+01:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2000-01-01T16:20:00+01:00", "timezone": "Europe/Rome" }, "name": "Peretola (January 2000)" }, "type": 2 }, { "isToday": false, "rangeType": 0, "sectionHeader": "Saturday, 1 Jan 2000", "transfer": { "@context": "http://schema.org", "@type": "Transfer", "alignment": "Before", "anchorTime": { "@type": "QDateTime", "@value": "2000-01-01T13:00:00+01:00", "timezone": "Europe/Berlin" }, "anchorTimeDelta": 3600, "floatingLocationType": "FavoriteLocation", "from": { "@type": "Location", "latitude": 52.51860046386719, "longitude": 13.376299858093262 }, "fromName": "Home", "state": "Pending", "to": { "@type": "Location", "latitude": 52.55970001220703, "longitude": 13.287799835205078, "name": "Tegel" }, "toName": "Tegel" }, "type": 3 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LH", "name": "Lufthansa" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 48.35390090942383, "longitude": 11.786100387573242 }, "iataCode": "MUC", "name": "Franz Josef Strauss" }, "arrivalTime": { "@type": "QDateTime", "@value": "2000-01-01T14:10:00+01:00", "timezone": "Europe/Berlin" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Tegel" }, "departureDay": "2000-01-01", "departureTime": { "@type": "QDateTime", "@value": "2000-01-01T13:00:00+01:00", "timezone": "Europe/Berlin" }, "flightNumber": "2037" }, "reservationNumber": "XXX007", "underName": { "@type": "Person", "name": "Traveler One" } }, { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LH", "name": "Lufthansa" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 48.35390090942383, "longitude": 11.786100387573242 }, "iataCode": "MUC", "name": "Franz Josef Strauss" }, "arrivalTime": { "@type": "QDateTime", "@value": "2000-01-01T14:10:00+01:00", "timezone": "Europe/Berlin" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Tegel" }, "departureDay": "2000-01-01", "departureTime": { "@type": "QDateTime", "@value": "2000-01-01T13:00:00+01:00", "timezone": "Europe/Berlin" }, "flightNumber": "2037" }, "reservationNumber": "XXX007", "underName": { "@type": "Person", "name": "Traveler Two" } } ], "sectionHeader": "Saturday, 1 Jan 2000", "type": 6 }, { "isToday": false, "locationInformation": { "@context": "http://schema.org", "@type": "LocationInformation", "drivingSide": "Right", "drivingSideDiffers": false, "isoCode": "IT", "powerPlugCompatibility": "PartiallyCompatible", - "powerSocketTypes": "Type L" + "powerSocketTypes": "Type L", + "timeZoneDiffers": false, + "timeZoneName": "Central European Standard Time" }, "rangeType": 0, "sectionHeader": "Saturday, 1 Jan 2000", "type": 5 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LH", "name": "Lufthansa" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "IT" }, "geo": { "@type": "GeoCoordinates", "latitude": 43.808799743652344, "longitude": 11.202899932861328 }, "iataCode": "FLR", "name": "Peretola" }, "arrivalTime": { "@type": "QDateTime", "@value": "2000-01-01T16:20:00+01:00", "timezone": "Europe/Rome" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 48.35390090942383, "longitude": 11.786100387573242 }, "iataCode": "MUC", "name": "Franz Josef Strauss" }, "departureDay": "2000-01-01", "departureTime": { "@type": "QDateTime", "@value": "2000-01-01T15:05:00+01:00", "timezone": "Europe/Berlin" }, "flightNumber": "9440" }, "reservationNumber": "XXX007", "underName": { "@type": "Person", "name": "Traveler One" } }, { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LH", "name": "Lufthansa" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "IT" }, "geo": { "@type": "GeoCoordinates", "latitude": 43.808799743652344, "longitude": 11.202899932861328 }, "iataCode": "FLR", "name": "Peretola" }, "arrivalTime": { "@type": "QDateTime", "@value": "2000-01-01T16:20:00+01:00", "timezone": "Europe/Rome" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 48.35390090942383, "longitude": 11.786100387573242 }, "iataCode": "MUC", "name": "Franz Josef Strauss" }, "departureDay": "2000-01-01", "departureTime": { "@type": "QDateTime", "@value": "2000-01-01T15:05:00+01:00", "timezone": "Europe/Berlin" }, "flightNumber": "9440" }, "reservationNumber": "XXX007", "underName": { "@type": "Person", "name": "Traveler Two" } } ], "sectionHeader": "Saturday, 1 Jan 2000", "type": 6 }, { "isToday": false, "rangeType": 0, "sectionHeader": "Saturday, 1 Jan 2000", "transfer": { "@context": "http://schema.org", "@type": "Transfer", "alignment": "After", "anchorTime": { "@type": "QDateTime", "@value": "2000-01-01T16:20:00+01:00", "timezone": "Europe/Rome" }, "anchorTimeDelta": 1800, "floatingLocationType": "FavoriteLocation", "from": { "@type": "Location", "latitude": 43.808799743652344, "longitude": 11.202899932861328, "name": "Peretola" }, "fromName": "Peretola", "state": "Pending", "to": { "@type": "Location", "latitude": 52.51860046386719, "longitude": 13.376299858093262 }, "toName": "Home" }, "type": 3 }, { "isToday": false, "rangeType": 2, "sectionHeader": "Saturday, 1 Jan 2000", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2000-01-01T13:00:00+01:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2000-01-01T16:20:00+01:00", "timezone": "Europe/Rome" }, "name": "Peretola (January 2000)" }, "type": 2 } ] diff --git a/autotests/data/tripgroupproxy/current-r0.model b/autotests/data/tripgroupproxy/current-r0.model index 3d84153..78d2426 100644 --- a/autotests/data/tripgroupproxy/current-r0.model +++ b/autotests/data/tripgroupproxy/current-r0.model @@ -1,745 +1,747 @@ [ { "isToday": true, "isTodayEmpty": true, "rangeType": 0, "sectionHeader": "Today", "type": 1 }, { "isToday": false, "rangeType": 1, "sectionHeader": "Sunday, 10 Sep 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "name": "Randa (September 2017)" }, "type": 2 }, { "isToday": false, "locationInformation": { "@context": "http://schema.org", "@type": "LocationInformation", "drivingSide": "Right", "drivingSideDiffers": false, "isoCode": "CH", "powerPlugCompatibility": "PartiallyCompatible", "powerPlugTypes": "Schuko", - "powerSocketTypes": "Type J" + "powerSocketTypes": "Type J", + "timeZoneDiffers": false, + "timeZoneName": "Central European Standard Time" }, "rangeType": 0, "sectionHeader": "Sunday, 10 Sep 2017", "type": 5 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "airplaneSeat": "15F", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LX" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.464698791503906, "longitude": 8.549169540405273 }, "iataCode": "ZRH", "name": "Zürich" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T08:15:00+02:00", "timezone": "Europe/Zurich" }, "boardingTime": { "@type": "QDateTime", "@value": "2017-09-10T06:15:00+02:00", "timezone": "Europe/Berlin" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Berlin Tegel" }, "departureDay": "2017-09-10", "departureGate": "A10", "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "flightNumber": "963" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 6 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "7", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T14:02:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-10", "departurePlatform": "3", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.45029830932617, "longitude": 8.562219619750977 }, "identifier": "ibnr:8503016", "name": "Zürich Flughafen" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T11:40:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "IC", "trainNumber": "816" }, "reservedTicket": { "@type": "Ticket", "ticketToken": "aztecCode:i0CVXXX007123456789xxxx01/01/1970xxxxxxxxxxxxxxx24/090011223344556677889 DOE JOHN 00000", "ticketedSeat": { "@type": "Seat", "seatNumber": "62", "seatSection": "17" } } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "identifier": "ibnr:8501687", "name": "Randa" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T14:53:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-10", "departurePlatform": "3", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T14:08:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "R", "trainNumber": "241" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TaxiReservation", "modifiedTime": "2020-01-22T00:00:00", "pickupLocation": { "@type": "Place", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "name": "Randa Bahnhof" }, "pickupTime": { "@type": "QDateTime", "@value": "2017-09-10T14:55:00+02:00", "timezone": "Europe/Zurich" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 0 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "EventReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Event", "location": { "@type": "Place", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa" }, "name": "KDE Randa Meeting 2017", "startDate": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" } }, "underName": { "@type": "Person", "name": "Dr Konqui" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 12 }, { "isToday": false, "rangeType": 1, "reservations": [ { "@context": "http://schema.org", "@type": "LodgingReservation", "checkinTime": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" }, "checkoutTime": { "@type": "QDateTime", "@value": "2017-09-15T10:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "LodgingBusiness", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa", "url": "https://randa-meetings.ch/" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 13 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "BusReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "BusTrip", "arrivalBusStop": { "@type": "BusStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.0242805480957, "longitude": 7.748660087585449 }, "name": "Zermatt" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-13T14:20:00+02:00", "timezone": "Europe/Zurich" }, "busName": "", "busNumber": "Zermatt Taxi", "departureBusStop": { "@type": "BusStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "name": "Randa" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-13T14:00:00+02:00", "timezone": "Europe/Zurich" } } } ], "sectionHeader": "Wednesday, 13 Sep 2017", "type": 9 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TouristAttractionVisit", "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-13T14:30:00+02:00", "timezone": "Europe/Zurich" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-13T15:30:00+02:00", "timezone": "Europe/Zurich" }, "touristAttraction": { "@type": "TouristAttraction", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Zermatt" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.01504898071289, "longitude": 7.742239952087402 }, "name": "Matterhorn" } } ], "sectionHeader": "Wednesday, 13 Sep 2017", "type": 11 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FoodEstablishmentReservation", "endTime": { "@type": "QDateTime", "@value": "2017-09-14T22:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "partySize": 20, "reservationFor": { "@type": "FoodEstablishment", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Raclette" }, "startTime": { "@type": "QDateTime", "@value": "2017-09-14T19:00:00+02:00", "timezone": "Europe/Zurich" } } ], "sectionHeader": "Thursday, 14 Sep 2017", "type": 10 }, { "isToday": false, "rangeType": 2, "reservations": [ { "@context": "http://schema.org", "@type": "LodgingReservation", "checkinTime": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" }, "checkoutTime": { "@type": "QDateTime", "@value": "2017-09-15T10:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "LodgingBusiness", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa", "url": "https://randa-meetings.ch/" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 13 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "3", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T15:46:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-15", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "identifier": "ibnr:8501687", "name": "Randa" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T14:54:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "R", "trainNumber": "250" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "2", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.45029830932617, "longitude": 8.562219619750977 }, "identifier": "ibnr:8503016", "name": "Zürich Flughafen" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T18:16:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-15", "departurePlatform": "2", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T15:57:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "IC", "trainNumber": "827" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "airplaneSeat": "10E", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LX" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Berlin Tegel" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "boardingTime": { "@type": "QDateTime", "@value": "2017-09-15T20:25:00+02:00", "timezone": "Europe/Zurich" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.464698791503906, "longitude": 8.549169540405273 }, "iataCode": "ZRH", "name": "Zürich" }, "departureDay": "2017-09-15", "departureGate": "52", "departureTerminal": "AB", "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T20:50:00+02:00", "timezone": "Europe/Zurich" }, "flightNumber": "962" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 6 }, { "isToday": false, "rangeType": 2, "sectionHeader": "Friday, 15 Sep 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "name": "Randa (September 2017)" }, "type": 2 } ] diff --git a/autotests/data/tripgroupproxy/current-r1.model b/autotests/data/tripgroupproxy/current-r1.model index 8817b41..b6b7d0f 100644 --- a/autotests/data/tripgroupproxy/current-r1.model +++ b/autotests/data/tripgroupproxy/current-r1.model @@ -1,745 +1,747 @@ [ { "isToday": false, "rangeType": 1, "sectionHeader": "Sunday, 10 Sep 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "name": "Randa (September 2017)" }, "type": 2 }, { "isToday": false, "locationInformation": { "@context": "http://schema.org", "@type": "LocationInformation", "drivingSide": "Right", "drivingSideDiffers": false, "isoCode": "CH", "powerPlugCompatibility": "PartiallyCompatible", "powerPlugTypes": "Schuko", - "powerSocketTypes": "Type J" + "powerSocketTypes": "Type J", + "timeZoneDiffers": false, + "timeZoneName": "Central European Standard Time" }, "rangeType": 0, "sectionHeader": "Sunday, 10 Sep 2017", "type": 5 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "airplaneSeat": "15F", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LX" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.464698791503906, "longitude": 8.549169540405273 }, "iataCode": "ZRH", "name": "Zürich" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T08:15:00+02:00", "timezone": "Europe/Zurich" }, "boardingTime": { "@type": "QDateTime", "@value": "2017-09-10T06:15:00+02:00", "timezone": "Europe/Berlin" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Berlin Tegel" }, "departureDay": "2017-09-10", "departureGate": "A10", "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "flightNumber": "963" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 6 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "7", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T14:02:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-10", "departurePlatform": "3", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.45029830932617, "longitude": 8.562219619750977 }, "identifier": "ibnr:8503016", "name": "Zürich Flughafen" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T11:40:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "IC", "trainNumber": "816" }, "reservedTicket": { "@type": "Ticket", "ticketToken": "aztecCode:i0CVXXX007123456789xxxx01/01/1970xxxxxxxxxxxxxxx24/090011223344556677889 DOE JOHN 00000", "ticketedSeat": { "@type": "Seat", "seatNumber": "62", "seatSection": "17" } } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "identifier": "ibnr:8501687", "name": "Randa" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T14:53:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-10", "departurePlatform": "3", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T14:08:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "R", "trainNumber": "241" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TaxiReservation", "modifiedTime": "2020-01-22T00:00:00", "pickupLocation": { "@type": "Place", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "name": "Randa Bahnhof" }, "pickupTime": { "@type": "QDateTime", "@value": "2017-09-10T14:55:00+02:00", "timezone": "Europe/Zurich" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 0 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "EventReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Event", "location": { "@type": "Place", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa" }, "name": "KDE Randa Meeting 2017", "startDate": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" } }, "underName": { "@type": "Person", "name": "Dr Konqui" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 12 }, { "isToday": false, "rangeType": 1, "reservations": [ { "@context": "http://schema.org", "@type": "LodgingReservation", "checkinTime": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" }, "checkoutTime": { "@type": "QDateTime", "@value": "2017-09-15T10:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "LodgingBusiness", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa", "url": "https://randa-meetings.ch/" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 13 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "BusReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "BusTrip", "arrivalBusStop": { "@type": "BusStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.0242805480957, "longitude": 7.748660087585449 }, "name": "Zermatt" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-13T14:20:00+02:00", "timezone": "Europe/Zurich" }, "busName": "", "busNumber": "Zermatt Taxi", "departureBusStop": { "@type": "BusStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "name": "Randa" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-13T14:00:00+02:00", "timezone": "Europe/Zurich" } } } ], "sectionHeader": "Wednesday, 13 Sep 2017", "type": 9 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TouristAttractionVisit", "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-13T14:30:00+02:00", "timezone": "Europe/Zurich" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-13T15:30:00+02:00", "timezone": "Europe/Zurich" }, "touristAttraction": { "@type": "TouristAttraction", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Zermatt" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.01504898071289, "longitude": 7.742239952087402 }, "name": "Matterhorn" } } ], "sectionHeader": "Wednesday, 13 Sep 2017", "type": 11 }, { "isToday": true, "isTodayEmpty": false, "rangeType": 0, "sectionHeader": "Today", "type": 1 }, { "isToday": true, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FoodEstablishmentReservation", "endTime": { "@type": "QDateTime", "@value": "2017-09-14T22:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "partySize": 20, "reservationFor": { "@type": "FoodEstablishment", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Raclette" }, "startTime": { "@type": "QDateTime", "@value": "2017-09-14T19:00:00+02:00", "timezone": "Europe/Zurich" } } ], "sectionHeader": "Today", "type": 10 }, { "isToday": false, "rangeType": 2, "reservations": [ { "@context": "http://schema.org", "@type": "LodgingReservation", "checkinTime": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" }, "checkoutTime": { "@type": "QDateTime", "@value": "2017-09-15T10:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "LodgingBusiness", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa", "url": "https://randa-meetings.ch/" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 13 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "3", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T15:46:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-15", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "identifier": "ibnr:8501687", "name": "Randa" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T14:54:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "R", "trainNumber": "250" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "2", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.45029830932617, "longitude": 8.562219619750977 }, "identifier": "ibnr:8503016", "name": "Zürich Flughafen" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T18:16:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-15", "departurePlatform": "2", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T15:57:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "IC", "trainNumber": "827" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "airplaneSeat": "10E", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LX" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Berlin Tegel" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "boardingTime": { "@type": "QDateTime", "@value": "2017-09-15T20:25:00+02:00", "timezone": "Europe/Zurich" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.464698791503906, "longitude": 8.549169540405273 }, "iataCode": "ZRH", "name": "Zürich" }, "departureDay": "2017-09-15", "departureGate": "52", "departureTerminal": "AB", "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T20:50:00+02:00", "timezone": "Europe/Zurich" }, "flightNumber": "962" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 6 }, { "isToday": false, "rangeType": 2, "sectionHeader": "Friday, 15 Sep 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "name": "Randa (September 2017)" }, "type": 2 } ] diff --git a/autotests/data/tripgroupproxy/expand-collapse-r0.model b/autotests/data/tripgroupproxy/expand-collapse-r0.model index 3152dd4..9bf0117 100644 --- a/autotests/data/tripgroupproxy/expand-collapse-r0.model +++ b/autotests/data/tripgroupproxy/expand-collapse-r0.model @@ -1,1380 +1,1404 @@ [ { "isToday": true, "isTodayEmpty": true, "rangeType": 0, "sectionHeader": "Today", "type": 1 }, { "isToday": false, "rangeType": 1, "sectionHeader": "Saturday, 1 Jan 2000", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2000-01-01T13:00:00+01:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2000-01-01T16:20:00+01:00", "timezone": "Europe/Rome" }, "name": "Peretola (January 2000)" }, "type": 2 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LH", "name": "Lufthansa" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 48.35390090942383, "longitude": 11.786100387573242 }, "iataCode": "MUC", "name": "Franz Josef Strauss" }, "arrivalTime": { "@type": "QDateTime", "@value": "2000-01-01T14:10:00+01:00", "timezone": "Europe/Berlin" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Tegel" }, "departureDay": "2000-01-01", "departureTime": { "@type": "QDateTime", "@value": "2000-01-01T13:00:00+01:00", "timezone": "Europe/Berlin" }, "flightNumber": "2037" }, "reservationNumber": "XXX007", "underName": { "@type": "Person", "name": "Traveler One" } }, { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LH", "name": "Lufthansa" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 48.35390090942383, "longitude": 11.786100387573242 }, "iataCode": "MUC", "name": "Franz Josef Strauss" }, "arrivalTime": { "@type": "QDateTime", "@value": "2000-01-01T14:10:00+01:00", "timezone": "Europe/Berlin" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Tegel" }, "departureDay": "2000-01-01", "departureTime": { "@type": "QDateTime", "@value": "2000-01-01T13:00:00+01:00", "timezone": "Europe/Berlin" }, "flightNumber": "2037" }, "reservationNumber": "XXX007", "underName": { "@type": "Person", "name": "Traveler Two" } } ], "sectionHeader": "Saturday, 1 Jan 2000", "type": 6 }, { "isToday": false, "locationInformation": { "@context": "http://schema.org", "@type": "LocationInformation", "drivingSide": "Right", "drivingSideDiffers": false, "isoCode": "IT", "powerPlugCompatibility": "PartiallyCompatible", - "powerSocketTypes": "Type L" + "powerSocketTypes": "Type L", + "timeZoneDiffers": false, + "timeZoneName": "Central European Standard Time" }, "rangeType": 0, "sectionHeader": "Saturday, 1 Jan 2000", "type": 5 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LH", "name": "Lufthansa" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "IT" }, "geo": { "@type": "GeoCoordinates", "latitude": 43.808799743652344, "longitude": 11.202899932861328 }, "iataCode": "FLR", "name": "Peretola" }, "arrivalTime": { "@type": "QDateTime", "@value": "2000-01-01T16:20:00+01:00", "timezone": "Europe/Rome" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 48.35390090942383, "longitude": 11.786100387573242 }, "iataCode": "MUC", "name": "Franz Josef Strauss" }, "departureDay": "2000-01-01", "departureTime": { "@type": "QDateTime", "@value": "2000-01-01T15:05:00+01:00", "timezone": "Europe/Berlin" }, "flightNumber": "9440" }, "reservationNumber": "XXX007", "underName": { "@type": "Person", "name": "Traveler One" } }, { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LH", "name": "Lufthansa" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "IT" }, "geo": { "@type": "GeoCoordinates", "latitude": 43.808799743652344, "longitude": 11.202899932861328 }, "iataCode": "FLR", "name": "Peretola" }, "arrivalTime": { "@type": "QDateTime", "@value": "2000-01-01T16:20:00+01:00", "timezone": "Europe/Rome" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 48.35390090942383, "longitude": 11.786100387573242 }, "iataCode": "MUC", "name": "Franz Josef Strauss" }, "departureDay": "2000-01-01", "departureTime": { "@type": "QDateTime", "@value": "2000-01-01T15:05:00+01:00", "timezone": "Europe/Berlin" }, "flightNumber": "9440" }, "reservationNumber": "XXX007", "underName": { "@type": "Person", "name": "Traveler Two" } } ], "sectionHeader": "Saturday, 1 Jan 2000", "type": 6 }, { "isToday": false, "rangeType": 2, "sectionHeader": "Saturday, 1 Jan 2000", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2000-01-01T13:00:00+01:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2000-01-01T16:20:00+01:00", "timezone": "Europe/Rome" }, "name": "Peretola (January 2000)" }, "type": 2 }, { "isToday": false, "rangeType": 1, "sectionHeader": "Saturday, 4 Mar 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-03-04T11:00:00-05:00", "timezone": "America/New_York" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-03-05T15:15:00-08:00", "timezone": "America/Los_Angeles" }, "name": "San Francisco Airport (March 2017)" }, "type": 2 }, { "isToday": false, "locationInformation": { "@context": "http://schema.org", "@type": "LocationInformation", "drivingSide": "Right", "drivingSideDiffers": false, "isoCode": "US", "powerPlugCompatibility": "Incompatible", "powerPlugTypes": "Europlug, Schuko", - "powerSocketTypes": "Type A, Type B" + "powerSocketTypes": "Type A, Type B", + "timeZoneDiffers": true, + "timeZoneName": "Central Standard Time" }, "rangeType": 0, "sectionHeader": "Saturday, 4 Mar 2017", "type": 5 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "potentialAction": [ { "@type": "CheckInAction", "target": "http://united.com/onlinecheckin.html" } ], "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "UA", "name": "United" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 41.978599548339844, "longitude": -87.90470123291016 }, "iataCode": "ORD", "name": "O'Hare International Airport" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-03-05T13:25:00-06:00", "timezone": "America/Chicago" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 40.63970184326172, "longitude": -73.77890014648438 }, "iataCode": "JFK", "name": "John F. Kennedy International Airport" }, "departureDay": "2017-03-04", "departureTime": { "@type": "QDateTime", "@value": "2017-03-04T11:00:00-05:00", "timezone": "America/New_York" }, "flightNumber": "201" }, "reservationNumber": "RXJ34P", "underName": { "@type": "Person", "name": "Eva Green" } }, { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "potentialAction": [ { "@type": "CheckInAction", "target": "http://united.com/onlinecheckin.html" } ], "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "UA", "name": "United" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 41.978599548339844, "longitude": -87.90470123291016 }, "iataCode": "ORD", "name": "O'Hare International Airport" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-03-05T13:25:00-06:00", "timezone": "America/Chicago" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 40.63970184326172, "longitude": -73.77890014648438 }, "iataCode": "JFK", "name": "John F. Kennedy International Airport" }, "departureDay": "2017-03-04", "departureTime": { "@type": "QDateTime", "@value": "2017-03-04T11:00:00-05:00", "timezone": "America/New_York" }, "flightNumber": "201" }, "reservationNumber": "RXJ34P", "underName": { "@type": "Person", "name": "John Green" } } ], "sectionHeader": "Saturday, 4 Mar 2017", "type": 6 }, + { + "isToday": false, + "locationInformation": { + "@context": "http://schema.org", + "@type": "LocationInformation", + "drivingSide": "Right", + "drivingSideDiffers": false, + "isoCode": "US", + "powerPlugCompatibility": "Incompatible", + "powerPlugTypes": "Europlug, Schuko", + "powerSocketTypes": "Type A, Type B", + "timeZoneDiffers": true, + "timeZoneName": "Pacific Standard Time" + }, + "rangeType": 0, + "sectionHeader": "Sunday, 5 Mar 2017", + "type": 5 + }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "potentialAction": [ { "@type": "CheckInAction", "target": "http://united.com/onlinecheckin.html" } ], "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "UA", "name": "United" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 37.618900299072266, "longitude": -122.375 }, "iataCode": "SFO", "name": "San Francisco Airport" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-03-05T15:15:00-08:00", "timezone": "America/Los_Angeles" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 41.978599548339844, "longitude": -87.90470123291016 }, "iataCode": "ORD", "name": "O'Hare International Airport" }, "departureDay": "2017-03-05", "departureTime": { "@type": "QDateTime", "@value": "2017-03-05T14:55:00-06:00", "timezone": "America/Chicago" }, "flightNumber": "1050" }, "reservationNumber": "RXJ34P", "underName": { "@type": "Person", "name": "Eva Green" } }, { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "potentialAction": [ { "@type": "CheckInAction", "target": "http://united.com/onlinecheckin.html" } ], "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "UA", "name": "United" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 37.618900299072266, "longitude": -122.375 }, "iataCode": "SFO", "name": "San Francisco Airport" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-03-05T15:15:00-08:00", "timezone": "America/Los_Angeles" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 41.978599548339844, "longitude": -87.90470123291016 }, "iataCode": "ORD", "name": "O'Hare International Airport" }, "departureDay": "2017-03-05", "departureTime": { "@type": "QDateTime", "@value": "2017-03-05T14:55:00-06:00", "timezone": "America/Chicago" }, "flightNumber": "1050" }, "reservationNumber": "RXJ34P", "underName": { "@type": "Person", "name": "John Green" } } ], "sectionHeader": "Sunday, 5 Mar 2017", "type": 6 }, { "isToday": false, "rangeType": 2, "sectionHeader": "Sunday, 5 Mar 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-03-04T11:00:00-05:00", "timezone": "America/New_York" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-03-05T15:15:00-08:00", "timezone": "America/Los_Angeles" }, "name": "San Francisco Airport (March 2017)" }, "type": 2 }, { "isToday": false, "rangeType": 1, "sectionHeader": "Sunday, 10 Sep 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "name": "Randa (September 2017)" }, "type": 2 }, { "isToday": false, "locationInformation": { "@context": "http://schema.org", "@type": "LocationInformation", "drivingSide": "Right", "drivingSideDiffers": false, "isoCode": "CH", "powerPlugCompatibility": "PartiallyCompatible", "powerPlugTypes": "Schuko", - "powerSocketTypes": "Type J" + "powerSocketTypes": "Type J", + "timeZoneDiffers": true, + "timeZoneName": "Central European Standard Time" }, "rangeType": 0, "sectionHeader": "Sunday, 10 Sep 2017", "type": 5 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "airplaneSeat": "15F", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LX" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.464698791503906, "longitude": 8.549169540405273 }, "iataCode": "ZRH", "name": "Zürich" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T08:15:00+02:00", "timezone": "Europe/Zurich" }, "boardingTime": { "@type": "QDateTime", "@value": "2017-09-10T06:15:00+02:00", "timezone": "Europe/Berlin" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Berlin Tegel" }, "departureDay": "2017-09-10", "departureGate": "A10", "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "flightNumber": "963" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 6 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "7", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T14:02:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-10", "departurePlatform": "3", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.45029830932617, "longitude": 8.562219619750977 }, "identifier": "ibnr:8503016", "name": "Zürich Flughafen" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T11:40:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "IC", "trainNumber": "816" }, "reservedTicket": { "@type": "Ticket", "ticketToken": "aztecCode:i0CVXXX007123456789xxxx01/01/1970xxxxxxxxxxxxxxx24/090011223344556677889 DOE JOHN 00000", "ticketedSeat": { "@type": "Seat", "seatNumber": "62", "seatSection": "17" } } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "identifier": "ibnr:8501687", "name": "Randa" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T14:53:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-10", "departurePlatform": "3", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T14:08:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "R", "trainNumber": "241" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TaxiReservation", "modifiedTime": "2020-01-22T00:00:00", "pickupLocation": { "@type": "Place", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "name": "Randa Bahnhof" }, "pickupTime": { "@type": "QDateTime", "@value": "2017-09-10T14:55:00+02:00", "timezone": "Europe/Zurich" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 0 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "EventReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Event", "location": { "@type": "Place", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa" }, "name": "KDE Randa Meeting 2017", "startDate": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" } }, "underName": { "@type": "Person", "name": "Dr Konqui" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 12 }, { "isToday": false, "rangeType": 1, "reservations": [ { "@context": "http://schema.org", "@type": "LodgingReservation", "checkinTime": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" }, "checkoutTime": { "@type": "QDateTime", "@value": "2017-09-15T10:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "LodgingBusiness", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa", "url": "https://randa-meetings.ch/" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 13 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "BusReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "BusTrip", "arrivalBusStop": { "@type": "BusStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.0242805480957, "longitude": 7.748660087585449 }, "name": "Zermatt" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-13T14:20:00+02:00", "timezone": "Europe/Zurich" }, "busName": "", "busNumber": "Zermatt Taxi", "departureBusStop": { "@type": "BusStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "name": "Randa" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-13T14:00:00+02:00", "timezone": "Europe/Zurich" } } } ], "sectionHeader": "Wednesday, 13 Sep 2017", "type": 9 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TouristAttractionVisit", "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-13T14:30:00+02:00", "timezone": "Europe/Zurich" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-13T15:30:00+02:00", "timezone": "Europe/Zurich" }, "touristAttraction": { "@type": "TouristAttraction", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Zermatt" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.01504898071289, "longitude": 7.742239952087402 }, "name": "Matterhorn" } } ], "sectionHeader": "Wednesday, 13 Sep 2017", "type": 11 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FoodEstablishmentReservation", "endTime": { "@type": "QDateTime", "@value": "2017-09-14T22:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "partySize": 20, "reservationFor": { "@type": "FoodEstablishment", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Raclette" }, "startTime": { "@type": "QDateTime", "@value": "2017-09-14T19:00:00+02:00", "timezone": "Europe/Zurich" } } ], "sectionHeader": "Thursday, 14 Sep 2017", "type": 10 }, { "isToday": false, "rangeType": 2, "reservations": [ { "@context": "http://schema.org", "@type": "LodgingReservation", "checkinTime": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" }, "checkoutTime": { "@type": "QDateTime", "@value": "2017-09-15T10:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "LodgingBusiness", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa", "url": "https://randa-meetings.ch/" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 13 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "3", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T15:46:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-15", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "identifier": "ibnr:8501687", "name": "Randa" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T14:54:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "R", "trainNumber": "250" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "2", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.45029830932617, "longitude": 8.562219619750977 }, "identifier": "ibnr:8503016", "name": "Zürich Flughafen" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T18:16:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-15", "departurePlatform": "2", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T15:57:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "IC", "trainNumber": "827" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "airplaneSeat": "10E", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LX" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Berlin Tegel" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "boardingTime": { "@type": "QDateTime", "@value": "2017-09-15T20:25:00+02:00", "timezone": "Europe/Zurich" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.464698791503906, "longitude": 8.549169540405273 }, "iataCode": "ZRH", "name": "Zürich" }, "departureDay": "2017-09-15", "departureGate": "52", "departureTerminal": "AB", "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T20:50:00+02:00", "timezone": "Europe/Zurich" }, "flightNumber": "962" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 6 }, { "isToday": false, "rangeType": 2, "sectionHeader": "Friday, 15 Sep 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "name": "Randa (September 2017)" }, "type": 2 } ] diff --git a/autotests/data/tripgroupproxy/expand-collapse-r1.model b/autotests/data/tripgroupproxy/expand-collapse-r1.model index 618c52c..2cdbd5a 100644 --- a/autotests/data/tripgroupproxy/expand-collapse-r1.model +++ b/autotests/data/tripgroupproxy/expand-collapse-r1.model @@ -1,1096 +1,1118 @@ [ { "isToday": true, "isTodayEmpty": true, "rangeType": 0, "sectionHeader": "Today", "type": 1 }, { "isToday": false, "rangeType": 0, "sectionHeader": "Saturday, 1 Jan 2000", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2000-01-01T13:00:00+01:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2000-01-01T16:20:00+01:00", "timezone": "Europe/Rome" }, "name": "Peretola (January 2000)" }, "type": 2 }, { "isToday": false, "rangeType": 1, "sectionHeader": "Saturday, 4 Mar 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-03-04T11:00:00-05:00", "timezone": "America/New_York" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-03-05T15:15:00-08:00", "timezone": "America/Los_Angeles" }, "name": "San Francisco Airport (March 2017)" }, "type": 2 }, { "isToday": false, "locationInformation": { "@context": "http://schema.org", "@type": "LocationInformation", "drivingSide": "Right", "drivingSideDiffers": false, "isoCode": "US", "powerPlugCompatibility": "Incompatible", "powerPlugTypes": "Europlug, Schuko", - "powerSocketTypes": "Type A, Type B" + "powerSocketTypes": "Type A, Type B", + "timeZoneDiffers": true, + "timeZoneName": "Central Standard Time" }, "rangeType": 0, "sectionHeader": "Saturday, 4 Mar 2017", "type": 5 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "potentialAction": [ { "@type": "CheckInAction", "target": "http://united.com/onlinecheckin.html" } ], "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "UA", "name": "United" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 41.978599548339844, "longitude": -87.90470123291016 }, "iataCode": "ORD", "name": "O'Hare International Airport" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-03-05T13:25:00-06:00", "timezone": "America/Chicago" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 40.63970184326172, "longitude": -73.77890014648438 }, "iataCode": "JFK", "name": "John F. Kennedy International Airport" }, "departureDay": "2017-03-04", "departureTime": { "@type": "QDateTime", "@value": "2017-03-04T11:00:00-05:00", "timezone": "America/New_York" }, "flightNumber": "201" }, "reservationNumber": "RXJ34P", "underName": { "@type": "Person", "name": "Eva Green" } }, { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "potentialAction": [ { "@type": "CheckInAction", "target": "http://united.com/onlinecheckin.html" } ], "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "UA", "name": "United" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 41.978599548339844, "longitude": -87.90470123291016 }, "iataCode": "ORD", "name": "O'Hare International Airport" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-03-05T13:25:00-06:00", "timezone": "America/Chicago" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 40.63970184326172, "longitude": -73.77890014648438 }, "iataCode": "JFK", "name": "John F. Kennedy International Airport" }, "departureDay": "2017-03-04", "departureTime": { "@type": "QDateTime", "@value": "2017-03-04T11:00:00-05:00", "timezone": "America/New_York" }, "flightNumber": "201" }, "reservationNumber": "RXJ34P", "underName": { "@type": "Person", "name": "John Green" } } ], "sectionHeader": "Saturday, 4 Mar 2017", "type": 6 }, + { + "isToday": false, + "locationInformation": { + "@context": "http://schema.org", + "@type": "LocationInformation", + "drivingSide": "Right", + "drivingSideDiffers": false, + "isoCode": "US", + "powerPlugCompatibility": "Incompatible", + "powerPlugTypes": "Europlug, Schuko", + "powerSocketTypes": "Type A, Type B", + "timeZoneDiffers": true, + "timeZoneName": "Pacific Standard Time" + }, + "rangeType": 0, + "sectionHeader": "Sunday, 5 Mar 2017", + "type": 5 + }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "potentialAction": [ { "@type": "CheckInAction", "target": "http://united.com/onlinecheckin.html" } ], "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "UA", "name": "United" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 37.618900299072266, "longitude": -122.375 }, "iataCode": "SFO", "name": "San Francisco Airport" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-03-05T15:15:00-08:00", "timezone": "America/Los_Angeles" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 41.978599548339844, "longitude": -87.90470123291016 }, "iataCode": "ORD", "name": "O'Hare International Airport" }, "departureDay": "2017-03-05", "departureTime": { "@type": "QDateTime", "@value": "2017-03-05T14:55:00-06:00", "timezone": "America/Chicago" }, "flightNumber": "1050" }, "reservationNumber": "RXJ34P", "underName": { "@type": "Person", "name": "Eva Green" } }, { "@context": "http://schema.org", "@type": "FlightReservation", "modifiedTime": "2020-01-22T00:00:00", "potentialAction": [ { "@type": "CheckInAction", "target": "http://united.com/onlinecheckin.html" } ], "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "UA", "name": "United" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 37.618900299072266, "longitude": -122.375 }, "iataCode": "SFO", "name": "San Francisco Airport" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-03-05T15:15:00-08:00", "timezone": "America/Los_Angeles" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "US" }, "geo": { "@type": "GeoCoordinates", "latitude": 41.978599548339844, "longitude": -87.90470123291016 }, "iataCode": "ORD", "name": "O'Hare International Airport" }, "departureDay": "2017-03-05", "departureTime": { "@type": "QDateTime", "@value": "2017-03-05T14:55:00-06:00", "timezone": "America/Chicago" }, "flightNumber": "1050" }, "reservationNumber": "RXJ34P", "underName": { "@type": "Person", "name": "John Green" } } ], "sectionHeader": "Sunday, 5 Mar 2017", "type": 6 }, { "isToday": false, "rangeType": 2, "sectionHeader": "Sunday, 5 Mar 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-03-04T11:00:00-05:00", "timezone": "America/New_York" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-03-05T15:15:00-08:00", "timezone": "America/Los_Angeles" }, "name": "San Francisco Airport (March 2017)" }, "type": 2 }, { "isToday": false, "rangeType": 1, "sectionHeader": "Sunday, 10 Sep 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "name": "Randa (September 2017)" }, "type": 2 }, { "isToday": false, "locationInformation": { "@context": "http://schema.org", "@type": "LocationInformation", "drivingSide": "Right", "drivingSideDiffers": false, "isoCode": "CH", "powerPlugCompatibility": "PartiallyCompatible", "powerPlugTypes": "Schuko", - "powerSocketTypes": "Type J" + "powerSocketTypes": "Type J", + "timeZoneDiffers": true, + "timeZoneName": "Central European Standard Time" }, "rangeType": 0, "sectionHeader": "Sunday, 10 Sep 2017", "type": 5 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "airplaneSeat": "15F", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LX" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.464698791503906, "longitude": 8.549169540405273 }, "iataCode": "ZRH", "name": "Zürich" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T08:15:00+02:00", "timezone": "Europe/Zurich" }, "boardingTime": { "@type": "QDateTime", "@value": "2017-09-10T06:15:00+02:00", "timezone": "Europe/Berlin" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Berlin Tegel" }, "departureDay": "2017-09-10", "departureGate": "A10", "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "flightNumber": "963" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 6 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "7", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T14:02:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-10", "departurePlatform": "3", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.45029830932617, "longitude": 8.562219619750977 }, "identifier": "ibnr:8503016", "name": "Zürich Flughafen" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T11:40:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "IC", "trainNumber": "816" }, "reservedTicket": { "@type": "Ticket", "ticketToken": "aztecCode:i0CVXXX007123456789xxxx01/01/1970xxxxxxxxxxxxxxx24/090011223344556677889 DOE JOHN 00000", "ticketedSeat": { "@type": "Seat", "seatNumber": "62", "seatSection": "17" } } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "identifier": "ibnr:8501687", "name": "Randa" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T14:53:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-10", "departurePlatform": "3", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T14:08:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "R", "trainNumber": "241" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TaxiReservation", "modifiedTime": "2020-01-22T00:00:00", "pickupLocation": { "@type": "Place", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "name": "Randa Bahnhof" }, "pickupTime": { "@type": "QDateTime", "@value": "2017-09-10T14:55:00+02:00", "timezone": "Europe/Zurich" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 0 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "EventReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Event", "location": { "@type": "Place", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa" }, "name": "KDE Randa Meeting 2017", "startDate": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" } }, "underName": { "@type": "Person", "name": "Dr Konqui" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 12 }, { "isToday": false, "rangeType": 1, "reservations": [ { "@context": "http://schema.org", "@type": "LodgingReservation", "checkinTime": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" }, "checkoutTime": { "@type": "QDateTime", "@value": "2017-09-15T10:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "LodgingBusiness", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa", "url": "https://randa-meetings.ch/" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 13 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "BusReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "BusTrip", "arrivalBusStop": { "@type": "BusStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.0242805480957, "longitude": 7.748660087585449 }, "name": "Zermatt" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-13T14:20:00+02:00", "timezone": "Europe/Zurich" }, "busName": "", "busNumber": "Zermatt Taxi", "departureBusStop": { "@type": "BusStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "name": "Randa" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-13T14:00:00+02:00", "timezone": "Europe/Zurich" } } } ], "sectionHeader": "Wednesday, 13 Sep 2017", "type": 9 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TouristAttractionVisit", "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-13T14:30:00+02:00", "timezone": "Europe/Zurich" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-13T15:30:00+02:00", "timezone": "Europe/Zurich" }, "touristAttraction": { "@type": "TouristAttraction", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Zermatt" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.01504898071289, "longitude": 7.742239952087402 }, "name": "Matterhorn" } } ], "sectionHeader": "Wednesday, 13 Sep 2017", "type": 11 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FoodEstablishmentReservation", "endTime": { "@type": "QDateTime", "@value": "2017-09-14T22:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "partySize": 20, "reservationFor": { "@type": "FoodEstablishment", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Raclette" }, "startTime": { "@type": "QDateTime", "@value": "2017-09-14T19:00:00+02:00", "timezone": "Europe/Zurich" } } ], "sectionHeader": "Thursday, 14 Sep 2017", "type": 10 }, { "isToday": false, "rangeType": 2, "reservations": [ { "@context": "http://schema.org", "@type": "LodgingReservation", "checkinTime": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" }, "checkoutTime": { "@type": "QDateTime", "@value": "2017-09-15T10:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "LodgingBusiness", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa", "url": "https://randa-meetings.ch/" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 13 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "3", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T15:46:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-15", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "identifier": "ibnr:8501687", "name": "Randa" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T14:54:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "R", "trainNumber": "250" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "2", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.45029830932617, "longitude": 8.562219619750977 }, "identifier": "ibnr:8503016", "name": "Zürich Flughafen" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T18:16:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-15", "departurePlatform": "2", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T15:57:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "IC", "trainNumber": "827" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "airplaneSeat": "10E", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LX" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Berlin Tegel" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "boardingTime": { "@type": "QDateTime", "@value": "2017-09-15T20:25:00+02:00", "timezone": "Europe/Zurich" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.464698791503906, "longitude": 8.549169540405273 }, "iataCode": "ZRH", "name": "Zürich" }, "departureDay": "2017-09-15", "departureGate": "52", "departureTerminal": "AB", "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T20:50:00+02:00", "timezone": "Europe/Zurich" }, "flightNumber": "962" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 6 }, { "isToday": false, "rangeType": 2, "sectionHeader": "Friday, 15 Sep 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "name": "Randa (September 2017)" }, "type": 2 } ] diff --git a/autotests/data/tripgroupproxy/expand-collapse-r2.model b/autotests/data/tripgroupproxy/expand-collapse-r2.model index a07c0f3..e30f5ef 100644 --- a/autotests/data/tripgroupproxy/expand-collapse-r2.model +++ b/autotests/data/tripgroupproxy/expand-collapse-r2.model @@ -1,787 +1,789 @@ [ { "isToday": true, "isTodayEmpty": true, "rangeType": 0, "sectionHeader": "Today", "type": 1 }, { "isToday": false, "rangeType": 0, "sectionHeader": "Saturday, 1 Jan 2000", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2000-01-01T13:00:00+01:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2000-01-01T16:20:00+01:00", "timezone": "Europe/Rome" }, "name": "Peretola (January 2000)" }, "type": 2 }, { "isToday": false, "rangeType": 0, "sectionHeader": "Saturday, 4 Mar 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-03-04T11:00:00-05:00", "timezone": "America/New_York" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-03-05T15:15:00-08:00", "timezone": "America/Los_Angeles" }, "name": "San Francisco Airport (March 2017)" }, "type": 2 }, { "isToday": false, "rangeType": 1, "sectionHeader": "Sunday, 10 Sep 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "name": "Randa (September 2017)" }, "type": 2 }, { "isToday": false, "locationInformation": { "@context": "http://schema.org", "@type": "LocationInformation", "drivingSide": "Right", "drivingSideDiffers": false, "isoCode": "CH", "powerPlugCompatibility": "PartiallyCompatible", "powerPlugTypes": "Schuko", - "powerSocketTypes": "Type J" + "powerSocketTypes": "Type J", + "timeZoneDiffers": true, + "timeZoneName": "Central European Standard Time" }, "rangeType": 0, "sectionHeader": "Sunday, 10 Sep 2017", "type": 5 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "airplaneSeat": "15F", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LX" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.464698791503906, "longitude": 8.549169540405273 }, "iataCode": "ZRH", "name": "Zürich" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T08:15:00+02:00", "timezone": "Europe/Zurich" }, "boardingTime": { "@type": "QDateTime", "@value": "2017-09-10T06:15:00+02:00", "timezone": "Europe/Berlin" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Berlin Tegel" }, "departureDay": "2017-09-10", "departureGate": "A10", "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "flightNumber": "963" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 6 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "7", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T14:02:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-10", "departurePlatform": "3", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.45029830932617, "longitude": 8.562219619750977 }, "identifier": "ibnr:8503016", "name": "Zürich Flughafen" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T11:40:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "IC", "trainNumber": "816" }, "reservedTicket": { "@type": "Ticket", "ticketToken": "aztecCode:i0CVXXX007123456789xxxx01/01/1970xxxxxxxxxxxxxxx24/090011223344556677889 DOE JOHN 00000", "ticketedSeat": { "@type": "Seat", "seatNumber": "62", "seatSection": "17" } } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "identifier": "ibnr:8501687", "name": "Randa" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-10T14:53:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-10", "departurePlatform": "3", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-10T14:08:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "R", "trainNumber": "241" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TaxiReservation", "modifiedTime": "2020-01-22T00:00:00", "pickupLocation": { "@type": "Place", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "name": "Randa Bahnhof" }, "pickupTime": { "@type": "QDateTime", "@value": "2017-09-10T14:55:00+02:00", "timezone": "Europe/Zurich" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 0 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "EventReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Event", "location": { "@type": "Place", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa" }, "name": "KDE Randa Meeting 2017", "startDate": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" } }, "underName": { "@type": "Person", "name": "Dr Konqui" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 12 }, { "isToday": false, "rangeType": 1, "reservations": [ { "@context": "http://schema.org", "@type": "LodgingReservation", "checkinTime": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" }, "checkoutTime": { "@type": "QDateTime", "@value": "2017-09-15T10:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "LodgingBusiness", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa", "url": "https://randa-meetings.ch/" } } ], "sectionHeader": "Sunday, 10 Sep 2017", "type": 13 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "BusReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "BusTrip", "arrivalBusStop": { "@type": "BusStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.0242805480957, "longitude": 7.748660087585449 }, "name": "Zermatt" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-13T14:20:00+02:00", "timezone": "Europe/Zurich" }, "busName": "", "busNumber": "Zermatt Taxi", "departureBusStop": { "@type": "BusStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "name": "Randa" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-13T14:00:00+02:00", "timezone": "Europe/Zurich" } } } ], "sectionHeader": "Wednesday, 13 Sep 2017", "type": 9 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TouristAttractionVisit", "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-13T14:30:00+02:00", "timezone": "Europe/Zurich" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-13T15:30:00+02:00", "timezone": "Europe/Zurich" }, "touristAttraction": { "@type": "TouristAttraction", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Zermatt" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.01504898071289, "longitude": 7.742239952087402 }, "name": "Matterhorn" } } ], "sectionHeader": "Wednesday, 13 Sep 2017", "type": 11 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FoodEstablishmentReservation", "endTime": { "@type": "QDateTime", "@value": "2017-09-14T22:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "partySize": 20, "reservationFor": { "@type": "FoodEstablishment", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Raclette" }, "startTime": { "@type": "QDateTime", "@value": "2017-09-14T19:00:00+02:00", "timezone": "Europe/Zurich" } } ], "sectionHeader": "Thursday, 14 Sep 2017", "type": 10 }, { "isToday": false, "rangeType": 2, "reservations": [ { "@context": "http://schema.org", "@type": "LodgingReservation", "checkinTime": { "@type": "QDateTime", "@value": "2017-09-10T15:00:00+02:00", "timezone": "Europe/Zurich" }, "checkoutTime": { "@type": "QDateTime", "@value": "2017-09-15T10:00:00+02:00", "timezone": "Europe/Zurich" }, "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "LodgingBusiness", "address": { "@type": "PostalAddress", "addressCountry": "CH", "addressLocality": "Randa", "addressRegion": "Wallis", "postalCode": "3928", "streetAddress": "Haus Maria am Weg" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.099029541015625, "longitude": 7.783259868621826 }, "name": "Haus Randa", "url": "https://randa-meetings.ch/" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 13 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "3", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T15:46:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-15", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.09989929199219, "longitude": 7.781469821929932 }, "identifier": "ibnr:8501687", "name": "Randa" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T14:54:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "R", "trainNumber": "250" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "TrainReservation", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "TrainTrip", "arrivalPlatform": "2", "arrivalStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.45029830932617, "longitude": 8.562219619750977 }, "identifier": "ibnr:8503016", "name": "Zürich Flughafen" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T18:16:00+02:00", "timezone": "Europe/Zurich" }, "departureDay": "2017-09-15", "departurePlatform": "2", "departureStation": { "@type": "TrainStation", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 46.29399871826172, "longitude": 7.881460189819336 }, "identifier": "ibnr:8501605", "name": "Visp" }, "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T15:57:00+02:00", "timezone": "Europe/Zurich" }, "provider": { "@type": "Organization", "name": "SBB" }, "trainName": "IC", "trainNumber": "827" } } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 7 }, { "isToday": false, "rangeType": 0, "reservations": [ { "@context": "http://schema.org", "@type": "FlightReservation", "airplaneSeat": "10E", "modifiedTime": "2020-01-22T00:00:00", "reservationFor": { "@type": "Flight", "airline": { "@type": "Airline", "iataCode": "LX" }, "arrivalAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "DE" }, "geo": { "@type": "GeoCoordinates", "latitude": 52.55970001220703, "longitude": 13.287799835205078 }, "iataCode": "TXL", "name": "Berlin Tegel" }, "arrivalTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "boardingTime": { "@type": "QDateTime", "@value": "2017-09-15T20:25:00+02:00", "timezone": "Europe/Zurich" }, "departureAirport": { "@type": "Airport", "address": { "@type": "PostalAddress", "addressCountry": "CH" }, "geo": { "@type": "GeoCoordinates", "latitude": 47.464698791503906, "longitude": 8.549169540405273 }, "iataCode": "ZRH", "name": "Zürich" }, "departureDay": "2017-09-15", "departureGate": "52", "departureTerminal": "AB", "departureTime": { "@type": "QDateTime", "@value": "2017-09-15T20:50:00+02:00", "timezone": "Europe/Zurich" }, "flightNumber": "962" }, "reservationNumber": "XXX007" } ], "sectionHeader": "Friday, 15 Sep 2017", "type": 6 }, { "isToday": false, "rangeType": 2, "sectionHeader": "Friday, 15 Sep 2017", "tripGroup": { "@context": "http://schema.org", "@type": "TripGroup", "beginDateTime": { "@type": "QDateTime", "@value": "2017-09-10T06:45:00+02:00", "timezone": "Europe/Berlin" }, "endDateTime": { "@type": "QDateTime", "@value": "2017-09-15T22:15:00+02:00", "timezone": "Europe/Berlin" }, "name": "Randa (September 2017)" }, "type": 2 } ] diff --git a/autotests/locationinformationtest.cpp b/autotests/locationinformationtest.cpp new file mode 100644 index 0000000..91e6963 --- /dev/null +++ b/autotests/locationinformationtest.cpp @@ -0,0 +1,57 @@ +/* + Copyright (C) 2020 Volker Krause + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include + +#include + +class LocationInformationTest : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void testTzCompare() + { + LocationInformation lhs; + LocationInformation rhs; + QVERIFY(lhs == rhs); + lhs.setTimeZone(QTimeZone("Europe/Berlin")); + QVERIFY(lhs == rhs); + QVERIFY(rhs == lhs); + + rhs.setTimeZone(QTimeZone("Europe/Vilnius")); + QCOMPARE(lhs == rhs, false); + QCOMPARE(rhs == lhs, false); + + rhs.setTimeZone(QTimeZone("Europe/Brussels")); + QCOMPARE(lhs == rhs, true); + QCOMPARE(rhs == lhs, true); + } + + void testTzDiff() + { + LocationInformation l; + l.setTimeZone(QTimeZone("Europe/Berlin")); + QCOMPARE(l.timeZoneDiffers(), false); + l.setTimeZone(QTimeZone("Europe/Vilnius")); + QCOMPARE(l.timeZoneDiffers(), true); + QVERIFY(!l.timeZoneName().isEmpty()); + } +}; + +QTEST_GUILESS_MAIN(LocationInformationTest) + +#include "locationinformationtest.moc" diff --git a/src/app/LocationInfoDelegate.qml b/src/app/LocationInfoDelegate.qml index 06de73a..e35cdb8 100644 --- a/src/app/LocationInfoDelegate.qml +++ b/src/app/LocationInfoDelegate.qml @@ -1,96 +1,104 @@ /* Copyright (C) 2018 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ import QtQuick 2.5 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.1 as QQC2 import org.kde.kirigami 2.4 as Kirigami import org.kde.kitinerary 1.0 as KItinerary import org.kde.itinerary 1.0 import "." as App Kirigami.AbstractCard { id: root property var locationInfo; header: Rectangle { id: headerBackground Kirigami.Theme.colorSet: Kirigami.Theme.Complementary Kirigami.Theme.inherit: false color: Kirigami.Theme.backgroundColor implicitHeight: headerLayout.implicitHeight + Kirigami.Units.largeSpacing * 2 anchors.leftMargin: -root.leftPadding anchors.topMargin: -root.topPadding anchors.rightMargin: -root.rightPadding RowLayout { id: headerLayout anchors.fill: parent anchors.margins: Kirigami.Units.largeSpacing Kirigami.Icon { source: "documentinfo" width: Kirigami.Units.iconSizes.small height: width color: Kirigami.Theme.neutralTextColor isMask: true } QQC2.Label { text: i18n("Entering %1", Localizer.countryName(locationInfo.isoCode)) color: Kirigami.Theme.neutralTextColor Layout.fillWidth: true } } } contentItem: ColumnLayout { id: topLayout QQC2.Label { Layout.fillWidth: true text: locationInfo.drivingSide == KItinerary.KnowledgeDb.DrivingSide.Right ? i18n("People are driving on the right side.") : i18n("People are driving on the wrong side.") color: Kirigami.Theme.negativeTextColor visible: locationInfo.drivingSideDiffers wrapMode: Text.WordWrap } QQC2.Label { Layout.fillWidth: true text: i18n("No compatible power sockets: %1", locationInfo.powerSocketTypes) color: Kirigami.Theme.negativeTextColor visible: locationInfo.powerPlugCompatibility == LocationInformation.Incompatible wrapMode: Text.WordWrap } QQC2.Label { Layout.fillWidth: true text: i18n("Some incompatible power sockets: %1", locationInfo.powerSocketTypes) color: Kirigami.Theme.neutralTextColor visible: locationInfo.powerPlugCompatibility == LocationInformation.PartiallyCompatible && locationInfo.powerSocketTypes != "" wrapMode: Text.WordWrap } QQC2.Label { Layout.fillWidth: true text: i18n("Some incompatible power plugs: %1", locationInfo.powerPlugTypes) color: Kirigami.Theme.neutralTextColor visible: locationInfo.powerPlugCompatibility == LocationInformation.PartiallyCompatible && locationInfo.powerPlugTypes != "" wrapMode: Text.WordWrap } + + QQC2.Label { + Layout.fillWidth: true + text: i18n("Timezone change: %1", locationInfo.timeZoneName) + color: Kirigami.Theme.neutralTextColor + visible: locationInfo.timeZoneDiffers + wrapMode: Text.WordWrap + } } } diff --git a/src/app/locationinformation.cpp b/src/app/locationinformation.cpp index 2463e2e..d783a1a 100644 --- a/src/app/locationinformation.cpp +++ b/src/app/locationinformation.cpp @@ -1,153 +1,181 @@ /* Copyright (C) 2018 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "locationinformation.h" #include #include using namespace KItinerary; -LocationInformation::LocationInformation() -{ -} - +LocationInformation::LocationInformation() = default; LocationInformation::~LocationInformation() = default; bool LocationInformation::operator==(const LocationInformation& other) const { const auto dsEqual = m_drivingSide == other.m_drivingSide || m_drivingSide == KnowledgeDb::DrivingSide::Unknown || other.m_drivingSide == KnowledgeDb::DrivingSide::Unknown; const auto ppEqual = (m_incompatPlugs == other.m_incompatPlugs && m_incompatSockets == other.m_incompatSockets) || m_powerPlugs == KnowledgeDb::Unknown || other.m_powerPlugs == KnowledgeDb::Unknown; - return dsEqual && ppEqual; + return dsEqual && ppEqual && !hasRelevantTimeZoneChange(other); } QString LocationInformation::isoCode() const { return m_isoCode; } void LocationInformation::setIsoCode(const QString& isoCode) { if (m_isoCode == isoCode) { return; } m_isoCode = isoCode; const auto id = KnowledgeDb::CountryId{isoCode}; if (!id.isValid()) { setDrivingSide(KnowledgeDb::DrivingSide::Unknown); setPowerPlugTypes(KnowledgeDb::Unknown); return; } const auto countryRecord = KnowledgeDb::countryForId(id); setDrivingSide(countryRecord.drivingSide); setPowerPlugTypes(countryRecord.powerPlugTypes); } KnowledgeDb::DrivingSide LocationInformation::drivingSide() const { return m_drivingSide; } void LocationInformation::setDrivingSide(KnowledgeDb::DrivingSide drivingSide) { if (m_drivingSide == drivingSide) { return; } if (m_drivingSide != KnowledgeDb::DrivingSide::Unknown) { m_drivingSideDiffers = true; } m_drivingSide = drivingSide; } bool LocationInformation::drivingSideDiffers() const { return m_drivingSideDiffers; } LocationInformation::PowerPlugCompatibility LocationInformation::powerPlugCompatibility() const { return m_powerPlugCompat; } struct plugTypeName { KnowledgeDb::PowerPlugType type; const char *name; } static const plug_name_table[] = { { KnowledgeDb::TypeA, I18N_NOOP("Type A") }, { KnowledgeDb::TypeB, I18N_NOOP("Type B") }, { KnowledgeDb::TypeC, I18N_NOOP("Europlug") }, { KnowledgeDb::TypeD, I18N_NOOP("Type D") }, { KnowledgeDb::TypeE, I18N_NOOP("Type E") }, { KnowledgeDb::TypeF, I18N_NOOP("Schuko") }, { KnowledgeDb::TypeG, I18N_NOOP("Type G") }, { KnowledgeDb::TypeH, I18N_NOOP("Type H") }, { KnowledgeDb::TypeI, I18N_NOOP("Type I") }, { KnowledgeDb::TypeJ, I18N_NOOP("Type J") }, { KnowledgeDb::TypeK, I18N_NOOP("Type K") }, { KnowledgeDb::TypeL, I18N_NOOP("Type L") }, { KnowledgeDb::TypeM, I18N_NOOP("Type M") }, { KnowledgeDb::TypeN, I18N_NOOP("Type N") }, }; static QString plugTypesToString(KnowledgeDb::PowerPlugTypes type) { QStringList l; for (const auto &elem : plug_name_table) { if (type & elem.type) { l.push_back(i18n(elem.name)); } } return l.join(QLatin1String(", ")); } QString LocationInformation::powerPlugTypes() const { return plugTypesToString(m_incompatPlugs); } QString LocationInformation::powerSocketTypes() const { return plugTypesToString(m_incompatSockets); } void LocationInformation::setPowerPlugTypes(KItinerary::KnowledgeDb::PowerPlugTypes powerPlugs) { if (m_powerPlugs == powerPlugs) { return; } if (powerPlugs != KnowledgeDb::Unknown && m_powerPlugs != KnowledgeDb::Unknown) { m_incompatPlugs = KnowledgeDb::incompatiblePowerPlugs(m_powerPlugs, powerPlugs); m_incompatSockets = KnowledgeDb::incompatiblePowerSockets(m_powerPlugs, powerPlugs); if ((m_powerPlugs & powerPlugs) == 0) { m_powerPlugCompat = Incompatible; } else if (m_incompatPlugs != KnowledgeDb::Unknown || m_incompatSockets != KnowledgeDb::Unknown) { m_powerPlugCompat = PartiallyCompatible; } } m_powerPlugs = powerPlugs; } + +QTimeZone LocationInformation::timeZone() const +{ + return m_timeZone; +} + +void LocationInformation::setTimeZone(const QTimeZone &tz) +{ + // TODO use transition time + m_timeZoneDiffers = m_timeZone.isValid() && tz.isValid() && m_timeZone.offsetFromUtc(QDateTime::currentDateTimeUtc()) != tz.offsetFromUtc(QDateTime::currentDateTimeUtc()); + qDebug() << m_timeZoneDiffers << tz << m_timeZone; + m_timeZone = tz; +} + +bool LocationInformation::hasRelevantTimeZoneChange(const LocationInformation &other) const +{ + // TODO this should uses the time we change the timezone, not now? + return m_timeZone.isValid() && other.m_timeZone.isValid() + && m_timeZone.offsetFromUtc(QDateTime::currentDateTimeUtc()) != other.m_timeZone.offsetFromUtc(QDateTime::currentDateTimeUtc()); +} + +bool LocationInformation::timeZoneDiffers() const +{ + return m_timeZoneDiffers && m_timeZone.isValid(); +} + +QString LocationInformation::timeZoneName() const +{ + // TODO use transition time + return m_timeZone.displayName(QTimeZone::GenericTime, QTimeZone::LongName); +} diff --git a/src/app/locationinformation.h b/src/app/locationinformation.h index e257bf9..b9dc61c 100644 --- a/src/app/locationinformation.h +++ b/src/app/locationinformation.h @@ -1,80 +1,92 @@ /* Copyright (C) 2018 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef LOCATIONINFORMATION_H #define LOCATIONINFORMATION_H #include #include #include +#include /** Data for country information elements in the timeline model. */ class LocationInformation { Q_GADGET Q_PROPERTY(QString isoCode READ isoCode) Q_PROPERTY(KItinerary::KnowledgeDb::DrivingSide drivingSide READ drivingSide) /** This indicates that the driving side information changed and needs to be displayed. */ Q_PROPERTY(bool drivingSideDiffers READ drivingSideDiffers) Q_PROPERTY(PowerPlugCompatibility powerPlugCompatibility READ powerPlugCompatibility) /** Plugs from the home country that will not fit. */ Q_PROPERTY(QString powerPlugTypes READ powerPlugTypes) /** Sockets in the destination country that are incompatible with (some of) my plugs. */ Q_PROPERTY(QString powerSocketTypes READ powerSocketTypes) + Q_PROPERTY(bool timeZoneDiffers READ timeZoneDiffers) + Q_PROPERTY(QString timeZoneName READ timeZoneName) + public: LocationInformation(); ~LocationInformation(); enum PowerPlugCompatibility { FullyCompatible, PartiallyCompatible, Incompatible }; Q_ENUM(PowerPlugCompatibility) bool operator==(const LocationInformation &other) const; QString isoCode() const; void setIsoCode(const QString &isoCode); KItinerary::KnowledgeDb::DrivingSide drivingSide() const; bool drivingSideDiffers() const; PowerPlugCompatibility powerPlugCompatibility() const; QString powerPlugTypes() const; QString powerSocketTypes() const; + QTimeZone timeZone() const; + void setTimeZone(const QTimeZone &tz); + bool hasRelevantTimeZoneChange(const LocationInformation &other) const; + bool timeZoneDiffers() const; + QString timeZoneName() const; + private: void setDrivingSide(KItinerary::KnowledgeDb::DrivingSide drivingSide); void setPowerPlugTypes(KItinerary::KnowledgeDb::PowerPlugTypes powerPlugs); QString m_isoCode; + QTimeZone m_timeZone; KItinerary::KnowledgeDb::PowerPlugTypes m_powerPlugs = KItinerary::KnowledgeDb::Unknown; KItinerary::KnowledgeDb::PowerPlugTypes m_incompatPlugs = KItinerary::KnowledgeDb::Unknown; KItinerary::KnowledgeDb::PowerPlugTypes m_incompatSockets = KItinerary::KnowledgeDb::Unknown; KItinerary::KnowledgeDb::DrivingSide m_drivingSide = KItinerary::KnowledgeDb::DrivingSide::Unknown; bool m_drivingSideDiffers = false; PowerPlugCompatibility m_powerPlugCompat = FullyCompatible; + bool m_timeZoneDiffers = false; }; Q_DECLARE_METATYPE(LocationInformation) #endif // LOCATIONINFORMATION_H diff --git a/src/app/timelinemodel.cpp b/src/app/timelinemodel.cpp index d3849c2..1585a82 100644 --- a/src/app/timelinemodel.cpp +++ b/src/app/timelinemodel.cpp @@ -1,749 +1,759 @@ /* Copyright (C) 2018 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "timelinemodel.h" #include "locationinformation.h" #include "pkpassmanager.h" #include "reservationmanager.h" #include "tripgroup.h" #include "tripgroupmanager.h" #include "transfermanager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace KItinerary; static bool needsSplitting(const QVariant &res) { // multi-day event? if (JsonLd::isA(res)) { const auto ev = res.value().reservationFor().value(); return ev.startDate().date() != ev.endDate().date() && ev.endDate().isValid(); } return JsonLd::isA(res) || JsonLd::isA(res); } static QString destinationCountry(const QVariant &res) { if (LocationUtil::isLocationChange(res)) { return LocationUtil::address(LocationUtil::arrivalLocation(res)).addressCountry(); } return LocationUtil::address(LocationUtil::location(res)).addressCountry(); } +static QTimeZone destinationTimeZone(const QVariant &res) +{ + const auto dt = SortUtil::endDateTime(res); + return dt.timeSpec() == Qt::TimeZone ? dt.timeZone() : QTimeZone(); +} + static GeoCoordinates geoCoordinate(const QVariant &res) { if (LocationUtil::isLocationChange(res)) { return LocationUtil::geo(LocationUtil::arrivalLocation(res)); } return LocationUtil::geo(LocationUtil::location(res)); } TimelineModel::TimelineModel(QObject *parent) : QAbstractListModel(parent) { connect(&m_dayUpdateTimer, &QTimer::timeout, this, &TimelineModel::dayChanged); m_dayUpdateTimer.setSingleShot(true); m_dayUpdateTimer.setInterval((QTime::currentTime().secsTo({23, 59, 59}) + 1) * 1000); m_dayUpdateTimer.start(); // make sure we properly update the empty today marker connect(this, &TimelineModel::todayRowChanged, this, [this]() { const auto idx = index(todayRow(), 0); if (m_todayEmpty == idx.data(TimelineModel::TodayEmptyRole).toBool()) { return; } m_todayEmpty = !m_todayEmpty; emit dataChanged(idx, idx); }); } TimelineModel::~TimelineModel() = default; void TimelineModel::setReservationManager(ReservationManager* mgr) { // for auto tests only if (Q_UNLIKELY(!mgr)) { beginResetModel(); disconnect(m_resMgr, &ReservationManager::batchAdded, this, &TimelineModel::batchAdded); disconnect(m_resMgr, &ReservationManager::batchChanged, this, &TimelineModel::batchChanged); disconnect(m_resMgr, &ReservationManager::batchContentChanged, this, &TimelineModel::batchChanged); disconnect(m_resMgr, &ReservationManager::batchRenamed, this, &TimelineModel::batchRenamed); disconnect(m_resMgr, &ReservationManager::batchRemoved, this, &TimelineModel::batchRemoved); m_resMgr = mgr; m_elements.clear(); endResetModel(); return; } beginResetModel(); m_resMgr = mgr; for (const auto &resId : mgr->batches()) { const auto res = m_resMgr->reservation(resId); if (needsSplitting(res)) { m_elements.push_back(TimelineElement{resId, res, TimelineElement::RangeBegin}); m_elements.push_back(TimelineElement{resId, res, TimelineElement::RangeEnd}); } else { m_elements.push_back(TimelineElement{resId, res, TimelineElement::SelfContained}); } } m_elements.push_back(TimelineElement{TimelineElement::TodayMarker, QDateTime(today(), QTime(0, 0))}); std::sort(m_elements.begin(), m_elements.end()); connect(mgr, &ReservationManager::batchAdded, this, &TimelineModel::batchAdded); connect(mgr, &ReservationManager::batchChanged, this, &TimelineModel::batchChanged); connect(mgr, &ReservationManager::batchContentChanged, this, &TimelineModel::batchChanged); connect(mgr, &ReservationManager::batchRenamed, this, &TimelineModel::batchRenamed); connect(mgr, &ReservationManager::batchRemoved, this, &TimelineModel::batchRemoved); endResetModel(); updateInformationElements(); emit todayRowChanged(); } void TimelineModel::setWeatherForecastManager(WeatherForecastManager* mgr) { m_weatherMgr = mgr; updateWeatherElements(); connect(m_weatherMgr, &WeatherForecastManager::forecastUpdated, this, &TimelineModel::updateWeatherElements); } TripGroupManager* TimelineModel::tripGroupManager() const { return m_tripGroupManager; } void TimelineModel::setTripGroupManager(TripGroupManager *mgr) { m_tripGroupManager = mgr; connect(mgr, &TripGroupManager::tripGroupAdded, this, &TimelineModel::tripGroupAdded); connect(mgr, &TripGroupManager::tripGroupChanged, this, &TimelineModel::tripGroupChanged); connect(mgr, &TripGroupManager::tripGroupRemoved, this, &TimelineModel::tripGroupRemoved); for (const auto &group : mgr->tripGroups()) { tripGroupAdded(group); } } void TimelineModel::setHomeCountryIsoCode(const QString &isoCode) { m_homeCountry = isoCode; updateInformationElements(); } void TimelineModel::setTransferManager(TransferManager *mgr) { m_transferManager = mgr; connect(mgr, &TransferManager::transferAdded, this, &TimelineModel::transferChanged); connect(mgr, &TransferManager::transferChanged, this, &TimelineModel::transferChanged); connect(mgr, &TransferManager::transferRemoved, this, &TimelineModel::transferRemoved); // load existing transfers into the model for (const auto &batchId : m_resMgr->batches()) { updateTransfersForBatch(batchId); } } int TimelineModel::rowCount(const QModelIndex& parent) const { if (parent.isValid() || !m_resMgr) { return 0; } return m_elements.size(); } QVariant TimelineModel::data(const QModelIndex& index, int role) const { if (!index.isValid() || !m_resMgr) { return {}; } const auto &elem = m_elements.at(index.row()); switch (role) { case SectionHeader: { if (elem.dt.isNull()) { return {}; } if (elem.dt.date() == today()) { return i18n("Today"); } return i18nc("weekday, date", "%1, %2", QLocale().dayName(elem.dt.date().dayOfWeek(), QLocale::LongFormat), QLocale().toString(elem.dt.date(), QLocale::ShortFormat)); } case BatchIdRole: return elem.batchId; case ElementTypeRole: return elem.elementType; case TodayEmptyRole: if (elem.elementType == TimelineElement::TodayMarker) { return index.row() == (int)(m_elements.size() - 1) || m_elements.at(index.row() + 1).dt.date() > today(); } return {}; case IsTodayRole: return elem.dt.date() == today(); case ElementRangeRole: return elem.rangeType; case LocationInformationRole: if (elem.elementType == TimelineElement::LocationInfo) return elem.content; break; case WeatherForecastRole: if (elem.elementType == TimelineElement::WeatherForecast) return elem.content; break; case ReservationsRole: { const auto resIds = m_resMgr->reservationsForBatch(elem.batchId); QVector v; v.reserve(resIds.size()); for (const auto &resId : resIds) { v.push_back(m_resMgr->reservation(resId)); } std::sort(v.begin(), v.end(), SortUtil::isBefore); return QVariant::fromValue(v); } case TripGroupIdRole: if (elem.elementType == TimelineElement::TripGroup) { return elem.content; } break; case TripGroupRole: if (elem.elementType == TimelineElement::TripGroup) return QVariant::fromValue(m_tripGroupManager->tripGroup(elem.content.toString())); break; case TransferRole: if (elem.elementType == TimelineElement::Transfer) { return elem.content; } break; } return {}; } QHash TimelineModel::roleNames() const { auto names = QAbstractListModel::roleNames(); names.insert(SectionHeader, "sectionHeader"); names.insert(BatchIdRole, "batchId"); names.insert(ElementTypeRole, "type"); names.insert(TodayEmptyRole, "isTodayEmpty"); names.insert(IsTodayRole, "isToday"); names.insert(ElementRangeRole, "rangeType"); names.insert(LocationInformationRole, "locationInformation"); names.insert(WeatherForecastRole, "weatherForecast"); names.insert(ReservationsRole, "reservations"); names.insert(TripGroupIdRole, "tripGroupId"); names.insert(TripGroupRole, "tripGroup"); names.insert(TransferRole, "transfer"); return names; } int TimelineModel::todayRow() const { const auto it = std::find_if(m_elements.begin(), m_elements.end(), [](const auto &e) { return e.elementType == TimelineElement::TodayMarker; }); return std::distance(m_elements.begin(), it); } void TimelineModel::batchAdded(const QString &resId) { const auto res = m_resMgr->reservation(resId); if (needsSplitting(res)) { insertElement(TimelineElement{resId, res, TimelineElement::RangeBegin}); insertElement(TimelineElement{resId, res, TimelineElement::RangeEnd}); } else { insertElement(TimelineElement{resId, res, TimelineElement::SelfContained}); } updateInformationElements(); updateTransfersForBatch(resId); emit todayRowChanged(); } void TimelineModel::insertElement(TimelineElement &&elem) { auto it = std::lower_bound(m_elements.begin(), m_elements.end(), elem); const auto row = std::distance(m_elements.begin(), it); beginInsertRows({}, row, row); m_elements.insert(it, std::move(elem)); endInsertRows(); } void TimelineModel::batchChanged(const QString &resId) { const auto res = m_resMgr->reservation(resId); if (needsSplitting(res)) { updateElement(resId, res, TimelineElement::RangeBegin); updateElement(resId, res, TimelineElement::RangeEnd); } else { updateElement(resId, res, TimelineElement::SelfContained); } updateInformationElements(); } void TimelineModel::batchRenamed(const QString& oldBatchId, const QString& newBatchId) { for (auto it = m_elements.begin(); it != m_elements.end(); ++it) { if ((*it).batchId != oldBatchId) { continue; } (*it).batchId = newBatchId; const auto idx = index(std::distance(m_elements.begin(), it), 0); emit dataChanged(idx, idx); if ((*it).rangeType == TimelineElement::SelfContained || (*it).rangeType == TimelineElement::RangeEnd) { break; } } } void TimelineModel::updateElement(const QString &resId, const QVariant &res, TimelineElement::RangeType rangeType) { const auto it = std::find_if(m_elements.begin(), m_elements.end(), [resId, rangeType](const auto &e) { return e.batchId == resId && e.rangeType == rangeType; }); if (it == m_elements.end()) { return; } const auto row = std::distance(m_elements.begin(), it); const auto newDt = TimelineElement::relevantDateTime(res, rangeType); if ((*it).dt != newDt) { // element moved beginRemoveRows({}, row, row); m_elements.erase(it); endRemoveRows(); insertElement(TimelineElement{resId, res, rangeType}); } else { emit dataChanged(index(row, 0), index(row, 0)); } } void TimelineModel::batchRemoved(const QString &resId) { const auto it = std::find_if(m_elements.begin(), m_elements.end(), [resId](const auto &e) { return e.batchId == resId; }); if (it == m_elements.end()) { return; } const auto isSplit = (*it).rangeType == TimelineElement::RangeBegin; const auto row = std::distance(m_elements.begin(), it); beginRemoveRows({}, row, row); m_elements.erase(it); endRemoveRows(); emit todayRowChanged(); if (isSplit) { batchRemoved(resId); } updateInformationElements(); } void TimelineModel::dayChanged() { updateTodayMarker(); updateWeatherElements(); m_dayUpdateTimer.setInterval((QTime::currentTime().secsTo({23, 59, 59}) + 1) * 1000); m_dayUpdateTimer.start(); } void TimelineModel::updateTodayMarker() { const auto it = std::lower_bound(m_elements.begin(), m_elements.end(), today(), [](const auto &lhs, const auto &rhs) { return lhs.dt.date() < rhs; }); const auto newRow = std::distance(m_elements.begin(), it); const auto oldRow = todayRow(); Q_ASSERT(oldRow < newRow); beginInsertRows({}, newRow, newRow); m_elements.insert(it, TimelineElement{TimelineElement::TodayMarker, QDateTime(today(), QTime(0, 0))}); endInsertRows(); beginRemoveRows({}, oldRow, oldRow); m_elements.erase(m_elements.begin() + oldRow); endRemoveRows(); emit todayRowChanged(); } void TimelineModel::updateInformationElements() { // the country information is shown before transitioning into a country that // differs in one or more properties from the home country and we where that // differences is introduced by the transition LocationInformation homeCountry; homeCountry.setIsoCode(m_homeCountry); auto previousCountry = homeCountry; for (auto it = m_elements.begin(); it != m_elements.end(); ++it) { switch ((*it).elementType) { case TimelineElement::TodayMarker: case TimelineElement::WeatherForecast: it = erasePreviousCountyInfo(it); continue; case TimelineElement::LocationInfo: previousCountry = (*it).content.value(); it = erasePreviousCountyInfo(it); // purge multiple consecutive country info elements continue; default: break; } + const auto res = m_resMgr->reservation((*it).batchId); + auto newCountry = homeCountry; - newCountry.setIsoCode(destinationCountry(m_resMgr->reservation((*it).batchId))); + newCountry.setIsoCode(destinationCountry(res)); + newCountry.setTimeZone(previousCountry.timeZone()); + newCountry.setTimeZone(destinationTimeZone(res)); if (newCountry == previousCountry) { continue; } - if (newCountry == homeCountry) { + if (newCountry == homeCountry && !newCountry.hasRelevantTimeZoneChange(previousCountry)) { assert(it != m_elements.begin()); // previousCountry == homeCountry in this case // purge outdated country info element it = erasePreviousCountyInfo(it); previousCountry = newCountry; continue; } // add new country info element auto row = std::distance(m_elements.begin(), it); beginInsertRows({}, row, row); it = m_elements.insert(it, TimelineElement{TimelineElement::LocationInfo, (*it).dt, QVariant::fromValue(newCountry)}); endInsertRows(); previousCountry = newCountry; } updateWeatherElements(); } std::vector::iterator TimelineModel::erasePreviousCountyInfo(std::vector::iterator it) { if (it == m_elements.begin()) { return it; } auto it2 = it; --it2; if ((*it2).elementType == TimelineElement::LocationInfo) { const auto row = std::distance(m_elements.begin(), it2); beginRemoveRows({}, row, row); it = m_elements.erase(it2); endRemoveRows(); } return it; } void TimelineModel::updateWeatherElements() { if (!m_weatherMgr || !m_weatherMgr->allowNetworkAccess() || m_elements.empty()) { return; } qDebug() << "recomputing weather elements"; GeoCoordinates geo; // look through the past, clean up weather elements there and figure out where we are auto it = m_elements.begin(); for (; it != m_elements.end() && (*it).dt < now();) { if ((*it).elementType == TimelineElement::WeatherForecast) { const auto row = std::distance(m_elements.begin(), it); beginRemoveRows({}, row, row); it = m_elements.erase(it); endRemoveRows(); continue; } const auto res = m_resMgr->reservation((*it).batchId); const auto newGeo = geoCoordinate(res); if (LocationUtil::isLocationChange(res) || newGeo.isValid()) { geo = newGeo; } ++it; } auto date = now(); date.setTime(QTime(date.time().hour() + 1, 0)); // ### this looks suspicious for 23:xx? while(it != m_elements.end() && date < m_weatherMgr->maximumForecastTime(today())) { if ((*it).dt < date || (*it).elementType == TimelineElement::TodayMarker) { // clean up outdated weather elements (happens when merging previously split ranges) if ((*it).elementType == TimelineElement::WeatherForecast) { const auto row = std::distance(m_elements.begin(), it); beginRemoveRows({}, row, row); it = m_elements.erase(it); endRemoveRows(); if (it == m_elements.end()) { break; } continue; } // track where we are const auto res = m_resMgr->reservation((*it).batchId); const auto newGeo = geoCoordinate(res); if (LocationUtil::isLocationChange(res) || newGeo.isValid()) { geo = newGeo; } ++it; continue; } // determine the length of the forecast range (at most until the end of the day) auto endTime = date; endTime.setTime(QTime(23, 59, 59)); auto nextStartTime = endTime; GeoCoordinates newGeo = geo; for (auto it2 = it; it2 != m_elements.end(); ++it2) { if ((*it2).dt >= endTime) { break; } const auto res = m_resMgr->reservation((*it2).batchId); if (LocationUtil::isLocationChange(res)) { // exclude the actual travel time from forecast ranges endTime = std::min(endTime, TimelineElement::relevantDateTime(res, TimelineElement::RangeBegin)); nextStartTime = std::max(endTime, TimelineElement::relevantDateTime(res, TimelineElement::RangeEnd)); newGeo = geoCoordinate(res); break; } } ::WeatherForecast fc; if (geo.isValid()) { m_weatherMgr->monitorLocation(geo.latitude(), geo.longitude()); fc = m_weatherMgr->forecast(geo.latitude(), geo.longitude(), date, endTime); } geo = newGeo; // case 1: we have forecast data, and a matching weather element: update if (fc.isValid() && (*it).dt == date && (*it).elementType == TimelineElement::WeatherForecast) { (*it).content = QVariant::fromValue(fc); const auto idx = index(std::distance(m_elements.begin(), it), 0); emit dataChanged(idx, idx); } // case 2: we have forecast data, but no matching weather element: insert else if (fc.isValid()) { const auto row = std::distance(m_elements.begin(), it); beginInsertRows({}, row, row); it = m_elements.insert(it, TimelineElement{TimelineElement::WeatherForecast, date, QVariant::fromValue(fc)}); endInsertRows(); } // case 3: we have no forecast data, but a matching weather element: remove else if ((*it).elementType == TimelineElement::WeatherForecast && (*it).dt == date) { const auto row = std::distance(m_elements.begin(), it); beginRemoveRows({}, row, row); it = m_elements.erase(it); endRemoveRows(); } date = nextStartTime.addSecs(1); ++it; } // append weather elements beyond the end of the list if necessary while (date < m_weatherMgr->maximumForecastTime(today()) && geo.isValid()) { auto endTime = date; endTime.setTime(QTime(23, 59, 59)); m_weatherMgr->monitorLocation(geo.latitude(), geo.longitude()); const auto fc = m_weatherMgr->forecast(geo.latitude(), geo.longitude(), date, endTime); if (fc.isValid()) { const auto row = std::distance(m_elements.begin(), it); beginInsertRows({}, row, row); it = m_elements.insert(it, TimelineElement{TimelineElement::WeatherForecast, date, QVariant::fromValue(fc)}); ++it; endInsertRows(); } date = endTime.addSecs(1); } qDebug() << "weather recomputation done"; } void TimelineModel::updateTransfersForBatch(const QString& batchId) { if (!m_transferManager) { return; } auto transfer = m_transferManager->transfer(batchId, Transfer::Before); if (transfer.state() != Transfer::UndefinedState) { transferChanged(transfer); } transfer = m_transferManager->transfer(batchId, Transfer::After); if (transfer.state() != Transfer::UndefinedState) { transferChanged(transfer); } } QDateTime TimelineModel::now() const { if (Q_UNLIKELY(m_unitTestTime.isValid())) { return m_unitTestTime; } return QDateTime::currentDateTime(); } QDate TimelineModel::today() const { if (Q_UNLIKELY(m_unitTestTime.isValid())) { return m_unitTestTime.date(); } return QDate::currentDate(); } void TimelineModel::setCurrentDateTime(const QDateTime &dt) { const auto dayDiffers = today() != dt.date(); m_unitTestTime = dt; if (dayDiffers && !m_elements.empty()) { dayChanged(); } } void TimelineModel::tripGroupAdded(const QString& groupId) { const auto g = m_tripGroupManager->tripGroup(groupId); TimelineElement beginElem{TimelineElement::TripGroup, g.beginDateTime(), groupId}; beginElem.rangeType = TimelineElement::RangeBegin; insertElement(std::move(beginElem)); TimelineElement endElem{TimelineElement::TripGroup, g.endDateTime(), groupId}; endElem.rangeType = TimelineElement::RangeEnd; insertElement(std::move(endElem)); } void TimelineModel::tripGroupChanged(const QString& groupId) { // ### this can be done better probably tripGroupRemoved(groupId); tripGroupAdded(groupId); } void TimelineModel::tripGroupRemoved(const QString& groupId) { for (auto it = m_elements.begin(); it != m_elements.end();) { if ((*it).elementType != TimelineElement::TripGroup || (*it).content.toString() != groupId) { ++it; continue; } const auto row = std::distance(m_elements.begin(), it); beginRemoveRows({}, row, row); it = m_elements.erase(it); endRemoveRows(); } } void TimelineModel::transferChanged(const Transfer& transfer) { if (transfer.state() == Transfer::UndefinedState) { return; } if (transfer.state() == Transfer::Discarded) { transferRemoved(transfer.reservationId(), transfer.alignment()); return; } auto it = std::find_if(m_elements.begin(), m_elements.end(), [transfer](const auto &e) { return e.batchId == transfer.reservationId(); }); if (it == m_elements.end()) { return; } auto insertIt = it; if (transfer.alignment() == Transfer::Before) { if (it != m_elements.begin()) { --it; } } else { ++it; ++insertIt; } if (it != m_elements.end() && (*it).elementType == TimelineElement::Transfer && (*it).content.value().reservationId() == transfer.reservationId()) { const auto row = std::distance(m_elements.begin(), it); (*it).content = QVariant::fromValue(transfer); emit dataChanged(index(row, 0), index(row, 0)); } else { const auto row = std::distance(m_elements.begin(), insertIt); beginInsertRows({}, row, row); m_elements.insert(insertIt, TimelineElement(transfer)); endInsertRows(); return; } emit todayRowChanged(); } void TimelineModel::transferRemoved(const QString &resId, Transfer::Alignment alignment) { auto it = std::find_if(m_elements.begin(), m_elements.end(), [resId](const auto &e) { return e.batchId == resId; }); if (it == m_elements.end()) { return; } if (alignment == Transfer::Before) { if (it == m_elements.begin()) { return; } --it; } else { // Transfer::After ++it; if (it == m_elements.end()) { return; } } if ((*it).elementType != TimelineElement::Transfer || (*it).content.value().reservationId() != resId) { return; } const auto row = std::distance(m_elements.begin(), it); beginRemoveRows({}, row, row); m_elements.erase(it); endRemoveRows(); emit todayRowChanged(); }