Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ public String toStringShort() {
@Override
public JSONObject toJSON() {
try {
JSONObject json = new JSONObject();
final JSONObject json = new JSONObject();
json.put(JSON_ROUTE, Route.toJSON(getRoute()));
json.put(JSON_DIRECTION, Direction.toJSON(getDirection()));
json.put(JSON_STOP, Stop.toJSON(getStop()));
Expand Down Expand Up @@ -291,6 +291,9 @@ public ContentValues toContentValues() {
values.put(GTFSProviderContract.RouteDirectionStopColumns.T_STOP_K_LNG, getStop().getLng());
values.put(GTFSProviderContract.RouteDirectionStopColumns.T_STOP_K_ACCESSIBLE, getStop().getAccessible());
values.put(GTFSProviderContract.RouteDirectionStopColumns.T_STOP_K_ORIGINAL_ID_HASH, getStop().getOriginalIdHash());
if (FeatureFlags.F_EXPORT_STOP_TIMEZONE_ID) {
values.put(GTFSProviderContract.RouteDirectionStopColumns.T_STOP_K_TIMEZONE_ID, getStop().getTimeZoneIdOrNull());
}
// T_DIRECTION_STOPS_K_STOP_SEQUENCE not used in RouteDirectionStop class
values.put(GTFSProviderContract.RouteDirectionStopColumns.T_DIRECTION_STOPS_K_NO_PICKUP, SqlUtils.toSQLBoolean(isNoPickup()));
if (FeatureFlags.F_EXPORT_DIRECTION_STOP_LAST) {
Expand Down Expand Up @@ -332,7 +335,8 @@ public static RouteDirectionStop fromCursorStatic(@NonNull Cursor c, @NonNull St
CursorExtKt.getDouble(c, GTFSProviderContract.RouteDirectionStopColumns.T_STOP_K_LAT),
CursorExtKt.getDouble(c, GTFSProviderContract.RouteDirectionStopColumns.T_STOP_K_LNG),
CursorExtKt.optIntNN(c, GTFSProviderContract.RouteDirectionStopColumns.T_STOP_K_ACCESSIBLE, Accessibility.DEFAULT),
CursorExtKt.optInt(c, GTFSProviderContract.RouteDirectionStopColumns.T_STOP_K_ORIGINAL_ID_HASH, GTFSCommons.DEFAULT_ID_HASH)
CursorExtKt.optInt(c, GTFSProviderContract.RouteDirectionStopColumns.T_STOP_K_ORIGINAL_ID_HASH, GTFSCommons.DEFAULT_ID_HASH),
CursorExtKt.optString(c, GTFSProviderContract.RouteDirectionStopColumns.T_STOP_K_TIMEZONE_ID, null)
),
CursorExtKt.getBoolean(c, GTFSProviderContract.RouteDirectionStopColumns.T_DIRECTION_STOPS_K_NO_PICKUP),
CursorExtKt.optBoolean(c, GTFSProviderContract.RouteDirectionStopColumns.T_DIRECTION_STOPS_K_ALWAYS_LAST_TRIP_STOP)
Expand Down
88 changes: 49 additions & 39 deletions src/main/java/org/mtransit/android/commons/data/Schedule.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.mtransit.android.commons.BuildConfig;
import org.mtransit.android.commons.Constants;
import org.mtransit.android.commons.JSONUtils;
import org.mtransit.android.commons.MTLog;
import org.mtransit.android.commons.R;
import org.mtransit.android.commons.StringUtils;
Expand Down Expand Up @@ -51,10 +53,13 @@ public String getLogTag() {

private boolean noPickup;

@Nullable
private final String localTimeZoneId;

@NonNull
private final List<Frequency> frequencies = new ArrayList<>();

public Schedule(@NonNull POIStatus status, long providerPrecisionInMs, boolean noPickup) {
public Schedule(@NonNull POIStatus status, long providerPrecisionInMs, boolean noPickup, @Nullable String localTimeZoneId) {
this(
status.getId(),
status.getTargetUUID(),
Expand All @@ -63,6 +68,7 @@ public Schedule(@NonNull POIStatus status, long providerPrecisionInMs, boolean n
status.getReadFromSourceAtInMs(),
providerPrecisionInMs,
noPickup,
localTimeZoneId,
status.getSourceLabel(),
status.isNoData()
);
Expand All @@ -76,9 +82,10 @@ public Schedule(
long readFromSourceAtInMs,
long providerPrecisionInMs,
boolean noPickup,
@Nullable String localTimeZoneId,
@Nullable String sourceLabel
) {
this(id, targetUUID, lastUpdateInMs, maxValidityInMs, readFromSourceAtInMs, providerPrecisionInMs, noPickup, sourceLabel, false);
this(id, targetUUID, lastUpdateInMs, maxValidityInMs, readFromSourceAtInMs, providerPrecisionInMs, noPickup, localTimeZoneId, sourceLabel, false);
}

public Schedule(
Expand All @@ -89,19 +96,26 @@ public Schedule(
long readFromSourceAtInMs,
long providerPrecisionInMs,
boolean noPickup,
@Nullable String localTimeZoneId,
@Nullable String sourceLabel,
boolean noData
) {
super(id, targetUUID, POI.ITEM_STATUS_TYPE_SCHEDULE, lastUpdateInMs, maxValidityInMs, readFromSourceAtInMs, sourceLabel, noData);
this.noPickup = noPickup;
this.providerPrecisionInMs = providerPrecisionInMs;
this.noPickup = noPickup;
this.localTimeZoneId = localTimeZoneId;
resetTimestampsUntilInMs();
}

public boolean isNoPickup() {
return noPickup;
}

@Nullable
public String getLocalTimeZoneId() {
return localTimeZoneId;
}
Comment thread
mmathieum marked this conversation as resolved.

public long getProviderPrecisionInMs() {
return providerPrecisionInMs;
}
Expand Down Expand Up @@ -141,13 +155,21 @@ private static Schedule fromExtraJSON(@NonNull POIStatus status, @NonNull JSONOb
try {
final long providerPrecisionInMs = extrasJSON.getInt(JSON_PROVIDER_PRECISION_IN_MS);
final boolean noPickup = extrasJSON.optBoolean(JSON_IS_NO_PICKUP, false);
final Schedule schedule = new Schedule(status, providerPrecisionInMs, noPickup);
String localTimeZoneId = JSONUtils.optString(extrasJSON, JSON_LOCAL_TIME_ZONE_ID);
final ArrayList<Timestamp> timestamps = new ArrayList<>();
final JSONArray jTimestamps = extrasJSON.getJSONArray(JSON_TIMESTAMPS);
for (int i = 0; i < jTimestamps.length(); i++) {
final JSONObject jTimestamp = jTimestamps.getJSONObject(i);
schedule.addTimestampWithoutSort(Timestamp.parseJSON(jTimestamp));
final Timestamp timestamp = Timestamp.parseJSON(jTimestamp);
if (timestamp == null) continue;
if (localTimeZoneId == null) {
//noinspection DiscouragedApi
localTimeZoneId = timestamp.getLocalTimeZoneId();
}
timestamps.add(timestamp);
}
schedule.sortTimestamps();
final Schedule schedule = new Schedule(status, providerPrecisionInMs, noPickup, localTimeZoneId);
schedule.setTimestampsAndSort(timestamps);
final JSONArray jFrequencies = extrasJSON.getJSONArray(JSON_FREQUENCIES);
for (int i = 0; i < jFrequencies.length(); i++) {
final JSONObject jFrequency = jFrequencies.getJSONObject(i);
Expand All @@ -165,6 +187,7 @@ private static Schedule fromExtraJSON(@NonNull POIStatus status, @NonNull JSONOb
private static final String JSON_IS_NO_PICKUP = "decentOnly"; // do NOT change JSON key string value!
private static final String JSON_TIMESTAMPS = "timestamps";
private static final String JSON_FREQUENCIES = "frequencies";
private static final String JSON_LOCAL_TIME_ZONE_ID = "tz";

@Nullable
@Override
Expand All @@ -173,6 +196,9 @@ public JSONObject getExtrasJSON() {
JSONObject json = new JSONObject();
json.put(JSON_PROVIDER_PRECISION_IN_MS, this.providerPrecisionInMs);
json.put(JSON_IS_NO_PICKUP, this.noPickup);
if (this.localTimeZoneId != null) {
json.put(JSON_LOCAL_TIME_ZONE_ID, this.localTimeZoneId);
}
JSONArray jTimestamps = new JSONArray();
for (Timestamp timestamp : this.timestamps) {
jTimestamps.put(timestamp.toJSON());
Expand Down Expand Up @@ -263,17 +289,6 @@ public int getTimestampsCount() {
return this.timestamps.size();
}

@Nullable
public TimeZone getTimeZone() {
for (Timestamp timestamp : this.timestamps) {
final String localTimeZoneId = timestamp.getLocalTimeZoneId();
if (localTimeZoneId != null) {
return TimeZone.getTimeZone(localTimeZoneId);
}
}
return null;
}

protected static final long MIN_UI_PRECISION_IN_MS = TimeUnit.MINUTES.toMillis(1L);

protected long getUIProviderPrecisionInMs() {
Expand Down Expand Up @@ -456,7 +471,7 @@ public String getLogTag() {
@Nullable
private String headsignValue = null;
@Nullable
private String localTimeZoneId = null;
private final String localTimeZoneId; // TODO remove once migrated fully to Schedule TZ
@Nullable
private Boolean realTime = null;
@Nullable
Expand All @@ -474,14 +489,14 @@ public String getLogTag() {

@VisibleForTesting
public Timestamp(long departureT) {
this.departureInMs = departureT;
this(departureT, (String) null);
}

public Timestamp(long departureT, @NonNull TimeZone localTimeZone) {
this(departureT, localTimeZone.getID());
}

public Timestamp(long departureT, @NonNull String localTimeZoneId) {
public Timestamp(long departureT, @Nullable String localTimeZoneId) {
this.departureInMs = departureT;
this.localTimeZoneId = localTimeZoneId;
}
Expand Down Expand Up @@ -620,20 +635,12 @@ private String getNewHeading() {
return Direction.getNewHeading(this.headsignType, this.headsignValue);
}

private void setLocalTimeZoneId(@Nullable String localTimeZone) {
this.localTimeZoneId = localTimeZone;
}

@Discouraged(message = "should use parent Schedule local time zone")
@Nullable
public String getLocalTimeZoneId() {
return localTimeZoneId;
}

@Deprecated
public boolean hasLocalTimeZoneId() {
return !TextUtils.isEmpty(this.localTimeZoneId);
}

public void setRealTime(@Nullable Boolean realTime) {
this.realTime = realTime;
}
Expand Down Expand Up @@ -758,7 +765,7 @@ public int hashCode() {
@NonNull
@Override
public String toString() {
StringBuilder sb = new StringBuilder(Timestamp.class.getSimpleName());
final StringBuilder sb = new StringBuilder(Timestamp.class.getSimpleName());
sb.append('{');
sb.append("d=").append(Constants.DEBUG ? MTLog.formatDateTime(getDepartureT()) : getDepartureT());
if (this.originalDepartureDelayMs != 0L) {
Expand Down Expand Up @@ -809,7 +816,7 @@ public String toString() {
private static final String JSON_STOP_SEQUENCE = "stop_seq";
private static final String JSON_HEADSIGN_TYPE = "ht";
private static final String JSON_HEADSIGN_VALUE = "hv";
private static final String JSON_LOCAL_TIME_ZONE = "localTimeZone";
private static final String JSON_LOCAL_TIME_ZONE_ID = "localTimeZone";
private static final String JSON_REAL_TIME = "rt";
private static final String JSON_OLD_SCHEDULE = "old";
private static final String JSON_ACCESSIBLE = "a11y";
Expand All @@ -819,7 +826,14 @@ public String toString() {
static Timestamp parseJSON(@NonNull JSONObject jTimestamp) {
try {
final long departureInMs = jTimestamp.getLong(JSON_DEPARTURE);
final Timestamp timestamp = new Timestamp(departureInMs);
final String localTimeZoneId = JSONUtils.optString(jTimestamp, JSON_LOCAL_TIME_ZONE_ID);
if (localTimeZoneId == null) {
if (BuildConfig.DEBUG) {
throw new IllegalStateException("Timestamp missing timezone in JSON!");
}
MTLog.w(LOG_TAG, "Timestamp missing timezone in JSON '%s'!", jTimestamp);
}
final Timestamp timestamp = new Timestamp(departureInMs, localTimeZoneId);
final long originalDepartureDelayMs = jTimestamp.optLong(JSON_ORIGINAL_DEPARTURE_DELAY, 0L);
if (originalDepartureDelayMs != 0L) {
timestamp.setOriginalDepartureDelayMs(originalDepartureDelayMs);
Expand All @@ -846,10 +860,6 @@ static Timestamp parseJSON(@NonNull JSONObject jTimestamp) {
timestamp.setHeadsign(headSignType, null);
}
}
final String localTimeZone = jTimestamp.optString(JSON_LOCAL_TIME_ZONE);
if (!TextUtils.isEmpty(localTimeZone)) {
timestamp.setLocalTimeZoneId(localTimeZone);
}
if (jTimestamp.has(JSON_REAL_TIME)) {
timestamp.setRealTime(jTimestamp.optBoolean(JSON_REAL_TIME, false));
}
Expand Down Expand Up @@ -879,6 +889,9 @@ public static JSONObject toJSON(@NonNull Timestamp timestamp) {
try {
final JSONObject jTimestamp = new JSONObject();
jTimestamp.put(JSON_DEPARTURE, timestamp.departureInMs);
if (timestamp.localTimeZoneId != null) {
jTimestamp.put(JSON_LOCAL_TIME_ZONE_ID, timestamp.localTimeZoneId);
}
if (timestamp.originalDepartureDelayMs != 0L) {
jTimestamp.put(JSON_ORIGINAL_DEPARTURE_DELAY, timestamp.originalDepartureDelayMs);
}
Expand All @@ -902,9 +915,6 @@ public static JSONObject toJSON(@NonNull Timestamp timestamp) {
jTimestamp.put(JSON_HEADSIGN_TYPE, timestamp.headsignType);
}
}
if (timestamp.localTimeZoneId != null) {
jTimestamp.put(JSON_LOCAL_TIME_ZONE, timestamp.localTimeZoneId);
}
if (timestamp.realTime != null) {
jTimestamp.put(JSON_REAL_TIME, timestamp.realTime);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ fun makeSchedule(
readFromSourceAtInMs: Long,
providerPrecisionInMs: Long,
isNoPickup: Boolean = false,
localTimeZoneId: String?,
sourceLabel: String? = null,
noData: Boolean = false
noData: Boolean = false,
) = Schedule(
id,
targetUUID,
Expand All @@ -30,6 +31,7 @@ fun makeSchedule(
readFromSourceAtInMs,
providerPrecisionInMs,
isNoPickup,
localTimeZoneId,
sourceLabel,
noData,
)
Expand All @@ -39,6 +41,7 @@ fun RouteDirectionStop.makeSchedule(
maxValidityInMs: Long,
readFromSourceAtInMs: Long,
providerPrecisionInMs: Long,
localTimeZoneId: String,
sourceLabel: String,
noData: Boolean,
) = makeSchedule(
Expand All @@ -47,6 +50,7 @@ fun RouteDirectionStop.makeSchedule(
maxValidityInMs = maxValidityInMs,
readFromSourceAtInMs = readFromSourceAtInMs,
providerPrecisionInMs = providerPrecisionInMs,
localTimeZoneId = localTimeZoneId,
sourceLabel = sourceLabel,
noData = noData
).apply {
Expand All @@ -61,6 +65,7 @@ fun Schedule.toNoData() = makeSchedule(
readFromSourceAtInMs = readFromSourceAtInMs,
providerPrecisionInMs = providerPrecisionInMs,
isNoPickup = isNoPickup,
localTimeZoneId = localTimeZoneId,
sourceLabel = sourceLabel,
noData = true // NO DATA
)
Expand Down Expand Up @@ -264,6 +269,7 @@ fun Schedule.Timestamp.toStringShort() = buildString {
if (tripId != null) {
append("[tId:").append(tripId).append("]")
}
//noinspection DiscouragedApi
localTimeZoneId?.let {
append("[tz:").append(it).append("]")
}
Expand Down
Loading
Loading