Я не вижу, чтобы ты был полностью уверен. «Солнце 3 ноября» может быть в 2002, 2013 или 2019 году или даже в далеком прошлом. Одним из способов будет, если вы предположите, что время последней синхронизации не превышает, скажем, несколько лет до текущего системного времени системы B, которое вы получите (а также не после этого времени), и сообщите ошибка, если вы можете обнаружить, что это не в течение этих нескольких лет.
Хитрость, когда заканчивается летнее время (переход на летнее время), состоит в том, чтобы всегда предполагать более раннее время, если есть какая-либо неопределенность. Таким образом, когда вы обнаруживаете, что время синхронизации позже, чем отметка времени от A, это верно независимо от того, как интерпретируется неоднозначное время синхронизации. Это также означает, что вы будете ждать, пока время последней синхронизации не наступит после 2:00, как вы предложили. Я не ожидал бы, что это будет слишком дорого с точки зрения сравнения, но если вам нужно быть уверенным, вам нужно сделать свои собственные измерения и суждения.
final DateTimeFormatter timestampFormatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd-HH-mm-ss");
final ZoneId systemBTimeZone = ZoneId.of("America/New_York");
final String syncFormatPattern = "'Sync''ed-as-of time:' EEE MMM d HH:mm";
final DateTimeFormatter currentSystemBTiemFormatter = new DateTimeFormatterBuilder()
.appendPattern("EEE MMM dd HH:mm:ss ")
.appendZoneText(TextStyle.SHORT, Collections.singleton(systemBTimeZone))
.appendPattern(" yyyy")
.toFormatter(Locale.US);
final Period maxSyncAge = Period.ofYears(2);
String systemATimestampString = "2019-11-03-06-05-55";
String lastSyncMsg = "Sync'ed-as-of time: Sun Nov 3 01:13";
String currentSystemBTime = "Sun Nov 03 01:13:07 EDT 2019";
OffsetDateTime systemATimestamp = LocalDateTime.parse(systemATimestampString, timestampFormatter)
.atOffset(ZoneOffset.UTC);
ZonedDateTime maxLastSyncTime
= ZonedDateTime.parse(currentSystemBTime, currentSystemBTiemFormatter);
ZonedDateTime minLatSyncTime = maxLastSyncTime.minus(maxSyncAge);
int candidateYear = maxLastSyncTime.getYear();
ZonedDateTime syncTime;
while (true) {
DateTimeFormatter syncFormatter = new DateTimeFormatterBuilder()
.appendPattern(syncFormatPattern)
.parseDefaulting(ChronoField.YEAR, candidateYear)
.toFormatter(Locale.US);
try {
syncTime = LocalDateTime.parse(lastSyncMsg, syncFormatter)
.atZone(systemBTimeZone)
.withEarlierOffsetAtOverlap();
if (syncTime.isBefore(minLatSyncTime) || syncTime.isAfter(maxLastSyncTime)) {
throw new IllegalStateException("Last sync time is out of range");
}
break;
} catch (DateTimeParseException dtpe) {
// Ignore; try next earlier year
}
candidateYear--;
}
System.out.println("Last sync time: " + syncTime);
System.out.println("Timestamp from system A: " + systemATimestamp);
System.out.println("Is OK? " + syncTime.toOffsetDateTime().isAfter(systemATimestamp));
При наличии фрагмента на выходе получается:
Last sync time: 2019-11-03T01:13-04:00[America/New_York]
Timestamp from system A: 2019-11-03T06:05:55Z
Is OK? false
Вы можете видеть, что он выбрал интерпретацию времени последней синхронизации 01:13 как летнего времени, смещение -04: 00, что приводит к сбою проверки. Время также могло бы быть в стандартном времени, смещение -05: 00, в этом случае UTC-эквивалент был бы 06:13, и проверка прошла бы успешно. Но, как уже говорилось, чтобы быть в безопасности, мы предпочитаем подождать, пока время синхронизации не пройдет после 02:00 и снова не станет однозначным.
Цикл while продолжает синтаксический анализ строки, принимая разные годы, пока не достигнет года, в котором совпадает день недели.