Skip to content

Commit

Permalink
Fix leap seconds calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
propensive committed Jan 25, 2025
1 parent 51646a8 commit fd11eb9
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 41 deletions.
6 changes: 4 additions & 2 deletions src/core/aviation.Aviation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)}
Expand Down
4 changes: 2 additions & 2 deletions src/core/aviation.LeapSeconds.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
14 changes: 7 additions & 7 deletions src/core/soundness+aviation-core.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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}
77 changes: 47 additions & 30 deletions src/test/aviation.Tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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"):
Expand Down

0 comments on commit fd11eb9

Please sign in to comment.