From fd11eb97cb4c042ee68b4bbe2de98209a251c462 Mon Sep 17 00:00:00 2001 From: Jon Pretty Date: Sat, 25 Jan 2025 11:59:50 +0100 Subject: [PATCH] Fix leap seconds calculation --- src/core/aviation.Aviation.scala | 6 +- src/core/aviation.LeapSeconds.scala | 4 +- src/core/soundness+aviation-core.scala | 14 ++--- src/test/aviation.Tests.scala | 77 ++++++++++++++++---------- 4 files changed, 60 insertions(+), 41 deletions(-) diff --git a/src/core/aviation.Aviation.scala b/src/core/aviation.Aviation.scala index d29d6e1..3138c80 100644 --- a/src/core/aviation.Aviation.scala +++ b/src/core/aviation.Aviation.scala @@ -48,8 +48,10 @@ object Aviation: val h: Base24 = (hour + (if pm then 12 else 0)).asInstanceOf[Base24] val length = lit.pos.endColumn - lit.pos.startColumn - if (hour < 10 && length != 4) || (hour >= 10 && length != 5) - then halt(m"the time should have exactly two minutes digits", lit.pos) + if (hour < 10 && length != 4) || (hour >= 10 && length != 5) then + if length == 0 + then warn(m"time is unchecked because range positions are not available") + else halt(m"the time should have exactly two minutes digits", lit.pos) val m: Base60 = minutes.asInstanceOf[Base60] '{Clockface(${Expr[Base24](h)}, ${Expr[Base60](m)}, 0)} diff --git a/src/core/aviation.LeapSeconds.scala b/src/core/aviation.LeapSeconds.scala index 0b741c2..233c743 100644 --- a/src/core/aviation.LeapSeconds.scala +++ b/src/core/aviation.LeapSeconds.scala @@ -32,11 +32,11 @@ object LeapSeconds: if midYear then june |= (Long.MinValue >> (year - 1972)) else december |= (Long.MinValue >> (year - 1972)) - def before(year: Int, plusSixMonths: Boolean): Int = + def during(year: Int, plusSixMonths: Boolean): Int = before((year - 1972)*2 + (if plusSixMonths then 1 else 0)) private def before(n: Int): Int = - inline def ones(long: Long): Int = long.bits.ones.int + inline def ones(long: Long): Int = java.lang.Long.bitCount(long) val decemberShift = n.min(127)/2 val juneShift = decemberShift + n%2 diff --git a/src/core/soundness+aviation-core.scala b/src/core/soundness+aviation-core.scala index 5bdce38..9f60d22 100644 --- a/src/core/soundness+aviation-core.scala +++ b/src/core/soundness+aviation-core.scala @@ -16,13 +16,13 @@ package soundness -export aviation.{Base24, Base60, Calendar, Clock, Clockface, DateError, Denomination, - DiurnalTimespan, FixedDuration, Horology, Period, LeapSeconds, LocalTime, MonthName, - RomanCalendar, StandardTime, TemporalTimespan, Timespan, Timestamp, TimeSystem, Timezone, - TimezoneError, Timing, Tzdb, TzdbError, Weekday, YearMonth, now, today, TimeEvent, am, pm, - year, month, week, day, hour, minute, second, years, months, weeks, days, hours, minutes, - seconds, tz, TimestampError, Instant, Duration, Date, Jan, Feb, Mar, Apr, May, Jun, Jul, - Aug, Sep, Oct, Nov, Dec} +export aviation . + { Base24, Base60, Calendar, Clock, Clockface, DateError, Denomination, DiurnalTimespan, + FixedDuration, Horology, Period, LeapSeconds, LocalTime, MonthName, RomanCalendar, StandardTime, + TemporalTimespan, Timespan, Timestamp, TimeSystem, Timezone, TimezoneError, Timing, Tzdb, + TzdbError, Weekday, YearMonth, now, today, TimeEvent, am, pm, year, month, week, day, hour, + minute, second, years, months, weeks, days, hours, minutes, seconds, tz, TimestampError, + Instant, Duration, Date, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec} package calendars: export aviation.calendars.{gregorian, julian} diff --git a/src/test/aviation.Tests.scala b/src/test/aviation.Tests.scala index 4bb0d23..2813c87 100644 --- a/src/test/aviation.Tests.scala +++ b/src/test/aviation.Tests.scala @@ -16,13 +16,10 @@ package aviation -import contingency.* -import gossamer.* -import probably.* -import rudiments.* -import spectacular.* +import soundness.* import strategies.throwUnsafely +import errorDiagnostics.stackTraces object Tests extends Suite(t"Aviation Tests"): def run(): Unit = @@ -58,55 +55,75 @@ object Tests extends Suite(t"Aviation Tests"): suite(t""): test(t"There are 10 leap seconds for any year before 1972"): - LeapSeconds.before(1900, false) + LeapSeconds.during(1900, false) .assert(_ == 10) - test(t"There are 10 leap seconds before 1972"): - LeapSeconds.before(1972, false) + test(t"There are 10 leap seconds in the first half of 1972"): + LeapSeconds.during(1972, false) .assert(_ == 10) - test(t"There are 11 leap seconds before mid-1972"): - LeapSeconds.before(1972, true) + test(t"There are 11 leap seconds in the second half of 1972"): + LeapSeconds.during(1972, true) .assert(_ == 11) - test(t"There are 12 leap seconds before 1973"): - LeapSeconds.before(1973, false) + test(t"There are 12 leap seconds in the first half of 1973"): + LeapSeconds.during(1973, false) .assert(_ == 12) - test(t"There are 12 leap seconds before mid-1973"): - LeapSeconds.before(1973, true) + test(t"There are 12 leap seconds in the second half of 1973"): + LeapSeconds.during(1973, true) .assert(_ == 12) - test(t"There are 13 leap seconds before 1974"): - LeapSeconds.before(1974, false) + test(t"There are 13 leap seconds in the first half of 1974"): + LeapSeconds.during(1974, false) .assert(_ == 13) - test(t"There are 13 leap seconds before mid-1974"): - LeapSeconds.before(1974, true) + test(t"There are 13 leap seconds in the second half of 1974"): + LeapSeconds.during(1974, true) .assert(_ == 13) - test(t"There are 19 leap seconds before 1981"): - LeapSeconds.before(1981, false) + test(t"There are 19 leap seconds in the first half of 1980"): + LeapSeconds.during(1980, false).tap(println) .assert(_ == 19) - test(t"There are 20 leap seconds before mid-1981"): - LeapSeconds.before(1981, true) + test(t"There are 19 leap seconds in the first half of 1981"): + LeapSeconds.during(1981, false) + .assert(_ == 19) + + test(t"There are 20 leap seconds in the second half of 1981"): + LeapSeconds.during(1981, true) + .assert(_ == 20) + + test(t"There are 19 leap seconds in the first half of 1981"): + LeapSeconds.during(1981, false) + .assert(_ == 19) + + test(t"There are 20 leap seconds in the second half of 1981"): + LeapSeconds.during(1981, true) .assert(_ == 20) - test(t"There are 20 leap seconds before 1982"): - LeapSeconds.before(1982, false) + test(t"There are 20 leap seconds in the first half of 1982"): + LeapSeconds.during(1982, false) .assert(_ == 20) - test(t"There are 20 leap seconds before mid-1982"): - LeapSeconds.before(1982, true) + test(t"There are 21 leap seconds in the second half of 1982"): + LeapSeconds.during(1982, true) .assert(_ == 21) - test(t"There are 37 leap seconds before 2017"): - LeapSeconds.before(2017, false) + test(t"There are 24 leap seconds in the second half of 1988"): + LeapSeconds.during(1988, true) + .assert(_ == 24) + + test(t"There are 32 leap seconds in the first half of 2000"): + LeapSeconds.during(2000, false) + .assert(_ == 32) + + test(t"There are 37 leap seconds in the first half of 2017"): + LeapSeconds.during(2017, false) .assert(_ == 37) - test(t"There are 37 leap seconds before 2100"): - LeapSeconds.before(2100, false) + test(t"There are 37 leap seconds in the first half of 2100"): + LeapSeconds.during(2100, false) .assert(_ == 37) suite(t"Gregorian Calendar Tests"):