Add workaround for crash when DST rules are unknown (#5914)

This commit is contained in:
José Rebelo
2026-03-20 21:41:08 +00:00
parent b92985fc3b
commit 4cb5a9e34d
6 changed files with 85 additions and 29 deletions
@@ -93,9 +93,15 @@ public class TimeChangeReceiver extends BroadcastReceiver {
*/
public static void scheduleNextDstChangeOrPeriodicSync(final Context context) {
final ZoneId zoneId = ZoneId.systemDefault();
final ZoneRules zoneRules = zoneId.getRules();
final Instant now = Instant.now();
final ZoneOffsetTransition transition = zoneRules.nextTransition(now);
ZoneOffsetTransition transition = null;
try {
// Guard against #5914
final ZoneRules zoneRules = zoneId.getRules();
transition = zoneRules.nextTransition(now);
} catch (final Exception e) {
LOG.error("Failed to get next transition for {}", zoneId, e);
}
final Intent i = new Intent(ACTION_DST_CHANGED_OR_PERIODIC_SYNC);
i.setPackage(BuildConfig.APPLICATION_ID);
@@ -17,6 +17,9 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.casio;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
@@ -32,8 +35,8 @@ import java.time.zone.ZoneOffsetTransition;
import java.time.zone.ZoneOffsetTransitionRule;
import java.time.zone.ZoneRules;
public class CasioTimeZone {
private static final Logger LOG = LoggerFactory.getLogger(CasioTimeZone.class);
/*
There are six clocks on the Casio GW-B5600 / S100
@@ -108,12 +111,12 @@ PONTA DELGADA E4 00 FC 04 02
*/
private byte[] name;
private byte[] number;
private byte offset;
private byte dstOffset;
private byte dstRules;
private byte dstSetting;
private final byte[] name;
private final byte[] number;
private final byte offset;
private final byte dstOffset;
private final byte dstRules;
private final byte dstSetting;
// bitwise flags
final static byte DST_SETTING_ON = 1;
@@ -129,7 +132,7 @@ PONTA DELGADA E4 00 FC 04 02
}
static public Set<Casio2C2DSupport.FeatureRequest> requests(int slot) {
HashSet<Casio2C2DSupport.FeatureRequest> requests = new HashSet();
HashSet<Casio2C2DSupport.FeatureRequest> requests = new HashSet<>();
requests.add(new Casio2C2DSupport.FeatureRequest(Casio2C2DSupport.FEATURE_DST_WATCH_STATE, (byte) (slot/2*2)));
requests.add(new Casio2C2DSupport.FeatureRequest(Casio2C2DSupport.FEATURE_DST_SETTING, (byte) slot));
requests.add(new Casio2C2DSupport.FeatureRequest(Casio2C2DSupport.FEATURE_WORLD_CITY, (byte) slot));
@@ -217,15 +220,23 @@ PONTA DELGADA E4 00 FC 04 02
byte dstRules = 0;
byte dstSetting = 0;
ZoneOffsetTransition next = rules.nextTransition(time);
int nextYear = next.getInstant().atZone(zone).getYear();
ZoneOffsetTransition next2 = (next == null ? null: rules.nextTransition(next.getInstant()));
int next2Year = (next2 == null ? 0 : next2.getInstant().atZone(zone).getYear());
ZoneOffsetTransition next = null;
ZoneOffsetTransition next2 = null;
try {
// Guard against #5914
next = rules.nextTransition(time);
next2 = (next == null ? null: rules.nextTransition(next.getInstant()));
} catch (final Exception e) {
LOG.error("Failed to get next transition for {}", zone.getId(), e);
}
if (next == null) {
// no DST is easy
dstSetting = DST_SETTING_AUTO;
} else {
final int nextYear = next.getInstant().atZone(zone).getYear();
final int next2Year = (next2 == null ? 0 : next2.getInstant().atZone(zone).getYear());
// we need an Instant with DST on to get the dstOffset
if (rules.isDaylightSavings(time)) {
dstOffset = (byte) (rules.getDaylightSavings(time).getSeconds() / 60 / 15);
@@ -28,11 +28,19 @@ public class CurrentTimeRequestMessage extends GFDIMessage {
protected boolean generateOutgoing() {
final Instant now = Instant.now();
final ZoneRules zoneRules = ZoneId.systemDefault().getRules();
final ZoneId zoneId = ZoneId.systemDefault();
final ZoneRules zoneRules = zoneId.getRules();
final int dstOffset = (int) zoneRules.getDaylightSavings(now).getSeconds();
final int timeZoneOffset = TimeZone.getDefault().getOffset(now.toEpochMilli()) / 1000;
final int garminTimestamp = GarminTimeUtils.unixTimeToGarminTimestamp((int) now.getEpochSecond());
final ZoneOffsetTransition nextTransitionStart = zoneRules.nextTransition(now);
ZoneOffsetTransition nextTransitionStart = null;
try {
// Guard against #5914
nextTransitionStart = zoneRules.nextTransition(now);
} catch (final Exception e) {
LOG.error("Failed to get next transition for {}", zoneId, e);
}
final int nextTransitionEndsGarminTs;
final int nextTransitionStartsGarminTs;
@@ -41,7 +49,13 @@ public class CurrentTimeRequestMessage extends GFDIMessage {
final int nextTransitionStartsTs = (int) nextTransitionStart.toEpochSecond();
nextTransitionStartsGarminTs = GarminTimeUtils.unixTimeToGarminTimestamp(nextTransitionStartsTs);
final ZoneOffsetTransition nextTransitionEnd = zoneRules.nextTransition(nextTransitionStart.getInstant());
ZoneOffsetTransition nextTransitionEnd = null;
try {
// Guard against #5914
nextTransitionEnd = zoneRules.nextTransition(nextTransitionStart.getInstant());
} catch (final Exception e) {
LOG.error("Failed to get next transition end for {}", zoneId, e);
}
if (nextTransitionEnd != null) {
final int nextTransitionEndsTs = (int) nextTransitionEnd.toEpochSecond();
@@ -91,7 +91,13 @@ public class ZeppOsTimeService extends AbstractZeppOsService {
public void setNextDst(final ZeppOsTransactionBuilder builder) {
final ZoneId zoneId = ZoneId.systemDefault();
final ZoneRules rules = zoneId.getRules();
final ZoneOffsetTransition nextTransition = rules.nextTransition(Instant.now());
final ZoneOffsetTransition nextTransition;
try {
nextTransition = rules.nextTransition(Instant.now());
} catch (final Exception e) {
LOG.error("Failed to get next transition", e);
return;
}
if (nextTransition == null) {
return;
}
@@ -133,22 +133,31 @@ public class ZeppOsWorldClocksService extends AbstractZeppOsService {
final ZoneRules zoneRules = zoneId.getRules();
if (useDaylightTime) {
final ZoneOffsetTransition transition;
if (inDaylightTime) {
daylightByte = 0x01;
transition = zoneRules.previousTransition(Instant.now());
} else {
daylightByte = 0x02;
transition = zoneRules.nextTransition(Instant.now());
ZoneOffsetTransition transition = null;
try {
if (inDaylightTime) {
daylightByte = 0x01;
transition = zoneRules.previousTransition(Instant.now());
} else {
daylightByte = 0x02;
transition = zoneRules.nextTransition(Instant.now());
}
} catch (final Exception e) {
LOG.error("Failed to get transition", e);
}
daylightOffsetMinutes = (byte) transition.getDuration().toMinutes();
daylightOffsetMinutes = (byte) (transition != null ? transition.getDuration().toMinutes() : 0);
}
baos.write(daylightByte);
baos.write(daylightOffsetMinutes);
// The timestamp of the next daylight savings transition, if any
final ZoneOffsetTransition nextTransition = zoneRules.nextTransition(Instant.now());
ZoneOffsetTransition nextTransition = null;
try {
nextTransition = zoneRules.nextTransition(Instant.now());
} catch (final Exception e) {
LOG.error("Failed to get neext transition", e);
}
long nextTransitionTs = 0;
if (nextTransition != null) {
nextTransitionTs = nextTransition
@@ -16,6 +16,9 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.withingssteelhr.communication.datastructures;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
import java.time.Instant;
import java.time.ZoneId;
@@ -24,6 +27,7 @@ import java.time.zone.ZoneRules;
import java.util.TimeZone;
public class Time extends WithingsStructure {
private static final Logger LOG = LoggerFactory.getLogger(Time.class);
private Instant now;
private int timeOffsetInSeconds;
@@ -35,8 +39,14 @@ public class Time extends WithingsStructure {
final TimeZone timezone = TimeZone.getDefault();
timeOffsetInSeconds = timezone.getOffset(now.toEpochMilli()) / 1000;
final ZoneId zoneId = ZoneId.systemDefault();
final ZoneRules zoneRules = zoneId.getRules();
final ZoneOffsetTransition nextTransition = zoneRules.nextTransition(Instant.now());
ZoneOffsetTransition nextTransition = null;
try {
// Guard against #5914
final ZoneRules zoneRules = zoneId.getRules();
nextTransition = zoneRules.nextTransition(Instant.now());
} catch (final Exception e) {
LOG.error("Failed to get next transition for {}", zoneId, e);
}
long nextTransitionTs = 0;
if (nextTransition != null) {
nextTransitionTs = nextTransition.getDateTimeBefore().atZone(zoneId).toEpochSecond();