diff --git a/src/munge.js b/src/munge.js index c23cddd..de13cb7 100644 --- a/src/munge.js +++ b/src/munge.js @@ -34,7 +34,7 @@ export const MODELS = { } const NOV = 10 -const secondsPerDay = new Second(86_400n, 1n) +const secondsPerDay = new Second(new Rat(86_400n, 1n)) const mjdEpoch = { unix: Second.fromMillis(Date.UTC(1858, NOV, 17)) } @@ -63,20 +63,20 @@ export const munge = (data, model) => { // Convert from a floating point number to a precise ratio // Offsets are given in TAI seconds to seven decimal places, e.g. `1.422_818_0`. // So we have to do some rounding - offsetAtRoot.atomic = new Second( + offsetAtRoot.atomic = new Second(new Rat( BigInt(Math.round(offsetAtRoot.atomicFloat * 10_000_000)), BigInt(10_000_000) - ) + )) root.unix = mjdEpoch.unix.plusS(secondsPerDay.timesR(new Rat(BigInt(root.mjds)))) // Convert from a floating point number to a precise ratio // Drift rates are given in TAI seconds to seven decimal places, e.g. `0.001_123_2` // So we have to do some rounding - driftRate.atomicPerUnixDay = new Second( + driftRate.atomicPerUnixDay = new Second(new Rat( BigInt(Math.round(driftRate.atomicPerUnixDayFloat * 10_000_000)), BigInt(10_000_000) - ) + )) driftRate.atomicPerUnix = driftRate.atomicPerUnixDay.divideS(secondsPerDay) const slope = {} @@ -104,7 +104,7 @@ export const munge = (data, model) => { : Second.END_OF_TIME } - if (datum.end.atomic.leS(datum.start.atomic)) { + if (datum.end.atomic === Second.END_OF_TIME ? datum.start.atomic === Second.END_OF_TIME : datum.end.atomic.leS(datum.start.atomic)) { throw Error('Disordered data') } }) diff --git a/src/rat.js b/src/rat.js index 43bd3ec..0df865d 100644 --- a/src/rat.js +++ b/src/rat.js @@ -3,13 +3,13 @@ import { div, gcd } from './div.js' export class Rat { constructor (nu, de = 1n) { if (typeof nu !== 'bigint') { - throw Error('Numerator must be a BigInt') + throw Error('numerator must be a BigInt') } if (typeof de !== 'bigint') { - throw Error('Denominator must be a BigInt') + throw Error('denominator must be a BigInt') } - if (de === 0n && nu <= 0n) { - throw Error('Numerator must be positive if denominator is zero') + if (de === 0n) { + throw Error('denominator cannot be zero') } const g = gcd(nu, de) // non-zero @@ -17,13 +17,10 @@ export class Rat { const g2 = (de < 0) === (g < 0) ? g : -g this.nu = nu / g2 // sign of `this.nu` is the sign of the represented rational - this.de = de / g2 // non-negative + this.de = de / g2 // positive } plus (other) { - if (this.de === 0n && other.de === 0n) { - return new Rat(this.nu + other.nu, 0n) - } return new Rat(this.nu * other.de + this.de * other.nu, this.de * other.de) } @@ -56,5 +53,3 @@ export class Rat { return div(this.nu, this.de) } } - -Rat.INFINITY = new Rat(1n, 0n) diff --git a/src/second.js b/src/second.js index fffe134..49e2e3d 100644 --- a/src/second.js +++ b/src/second.js @@ -1,28 +1,24 @@ import { Rat } from './rat.js' export class Second { - constructor (nu, de) { - this.rat = new Rat(nu, de) + constructor (rat) { + this.rat = rat } plusS (other) { - const sum = this.rat.plus(other.rat) - return new Second(sum.nu, sum.de) + return new Second(this.rat.plus(other.rat)) } minusS (other) { - const difference = this.rat.minus(other.rat) - return new Second(difference.nu, difference.de) + return new Second(this.rat.minus(other.rat)) } timesR (other) { - const product = this.rat.times(other) - return new Second(product.nu, product.de) + return new Second(this.rat.times(other)) } divideR (other) { - const quotient = this.rat.divide(other) - return new Second(quotient.nu, quotient.de) + return new Second(this.rat.divide(other)) } divideS (other) { @@ -51,10 +47,7 @@ Second.fromMillis = millis => { throw Error(`Not an integer: ${millis}`) } - return new Second(BigInt(millis), 1_000n) + return new Second(new Rat(BigInt(millis), 1_000n)) } -// Support for this special value is limited. In all cases it either returns -// a correct, meaningful result, or throws an exception - it does NOT return -// bad results. -Second.END_OF_TIME = new Second(1n, 0n) +Second.END_OF_TIME = Symbol('end of time') diff --git a/src/segment.js b/src/segment.js index 3034be2..c26f63f 100644 --- a/src/segment.js +++ b/src/segment.js @@ -9,19 +9,19 @@ import { Second } from './second.js' export class Segment { constructor (start, end = { atomic: Second.END_OF_TIME }, slope = { unixPerAtomic: new Rat(1n) }) { if (!(start.atomic instanceof Second)) { - throw Error('TAI start must be a rational number of seconds') + throw Error('TAI start must be a `Second`') } if (!(start.unix instanceof Second)) { - throw Error('Unix start must be a rational number of seconds') + throw Error('Unix start must be a `Second`') } - if (!(end.atomic instanceof Second)) { - throw Error('TAI end must be a rational number of seconds') + if (!(end.atomic instanceof Second || end.atomic === Second.END_OF_TIME)) { + throw Error('TAI end must be a `Second` or `Second.END_OF_TIME`') } if (!(slope.unixPerAtomic instanceof Rat)) { - throw Error('Slope must be a pure ratio') + throw Error('slope must be a `Rat`') } - if (end.atomic.leS(start.atomic)) { - throw Error('Segment length must be positive') + if (end.atomic === Second.END_OF_TIME ? start.atomic === Second.END_OF_TIME : end.atomic.leS(start.atomic)) { + throw Error('segment length must be positive') } this.slope = { @@ -59,6 +59,10 @@ export class Segment { } atomicToUnix (atomic) { + if (atomic === Second.END_OF_TIME) { + return Second.END_OF_TIME + } + return atomic .minusS(this.start.atomic) .timesR(this.slope.unixPerAtomic) @@ -71,12 +75,12 @@ export class Segment { // Unix by the segment. atomicOnSegment (atomic) { - return this.start.atomic.leS(atomic) && this.end.atomic.gtS(atomic) + return this.start.atomic.leS(atomic) && (this.end.atomic === Second.END_OF_TIME ? atomic !== Second.END_OF_TIME : this.end.atomic.gtS(atomic)) } unixOnSegment (unix) { return this.slope.unixPerAtomic.eq(new Rat(0n)) ? this.start.unix.eqS(unix) - : this.start.unix.leS(unix) && this.end.unix.gtS(unix) + : this.start.unix.leS(unix) && (this.end.unix === Second.END_OF_TIME ? unix !== Second.END_OF_TIME : this.end.unix.gtS(unix)) } } diff --git a/test/converter.spec.js b/test/converter.spec.js index 70b9033..a9dfac8 100644 --- a/test/converter.spec.js +++ b/test/converter.spec.js @@ -3,6 +3,7 @@ import { describe, it } from 'mocha' import { Converter } from '../src/converter.js' import { MODELS } from '../src/munge.js' import { Range } from '../src/range.js' +import { Rat } from '../src/rat.js' import { Second } from '../src/second.js' const JAN = 0 @@ -267,7 +268,7 @@ describe('Converter', () => { ]) assert.deepStrictEqual(converter.unixToAtomic(Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 1))), [ - new Range(Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 1)).plusS(new Second(1n, 86_400_000n))) + new Range(Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 1)).plusS(new Second(new Rat(1n, 86_400_000n)))) ]) // SMEAR MIDPOINT @@ -279,7 +280,7 @@ describe('Converter', () => { // SMEAR ENDS, ATOMIC IS A FULL SECOND AHEAD (actually Unix is a full second behind) assert.deepStrictEqual(converter.unixToAtomic(Second.fromMillis(Date.UTC(1980, JAN, 1, 11, 59, 59, 999))), [ - new Range(Second.fromMillis(Date.UTC(1980, JAN, 1, 11, 59, 59, 999)).plusS(new Second(86_399_999n, 86_400_000n))) + new Range(Second.fromMillis(Date.UTC(1980, JAN, 1, 11, 59, 59, 999)).plusS(new Second(new Rat(86_399_999n, 86_400_000n)))) ]) assert.deepStrictEqual(converter.unixToAtomic(Second.fromMillis(Date.UTC(1980, JAN, 1, 12, 0, 0, 0))), [ @@ -301,7 +302,7 @@ describe('Converter', () => { assert.deepStrictEqual(converter.atomicToUnix(Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 0))), Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 0))) assert.deepStrictEqual(converter.atomicToUnix(Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 1))), - Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 1)).minusS(new Second(1n, 86_401_000n))) + Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 1)).minusS(new Second(new Rat(1n, 86_401_000n)))) // SMEAR MIDPOINT assert.deepStrictEqual(converter.atomicToUnix(Second.fromMillis(Date.UTC(1980, JAN, 1, 0, 0, 0, 500))), @@ -309,7 +310,7 @@ describe('Converter', () => { // SMEAR ENDS, UNIX HAS DROPPED A FULL SECOND BEHIND assert.deepStrictEqual(converter.atomicToUnix(Second.fromMillis(Date.UTC(1980, JAN, 1, 12, 0, 0, 999))), - Second.fromMillis(Date.UTC(1980, JAN, 1, 12, 0, 0, 999)).minusS(new Second(86_400_999n, 86_401_000n))) + Second.fromMillis(Date.UTC(1980, JAN, 1, 12, 0, 0, 999)).minusS(new Second(new Rat(86_400_999n, 86_401_000n)))) assert.deepStrictEqual(converter.atomicToUnix(Second.fromMillis(Date.UTC(1980, JAN, 1, 12, 0, 1, 0))), Second.fromMillis(Date.UTC(1980, JAN, 1, 12, 0, 0, 0))) assert.deepStrictEqual(converter.atomicToUnix(Second.fromMillis(Date.UTC(1980, JAN, 1, 12, 0, 1, 1))), @@ -482,7 +483,7 @@ describe('Converter', () => { ]) assert.deepStrictEqual(converter.unixToAtomic(Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 1))), [ - new Range(Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 1)).minusS(new Second(1n, 86_400_000n))) + new Range(Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 1)).minusS(new Second(new Rat(1n, 86_400_000n)))) ]) // SMEAR MIDPOINT @@ -494,7 +495,7 @@ describe('Converter', () => { // SMEAR ENDS, ATOMIC IS A FULL SECOND BEHIND (actually Unix is a full second ahead) assert.deepStrictEqual(converter.unixToAtomic(Second.fromMillis(Date.UTC(1980, JAN, 1, 11, 59, 59, 999))), [ - new Range(Second.fromMillis(Date.UTC(1980, JAN, 1, 11, 59, 59, 999)).minusS(new Second(86_399_999n, 86_400_000n))) + new Range(Second.fromMillis(Date.UTC(1980, JAN, 1, 11, 59, 59, 999)).minusS(new Second(new Rat(86_399_999n, 86_400_000n)))) ]) assert.deepStrictEqual(converter.unixToAtomic(Second.fromMillis(Date.UTC(1980, JAN, 1, 12, 0, 0, 0))), [ @@ -516,7 +517,7 @@ describe('Converter', () => { assert.deepStrictEqual(converter.atomicToUnix(Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 0))), Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 0))) assert.deepStrictEqual(converter.atomicToUnix(Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 1))), - Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 1)).plusS(new Second(1n, 86_399_000n))) + Second.fromMillis(Date.UTC(1979, DEC, 31, 12, 0, 0, 1)).plusS(new Second(new Rat(1n, 86_399_000n)))) // SMEAR MIDPOINT assert.deepStrictEqual(converter.atomicToUnix(Second.fromMillis(Date.UTC(1979, DEC, 31, 23, 59, 59, 500))), @@ -524,7 +525,7 @@ describe('Converter', () => { // SMEAR ENDS, UNIX HAS RUN A FULL SECOND FASTER THAN ATOMIC assert.deepStrictEqual(converter.atomicToUnix(Second.fromMillis(Date.UTC(1980, JAN, 1, 11, 59, 58, 999))), - Second.fromMillis(Date.UTC(1980, JAN, 1, 11, 59, 58, 999)).plusS(new Second(86_398_999n, 86_399_000n))) + Second.fromMillis(Date.UTC(1980, JAN, 1, 11, 59, 58, 999)).plusS(new Second(new Rat(86_398_999n, 86_399_000n)))) assert.deepStrictEqual(converter.atomicToUnix(Second.fromMillis(Date.UTC(1980, JAN, 1, 11, 59, 59, 0))), Second.fromMillis(Date.UTC(1980, JAN, 1, 12, 0, 0, 0))) assert.deepStrictEqual(converter.atomicToUnix(Second.fromMillis(Date.UTC(1980, JAN, 1, 11, 59, 59, 1))), @@ -543,9 +544,9 @@ describe('Converter', () => { assert.deepStrictEqual(converter.unixToAtomic(Second.fromMillis(1)), [ - new Range(new Second(900n, 1_000_000n)) + new Range(new Second(new Rat(900n, 1_000_000n))) ]) - assert.deepStrictEqual(converter.atomicToUnix(new Second(900n, 1_000_000n)), + assert.deepStrictEqual(converter.atomicToUnix(new Second(new Rat(900n, 1_000_000n))), Second.fromMillis(1)) }) @@ -558,9 +559,9 @@ describe('Converter', () => { assert.deepStrictEqual(converter.unixToAtomic(Second.fromMillis(-1)), [ - new Range(new Second(-900n, 1_000_000n)) + new Range(new Second(new Rat(-900n, 1_000_000n))) ]) - assert.deepStrictEqual(converter.atomicToUnix(new Second(-900n, 1_000_000n)), + assert.deepStrictEqual(converter.atomicToUnix(new Second(new Rat(-900n, 1_000_000n))), Second.fromMillis(-1)) }) }) @@ -678,14 +679,14 @@ describe('Converter', () => { describe('BREAK', () => { it('says no', () => { assert.throws(() => new Converter(data, MODELS.BREAK), - /Segment length must be positive/) + /segment length must be positive/) }) }) describe('STALL', () => { it('says no', () => { assert.throws(() => new Converter(data, MODELS.STALL), - /Segment length must be positive/) + /segment length must be positive/) }) }) }) diff --git a/test/exact.spec.js b/test/exact.spec.js index 0b06c64..504cb65 100644 --- a/test/exact.spec.js +++ b/test/exact.spec.js @@ -2,6 +2,7 @@ import assert from 'node:assert' import { describe, it } from 'mocha' import { TaiConverter, Second, MODELS, UNIX_START, UNIX_END } from '../src/exact.js' import { Range } from '../src/range.js' +import { Rat } from '../src/rat.js' const JAN = 0 const FEB = 1 @@ -48,51 +49,51 @@ describe('TaiConverter', () => { // 00:00:01.422_818 is in range, but rounds down to 00:00:01.422 which is not assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 0, 0))), [ - new Range(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 1, 422)).plusS(new Second(818_000_000n, 1_000_000_000_000n))) + new Range(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 1, 422)).plusS(new Second(new Rat(818_000_000n, 1_000_000_000_000n)))) ]) }) it('advances 15 TAI picoseconds per Unix millisecond', () => { assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 0, 1))), [ - new Range(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 1, 423)).plusS(new Second(818_000_015n, 1_000_000_000_000n))) + new Range(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 1, 423)).plusS(new Second(new Rat(818_000_015n, 1_000_000_000_000n)))) ]) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 0, 2))), [ - new Range(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 1, 424)).plusS(new Second(818_000_030n, 1_000_000_000_000n))) + new Range(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 1, 424)).plusS(new Second(new Rat(818_000_030n, 1_000_000_000_000n)))) ]) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 0, 3))), [ - new Range(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 1, 425)).plusS(new Second(818_000_045n, 1_000_000_000_000n))) + new Range(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 1, 425)).plusS(new Second(new Rat(818_000_045n, 1_000_000_000_000n)))) ]) }) it('advances 0.001_296 TAI seconds per Unix day', () => { assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1961, JAN, 2, 0, 0, 0, 0))), [ - new Range(Second.fromMillis(Date.UTC(1961, JAN, 2, 0, 0, 1, 424)).plusS(new Second(114n, 1_000_000n))) + new Range(Second.fromMillis(Date.UTC(1961, JAN, 2, 0, 0, 1, 424)).plusS(new Second(new Rat(114n, 1_000_000n)))) ]) }) it('makes certain TAI millisecond counts inaccessible', () => { assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(-283_984_666_668)), [ - new Range(new Second(-283_984_665_245_000_000_020n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-283_984_665_245_000_000_020n, 1_000_000_000_000n))) ]) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(-283_984_666_667)), [ - new Range(new Second(-283_984_665_244_000_000_005n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-283_984_665_244_000_000_005n, 1_000_000_000_000n))) ]) // it's not possible to get a result of -283_984_665_244_XXX_XXX_XXXn assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(-283_984_666_666)), [ - new Range(new Second(-283_984_665_242_999_999_990n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-283_984_665_242_999_999_990n, 1_000_000_000_000n))) ]) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(-283_984_666_665)), [ - new Range(new Second(-283_984_665_241_999_999_975n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-283_984_665_241_999_999_975n, 1_000_000_000_000n))) ]) }) }) @@ -103,7 +104,7 @@ describe('TaiConverter', () => { NaN) // Actual start of TAI: 1961-01-01 00:00:01.422_818 - assert.deepStrictEqual(taiConverter.atomicToUnix(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 1, 422)).plusS(new Second(818n, 1_000_000n))), + assert.deepStrictEqual(taiConverter.atomicToUnix(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 1, 422)).plusS(new Second(new Rat(818n, 1_000_000n)))), Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 0, 0))) }) @@ -143,7 +144,7 @@ describe('TaiConverter', () => { // Fun fact! There is about 105 leap milliseconds here! assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1972, JAN, 1, 0, 0, 0, 0))), [ - new Range(Second.fromMillis(Date.UTC(1972, JAN, 1, 0, 0, 9, 892)).plusS(new Second(242n, 1_000_000n))), + new Range(Second.fromMillis(Date.UTC(1972, JAN, 1, 0, 0, 9, 892)).plusS(new Second(new Rat(242n, 1_000_000n)))), new Range(Second.fromMillis(Date.UTC(1972, JAN, 1, 0, 0, 10, 0))) ]) }) @@ -188,15 +189,15 @@ describe('TaiConverter', () => { // TAI picosecond count rounds to -252_460_798_155 which is not in range assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1961, DEC, 31, 23, 59, 59, 999))), [ - new Range(new Second(-252_460_798_155_142_000_015n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-252_460_798_155_142_000_015n, 1_000_000_000_000n))) ]) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1962, JAN, 1, 0, 0, 0, 0))), [ - new Range(new Second(-252_460_798_154_142_000_000n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-252_460_798_154_142_000_000n, 1_000_000_000_000n))) ]) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1962, JAN, 1, 0, 0, 0, 1))), [ - new Range(new Second(-252_460_798_153_141_999_987n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-252_460_798_153_141_999_987n, 1_000_000_000_000n))) ]) }) @@ -205,8 +206,8 @@ describe('TaiConverter', () => { // The period between 1965-09-01 00:00:00 and 00:00:00.100 UTC happened twice! assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1965, SEP, 1, 0, 0, 0, 50))), [ - new Range(new Second(-136_771_195_894_941_999_250n, 1_000_000_000_000n)), - new Range(new Second(-136_771_195_794_941_999_250n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-136_771_195_894_941_999_250n, 1_000_000_000_000n))), + new Range(new Second(new Rat(-136_771_195_794_941_999_250n, 1_000_000_000_000n))) ]) }) @@ -216,11 +217,11 @@ describe('TaiConverter', () => { // Which means that 23:59:59.950 UTC *does* actually exist... assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1961, JUL, 31, 23, 59, 59, 949))), [ - new Range(new Second(-265_679_998_353_430_000_765n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-265_679_998_353_430_000_765n, 1_000_000_000_000n))) ]) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1961, JUL, 31, 23, 59, 59, 950))), [ - new Range(new Second(-265_679_998_352_430_000_750n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-265_679_998_352_430_000_750n, 1_000_000_000_000n))) ]) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1961, JUL, 31, 23, 59, 59, 951))), []) @@ -229,11 +230,11 @@ describe('TaiConverter', () => { []) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1961, AUG, 1, 0, 0, 0, 0))), [ - new Range(new Second(-265_679_998_352_430_000_000n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-265_679_998_352_430_000_000n, 1_000_000_000_000n))) ]) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1961, AUG, 1, 0, 0, 0, 1))), [ - new Range(new Second(-265_679_998_351_429_999_985n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-265_679_998_351_429_999_985n, 1_000_000_000_000n))) ]) }) @@ -290,7 +291,7 @@ describe('TaiConverter', () => { 1) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1968, JAN, 31, 23, 59, 59, 900))), [ - new Range(new Second(-60_479_993_814_318_003n, 1_000_000_000n)) + new Range(new Second(new Rat(-60_479_993_814_318_003n, 1_000_000_000n))) ]) assert.strictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1968, JAN, 31, 23, 59, 59, 901))).length, @@ -471,7 +472,7 @@ describe('TaiConverter', () => { describe('atomicToUnix', () => { it('The NEW earliest instant in TAI', () => { // Actual start of TAI: 1961-01-01 00:00:01.422_818 - assert.deepStrictEqual(taiConverter.atomicToUnix(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 1, 422)).plusS(new Second(818n, 1_000_000n))), + assert.deepStrictEqual(taiConverter.atomicToUnix(Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 1, 422)).plusS(new Second(new Rat(818n, 1_000_000n)))), Second.fromMillis(Date.UTC(1961, JAN, 1, 0, 0, 0, 0))) }) @@ -482,7 +483,7 @@ describe('TaiConverter', () => { it('0.107_758 seconds added, start of 1972', () => { // stall begins at 1972-01-01 00:00:09.892_242 TAI - assert.deepStrictEqual(taiConverter.atomicToUnix(Second.fromMillis(Date.UTC(1972, JAN, 1, 0, 0, 9, 892)).plusS(new Second(242n, 1_000_000n))), + assert.deepStrictEqual(taiConverter.atomicToUnix(Second.fromMillis(Date.UTC(1972, JAN, 1, 0, 0, 9, 892)).plusS(new Second(new Rat(242n, 1_000_000n)))), Second.fromMillis(Date.UTC(1972, JAN, 1, 0, 0, 0, 0))) assert.deepStrictEqual(taiConverter.atomicToUnix(Second.fromMillis(Date.UTC(1972, JAN, 1, 0, 0, 9, 893))), Second.fromMillis(Date.UTC(1972, JAN, 1, 0, 0, 0, 0))) @@ -547,11 +548,11 @@ describe('TaiConverter', () => { // Exact picosecond ratios assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1962, JAN, 1, 0, 0, 0, 0))), [ - new Range(new Second(-252_460_798_154_142_000_000n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-252_460_798_154_142_000_000n, 1_000_000_000_000n))) ]) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(1962, JAN, 1, 0, 0, 0, 1))), [ - new Range(new Second(-252_460_798_153_141_999_987n, 1_000_000_000_000n)) + new Range(new Second(new Rat(-252_460_798_153_141_999_987n, 1_000_000_000_000n))) ]) }) @@ -706,7 +707,7 @@ describe('TaiConverter', () => { const atomic = Second.fromMillis(63_072_010_000) assert.deepStrictEqual(taiConverter.unixToAtomic(taiConverter.atomicToUnix(atomic)), [ - new Range(atomic.minusS(new Second(107_758n, 1_000_000n)), atomic) + new Range(atomic.minusS(new Second(new Rat(107_758n, 1_000_000n))), atomic) ]) }) @@ -772,7 +773,7 @@ describe('TaiConverter', () => { ]) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(2016, DEC, 31, 12, 0, 0, 1))), [ - new Range(Second.fromMillis(Date.UTC(2016, DEC, 31, 12, 0, 36, 1)).plusS(new Second(1n, 86_400_000n))) + new Range(Second.fromMillis(Date.UTC(2016, DEC, 31, 12, 0, 36, 1)).plusS(new Second(new Rat(1n, 86_400_000n)))) ]) // After 86_400 Unix milliseconds, exactly 86_401 TAI milliseconds have passed @@ -790,7 +791,7 @@ describe('TaiConverter', () => { // SMEAR ENDS. After 24 Unix hours, 24 TAI hours and 1 second assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(2017, JAN, 1, 11, 59, 59, 999))), [ - new Range(Second.fromMillis(Date.UTC(2017, JAN, 1, 12, 0, 35, 999)).plusS(new Second(86_399_999n, 86_400_000n))) + new Range(Second.fromMillis(Date.UTC(2017, JAN, 1, 12, 0, 35, 999)).plusS(new Second(new Rat(86_399_999n, 86_400_000n)))) ]) assert.deepStrictEqual(taiConverter.unixToAtomic(Second.fromMillis(Date.UTC(2017, JAN, 1, 12, 0, 0, 0))), [ diff --git a/test/millis-converter.spec.js b/test/millis-converter.spec.js index 35748e0..fb7b3d1 100644 --- a/test/millis-converter.spec.js +++ b/test/millis-converter.spec.js @@ -958,14 +958,14 @@ describe('MillisConverter', () => { describe('BREAK', () => { it('says no', () => { assert.throws(() => new MillisConverter(data, MODELS.BREAK), - /Segment length must be positive/) + /segment length must be positive/) }) }) describe('STALL', () => { it('says no', () => { assert.throws(() => new MillisConverter(data, MODELS.STALL), - /Segment length must be positive/) + /segment length must be positive/) }) }) }) diff --git a/test/munge.spec.js b/test/munge.spec.js index 87dc080..09f434b 100644 --- a/test/munge.spec.js +++ b/test/munge.spec.js @@ -66,13 +66,13 @@ describe('munge', () => { [9_000, -3], // inserted leap second [13_000, -4] // removed leap second ], MODELS.OVERRUN), [new Segment( - { atomic: new Second(-5n, 1n), unix: new Second(-1n, 1n) }, - { atomic: new Second(6n, 1n) } + { atomic: new Second(new Rat(-5n, 1n)), unix: new Second(new Rat(-1n, 1n)) }, + { atomic: new Second(new Rat(6n, 1n)) } ), new Segment( - { atomic: new Second(6n, 1n), unix: new Second(9n, 1n) }, - { atomic: new Second(9n, 1n) } + { atomic: new Second(new Rat(6n, 1n)), unix: new Second(new Rat(9n, 1n)) }, + { atomic: new Second(new Rat(9n, 1n)) } ), new Segment( - { atomic: new Second(9n, 1n), unix: new Second(13n, 1n) } + { atomic: new Second(new Rat(9n, 1n)), unix: new Second(new Rat(13n, 1n)) } )]) }) @@ -125,7 +125,7 @@ describe('munge', () => { assert.deepStrictEqual(munge([ [Date.UTC(1961, JAN, 1), 1.422_818_0, 37_300, 0.001_296] ], MODELS.OVERRUN), [new Segment( - { atomic: new Second(-283_996_798_577_182n, 1_000_000n), unix: new Second(-283_996_800n, 1n) }, + { atomic: new Second(new Rat(-283_996_798_577_182n, 1_000_000n)), unix: new Second(new Rat(-283_996_800n, 1n)) }, { atomic: Second.END_OF_TIME }, { unixPerAtomic: new Rat(86_400_000_000_000n, 86_400_000_000_000n + 1_296_000n) } )]) @@ -202,46 +202,46 @@ describe('munge', () => { return b.minusS(a) }), [ // Exact ratio of microseconds - new Second(-50_000n, 1_000_000n), - new Second(0n, 1_000_000n), - new Second(100_000n, 1_000_000n), - new Second(0n, 1_000_000n), - new Second(100_000n, 1_000_000n), - new Second(100_000n, 1_000_000n), - new Second(100_000n, 1_000_000n), - new Second(100_000n, 1_000_000n), - new Second(100_000n, 1_000_000n), - new Second(100_000n, 1_000_000n), - new Second(0n, 1_000_000n), - new Second(-100_000n, 1_000_000n), - new Second(107_758n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), - new Second(1_000_000n, 1_000_000n), + new Second(new Rat(-50_000n, 1_000_000n)), + new Second(new Rat(0n, 1_000_000n)), + new Second(new Rat(100_000n, 1_000_000n)), + new Second(new Rat(0n, 1_000_000n)), + new Second(new Rat(100_000n, 1_000_000n)), + new Second(new Rat(100_000n, 1_000_000n)), + new Second(new Rat(100_000n, 1_000_000n)), + new Second(new Rat(100_000n, 1_000_000n)), + new Second(new Rat(100_000n, 1_000_000n)), + new Second(new Rat(100_000n, 1_000_000n)), + new Second(new Rat(0n, 1_000_000n)), + new Second(new Rat(-100_000n, 1_000_000n)), + new Second(new Rat(107_758n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), + new Second(new Rat(1_000_000n, 1_000_000n)), NaN // `Infinity - Infinity` ]) }) @@ -251,7 +251,7 @@ describe('munge', () => { assert.deepStrictEqual(munge([ [Date.UTC(1970, JAN, 1, 0, 0, 0, 1), -0.000_1] ], MODELS.OVERRUN), [new Segment( - { atomic: new Second(900n, 1_000_000n), unix: Second.fromMillis(1) } // ray start intentionally doesn't include TAI epoch + { atomic: new Second(new Rat(900n, 1_000_000n)), unix: Second.fromMillis(1) } // ray start intentionally doesn't include TAI epoch )]) }) @@ -261,10 +261,10 @@ describe('munge', () => { [Date.UTC(1969, DEC, 31, 23, 59, 59, 999), 0.000_1], [Date.UTC(1970, JAN, 1, 0, 0, 0, 1), -0.001_1] ], MODELS.OVERRUN), [new Segment( - { atomic: new Second(-900n, 1_000_000n), unix: Second.fromMillis(-1) }, - { atomic: new Second(-100n, 1_000_000n) } + { atomic: new Second(new Rat(-900n, 1_000_000n)), unix: Second.fromMillis(-1) }, + { atomic: new Second(new Rat(-100n, 1_000_000n)) } ), new Segment( - { atomic: new Second(-100n, 1_000_000n), unix: Second.fromMillis(1) } + { atomic: new Second(new Rat(-100n, 1_000_000n)), unix: Second.fromMillis(1) } )]) }) }) @@ -289,14 +289,14 @@ describe('munge', () => { [9_000, -3], // inserted leap second [13_000, -4] // removed leap second ], MODELS.BREAK), [new Segment( - { atomic: new Second(-5n, 1n), unix: new Second(-1n, 1n) }, - { atomic: new Second(5n, 1n) } + { atomic: new Second(new Rat(-5n, 1n)), unix: new Second(new Rat(-1n, 1n)) }, + { atomic: new Second(new Rat(5n, 1n)) } ), new Segment( // this segment starts a full TAI second after the previous segment ended - { atomic: new Second(6n, 1n), unix: new Second(9n, 1n) }, - { atomic: new Second(9n, 1n) } + { atomic: new Second(new Rat(6n, 1n)), unix: new Second(new Rat(9n, 1n)) }, + { atomic: new Second(new Rat(9n, 1n)) } ), new Segment( - { atomic: new Second(9n, 1n), unix: new Second(13n, 1n) } + { atomic: new Second(new Rat(9n, 1n)), unix: new Second(new Rat(13n, 1n)) } )]) }) }) @@ -335,18 +335,18 @@ describe('munge', () => { [9_000, -3], // inserted leap second [13_000, -4] // removed leap second ], MODELS.STALL), [new Segment( - { atomic: new Second(-5n, 1n), unix: new Second(-1n, 1n) }, - { atomic: new Second(5n, 1n) } + { atomic: new Second(new Rat(-5n, 1n)), unix: new Second(new Rat(-1n, 1n)) }, + { atomic: new Second(new Rat(5n, 1n)) } ), new Segment( // Stall segment inserted here - { atomic: new Second(5n, 1n), unix: new Second(9n, 1n) }, - { atomic: new Second(6n, 1n) }, + { atomic: new Second(new Rat(5n, 1n)), unix: new Second(new Rat(9n, 1n)) }, + { atomic: new Second(new Rat(6n, 1n)) }, { unixPerAtomic: new Rat(0n) } ), new Segment( - { atomic: new Second(6n, 1n), unix: new Second(9n, 1n) }, - { atomic: new Second(9n, 1n) } + { atomic: new Second(new Rat(6n, 1n)), unix: new Second(new Rat(9n, 1n)) }, + { atomic: new Second(new Rat(9n, 1n)) } ), new Segment( - { atomic: new Second(9n, 1n), unix: new Second(13n, 1n) } + { atomic: new Second(new Rat(9n, 1n)), unix: new Second(new Rat(13n, 1n)) } )]) }) @@ -399,7 +399,7 @@ describe('munge', () => { assert.deepStrictEqual(munge([ [Date.UTC(1961, JAN, 1), 1.422_818_0, 37_300, 0.001_296] ], MODELS.STALL), [new Segment( - { atomic: new Second(-283_996_798_577_182n, 1_000_000n), unix: new Second(-283_996_800n, 1n) }, + { atomic: new Second(new Rat(-283_996_798_577_182n, 1_000_000n)), unix: new Second(new Rat(-283_996_800n, 1n)) }, { atomic: Second.END_OF_TIME }, { unixPerAtomic: new Rat(86_400_000_000_000n, 86_400_000_000_000n + 1_296_000n) } )]) @@ -518,81 +518,81 @@ describe('munge', () => { return b.minusS(a) }), [ // Exact ratio expressing milliseconds - new Second(-50n, 1_000n), // 0.05 TAI seconds removed from UTC - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(-100n, 1_000n), // 0.1 TAI seconds removed from UTC - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), - new Second(0n, 1_000n), + new Second(new Rat(-50n, 1_000n)), // 0.05 TAI seconds removed from UTC + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(-100n, 1_000n)), // 0.1 TAI seconds removed from UTC + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), + new Second(new Rat(0n, 1_000n)), NaN ]) }) @@ -613,13 +613,13 @@ describe('munge', () => { [86_400_000, 1] // inserted leap second after one day ], MODELS.SMEAR), [new Segment( { atomic: Second.fromMillis(0), unix: Second.fromMillis(0) }, - { atomic: new Second(43_200n, 1n) } // midday + { atomic: new Second(new Rat(43_200n, 1n)) } // midday ), new Segment( - { atomic: new Second(43_200n, 1n), unix: new Second(43_200n, 1n) }, // midday - { atomic: new Second(129_601n, 1n) }, // midday + { atomic: new Second(new Rat(43_200n, 1n)), unix: new Second(new Rat(43_200n, 1n)) }, // midday + { atomic: new Second(new Rat(129_601n, 1n)) }, // midday { unixPerAtomic: new Rat(86_400n, 86_401n) } // A full Unix day elapses, but a full TAI day plus one second elapses ), new Segment( - { atomic: new Second(129_601n, 1n), unix: new Second(129_600n, 1n) } // midday + { atomic: new Second(new Rat(129_601n, 1n)), unix: new Second(new Rat(129_600n, 1n)) } // midday )]) }) @@ -629,13 +629,13 @@ describe('munge', () => { [86_400_000, -1] // removed leap second after one day ], MODELS.SMEAR), [new Segment( { atomic: Second.fromMillis(0), unix: Second.fromMillis(0) }, - { atomic: new Second(43_200n, 1n) } // midday + { atomic: new Second(new Rat(43_200n, 1n)) } // midday ), new Segment( - { atomic: new Second(43_200n, 1n), unix: new Second(43_200n, 1n) }, // midday - { atomic: new Second(129_599n, 1n) }, // midday + { atomic: new Second(new Rat(43_200n, 1n)), unix: new Second(new Rat(43_200n, 1n)) }, // midday + { atomic: new Second(new Rat(129_599n, 1n)) }, // midday { unixPerAtomic: new Rat(86_400n, 86_399n) } // A full Unix day elapses, but a full TAI day minus one second elapses ), new Segment( - { atomic: new Second(129_599n, 1n), unix: new Second(129_600n, 1n) } // midday + { atomic: new Second(new Rat(129_599n, 1n)), unix: new Second(new Rat(129_600n, 1n)) } // midday )]) }) @@ -752,86 +752,86 @@ describe('munge', () => { return b.minusS(a) }), [ - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), - new Second(0n, 1n), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), + new Second(new Rat(0n, 1n)), NaN ]) }) diff --git a/test/rat.spec.js b/test/rat.spec.js index 13cf7f4..52061f5 100644 --- a/test/rat.spec.js +++ b/test/rat.spec.js @@ -4,10 +4,10 @@ import { Rat } from '../src/rat.js' describe('Rat', () => { it('type checking', () => { - assert.throws(() => new Rat(1, 2n), /Numerator must be a BigInt/) - assert.throws(() => new Rat(1n, 2), /Denominator must be a BigInt/) - assert.throws(() => new Rat(1n, 0), /Denominator must be a BigInt/) - assert.throws(() => new Rat(-1n, 0n), /Numerator must be positive if denominator is zero/) + assert.throws(() => new Rat(1, 2n), /numerator must be a BigInt/) + assert.throws(() => new Rat(1n, 2), /denominator must be a BigInt/) + assert.throws(() => new Rat(1n, 0), /denominator must be a BigInt/) + assert.throws(() => new Rat(-1n, 0n), /denominator cannot be zero/) }) it('defaults to an integer', () => { @@ -92,84 +92,4 @@ describe('Rat', () => { assert.strictEqual(new Rat(18n, -10n).trunc(), -2n) }) }) - - describe('positive infinity', () => { - it('reduces to the lowest terms', () => { - assert.deepStrictEqual(Rat.INFINITY, new Rat(133n, 0n)) - }) - - it('adds', () => { - assert.deepStrictEqual(Rat.INFINITY.plus(new Rat(15n, 69n)), Rat.INFINITY) - assert.deepStrictEqual(Rat.INFINITY.plus(new Rat(0n, 3n)), Rat.INFINITY) - assert.deepStrictEqual(Rat.INFINITY.plus(new Rat(-12n, 1n)), Rat.INFINITY) - assert.deepStrictEqual(new Rat(15n, 69n).plus(Rat.INFINITY), Rat.INFINITY) - assert.deepStrictEqual(new Rat(0n, 3n).plus(Rat.INFINITY), Rat.INFINITY) - assert.deepStrictEqual(new Rat(-12n, 1n).plus(Rat.INFINITY), Rat.INFINITY) - assert.deepStrictEqual(Rat.INFINITY.plus(Rat.INFINITY), Rat.INFINITY) - }) - - it('subtracts', () => { - assert.deepStrictEqual(Rat.INFINITY.minus(new Rat(15n, 69n)), Rat.INFINITY) - assert.deepStrictEqual(Rat.INFINITY.minus(new Rat(0n, 3n)), Rat.INFINITY) - assert.deepStrictEqual(Rat.INFINITY.minus(new Rat(-12n, 1n)), Rat.INFINITY) - assert.throws(() => new Rat(15n, 69n).minus(Rat.INFINITY)) - assert.throws(() => new Rat(0n, 3n).minus(Rat.INFINITY)) - assert.throws(() => new Rat(-12n, 1n).minus(Rat.INFINITY)) - assert.throws(() => Rat.INFINITY.minus(Rat.INFINITY)) - }) - - it('multiplies', () => { - assert.deepStrictEqual(Rat.INFINITY.times(new Rat(15n, 69n)), Rat.INFINITY) - assert.throws(() => Rat.INFINITY.times(new Rat(0n, 3n))) - assert.throws(() => Rat.INFINITY.times(new Rat(-12n, 1n))) - assert.deepStrictEqual(new Rat(15n, 69n).times(Rat.INFINITY), Rat.INFINITY) - assert.throws(() => new Rat(0n, 3n).times(Rat.INFINITY)) - assert.throws(() => new Rat(-12n, 1n).times(Rat.INFINITY)) - assert.deepStrictEqual(Rat.INFINITY.times(Rat.INFINITY), Rat.INFINITY) - }) - - it('divides', () => { - assert.deepStrictEqual(Rat.INFINITY.divide(new Rat(15n, 69n)), Rat.INFINITY) - assert.deepStrictEqual(Rat.INFINITY.divide(new Rat(0n, 3n)), Rat.INFINITY) - assert.throws(() => Rat.INFINITY.divide(new Rat(-12n, 1n)), /Numerator must be positive if denominator is zero/) - assert.deepStrictEqual(new Rat(15n, 69n).divide(Rat.INFINITY), new Rat(0n)) - assert.deepStrictEqual(new Rat(0n, 3n).divide(Rat.INFINITY), new Rat(0n)) - assert.deepStrictEqual(new Rat(-12n, 1n).divide(Rat.INFINITY), new Rat(0n)) - assert.throws(() => Rat.INFINITY.divide(Rat.INFINITY)) - }) - - it('equals', () => { - assert.strictEqual(Rat.INFINITY.eq(new Rat(15n, 69n)), false) - assert.strictEqual(Rat.INFINITY.eq(new Rat(0n, 3n)), false) - assert.strictEqual(Rat.INFINITY.eq(new Rat(-12n, 1n)), false) - assert.throws(() => new Rat(15n, 69n).eq(Rat.INFINITY)) - assert.throws(() => new Rat(0n, 3n).eq(Rat.INFINITY)) - assert.throws(() => new Rat(-12n, 1n).eq(Rat.INFINITY)) - assert.throws(() => Rat.INFINITY.eq(Rat.INFINITY)) - }) - - it('less than or equal', () => { - assert.strictEqual(Rat.INFINITY.le(new Rat(15n, 69n)), false) - assert.strictEqual(Rat.INFINITY.le(new Rat(0n, 3n)), false) - assert.strictEqual(Rat.INFINITY.le(new Rat(-12n, 1n)), false) - assert.throws(() => new Rat(15n, 69n).le(Rat.INFINITY)) - assert.throws(() => new Rat(0n, 3n).le(Rat.INFINITY)) - assert.throws(() => new Rat(-12n, 1n).le(Rat.INFINITY)) - assert.throws(() => Rat.INFINITY.le(Rat.INFINITY)) - }) - - it('greater than', () => { - assert.strictEqual(Rat.INFINITY.gt(new Rat(15n, 69n)), true) - assert.strictEqual(Rat.INFINITY.gt(new Rat(0n, 3n)), true) - assert.strictEqual(Rat.INFINITY.gt(new Rat(-12n, 1n)), true) - assert.throws(() => new Rat(15n, 69n).gt(Rat.INFINITY)) - assert.throws(() => new Rat(0n, 3n).gt(Rat.INFINITY)) - assert.throws(() => new Rat(-12n, 1n).gt(Rat.INFINITY)) - assert.throws(() => Rat.INFINITY.gt(Rat.INFINITY)) - }) - - it('truncates', () => { - assert.throws(() => Rat.INFINITY.trunc()) - }) - }) }) diff --git a/test/second.spec.js b/test/second.spec.js index e7d1ad7..16f14c6 100644 --- a/test/second.spec.js +++ b/test/second.spec.js @@ -4,143 +4,53 @@ import { Rat } from '../src/rat.js' import { Second } from '../src/second.js' describe('Second', () => { - it('type checking', () => { - assert.throws(() => new Second(1, 2n), /Numerator must be a BigInt/) - assert.throws(() => new Second(1n, 2), /Denominator must be a BigInt/) - assert.throws(() => new Second(1n, 0), /Denominator must be a BigInt/) - assert.throws(() => new Second(-1n, 0n), /Numerator must be positive if denominator is zero/) - }) - - it('defaults to an integer', () => { - assert.deepStrictEqual(new Second(1n), new Second(1n, 1n)) - }) - it('adds', () => { - assert.deepStrictEqual(new Second(1n, 2n).plusS(new Second(1n, 3n)), new Second(5n, 6n)) - assert.deepStrictEqual(new Second(1n, 2n).plusS(new Second(0n, 3n)), new Second(1n, 2n)) - assert.deepStrictEqual(new Second(0n, 2n).plusS(new Second(1n, 3n)), new Second(1n, 3n)) + assert.deepStrictEqual(new Second(new Rat(1n, 2n)).plusS(new Second(new Rat(1n, 3n))), new Second(new Rat(5n, 6n))) + assert.deepStrictEqual(new Second(new Rat(1n, 2n)).plusS(new Second(new Rat(0n, 3n))), new Second(new Rat(1n, 2n))) + assert.deepStrictEqual(new Second(new Rat(0n, 2n)).plusS(new Second(new Rat(1n, 3n))), new Second(new Rat(1n, 3n))) }) it('subtracts', () => { - assert.deepStrictEqual(new Second(1n, 2n).minusS(new Second(1n, 3n)), new Second(1n, 6n)) - assert.deepStrictEqual(new Second(1n, 2n).minusS(new Second(0n, 3n)), new Second(1n, 2n)) - assert.deepStrictEqual(new Second(0n, 2n).minusS(new Second(1n, 3n)), new Second(-1n, 3n)) + assert.deepStrictEqual(new Second(new Rat(1n, 2n)).minusS(new Second(new Rat(1n, 3n))), new Second(new Rat(1n, 6n))) + assert.deepStrictEqual(new Second(new Rat(1n, 2n)).minusS(new Second(new Rat(0n, 3n))), new Second(new Rat(1n, 2n))) + assert.deepStrictEqual(new Second(new Rat(0n, 2n)).minusS(new Second(new Rat(1n, 3n))), new Second(new Rat(-1n, 3n))) }) it('multiplies', () => { - assert.deepStrictEqual(new Second(6n, 5n).timesR(new Rat(4n, 5n)), new Second(24n, 25n)) - assert.deepStrictEqual(new Second(6n, 5n).timesR(new Rat(0n, 5n)), new Second(0n, 25n)) - assert.deepStrictEqual(new Second(0n, 5n).timesR(new Rat(4n, 5n)), new Second(0n, 25n)) + assert.deepStrictEqual(new Second(new Rat(6n, 5n)).timesR(new Rat(4n, 5n)), new Second(new Rat(24n, 25n))) + assert.deepStrictEqual(new Second(new Rat(6n, 5n)).timesR(new Rat(0n, 5n)), new Second(new Rat(0n, 25n))) + assert.deepStrictEqual(new Second(new Rat(0n, 5n)).timesR(new Rat(4n, 5n)), new Second(new Rat(0n, 25n))) }) it('divides', () => { - assert.deepStrictEqual(new Second(6n, 5n).divideS(new Second(4n, 5n)), new Rat(30n, 20n)) - assert.deepStrictEqual(new Second(0n, 5n).divideS(new Second(4n, 5n)), new Rat(0n, 20n)) + assert.deepStrictEqual(new Second(new Rat(6n, 5n)).divideS(new Second(new Rat(4n, 5n))), new Rat(30n, 20n)) + assert.deepStrictEqual(new Second(new Rat(0n, 5n)).divideS(new Second(new Rat(4n, 5n))), new Rat(0n, 20n)) }) it('greater than', () => { - assert.strictEqual(new Second(-1n, 3n).gtS(new Second(1n, -2n)), true) - assert.strictEqual(new Second(0n).gtS(new Second(1n)), false) + assert.strictEqual(new Second(new Rat(-1n, 3n)).gtS(new Second(new Rat(1n, -2n))), true) + assert.strictEqual(new Second(new Rat(0n)).gtS(new Second(new Rat(1n))), false) }) it('equal', () => { - assert.strictEqual(new Second(-1n, 3n).eqS(new Second(4n, -12n)), true) - assert.strictEqual(new Second(0n).eqS(new Second(-1n)), false) - assert.strictEqual(new Second(0n).eqS(new Second(-0n)), true) + assert.strictEqual(new Second(new Rat(-1n, 3n)).eqS(new Second(new Rat(4n, -12n))), true) + assert.strictEqual(new Second(new Rat(0n)).eqS(new Second(new Rat(-1n))), false) + assert.strictEqual(new Second(new Rat(0n)).eqS(new Second(new Rat(-0n))), true) }) it('less than or equal', () => { - assert.strictEqual(new Second(-2n, -3n).leS(new Second(-2n, -3n)), true) - assert.strictEqual(new Second(-2n, -3n).leS(new Second(2n, 3n)), true) - assert.strictEqual(new Second(9n, 12n).leS(new Second(6n, 8n)), true) - assert.strictEqual(new Second(9n, 13n).leS(new Second(6n, 8n)), true) + assert.strictEqual(new Second(new Rat(-2n, -3n)).leS(new Second(new Rat(-2n, -3n))), true) + assert.strictEqual(new Second(new Rat(-2n, -3n)).leS(new Second(new Rat(2n, 3n))), true) + assert.strictEqual(new Second(new Rat(9n, 12n)).leS(new Second(new Rat(6n, 8n))), true) + assert.strictEqual(new Second(new Rat(9n, 13n)).leS(new Second(new Rat(6n, 8n))), true) }) it('fromMillis', () => { - assert.deepStrictEqual(Second.fromMillis(123), new Second(123n, 1_000n)) + assert.deepStrictEqual(Second.fromMillis(123), new Second(new Rat(123n, 1_000n))) assert.throws(() => Second.fromMillis(Infinity)) }) it('toMillis', () => { - assert.strictEqual(new Second(123n, 1_000n).toMillis(), 123) - }) - - describe('positive infinity', () => { - it('reduces to the lowest terms', () => { - assert.deepStrictEqual(Second.END_OF_TIME, new Second(133n, 0n)) - }) - - it('adds', () => { - assert.deepStrictEqual(Second.END_OF_TIME.plusS(new Second(15n, 69n)), Second.END_OF_TIME) - assert.deepStrictEqual(Second.END_OF_TIME.plusS(new Second(0n, 3n)), Second.END_OF_TIME) - assert.deepStrictEqual(Second.END_OF_TIME.plusS(new Second(-12n, 1n)), Second.END_OF_TIME) - assert.deepStrictEqual(new Second(15n, 69n).plusS(Second.END_OF_TIME), Second.END_OF_TIME) - assert.deepStrictEqual(new Second(0n, 3n).plusS(Second.END_OF_TIME), Second.END_OF_TIME) - assert.deepStrictEqual(new Second(-12n, 1n).plusS(Second.END_OF_TIME), Second.END_OF_TIME) - assert.deepStrictEqual(Second.END_OF_TIME.plusS(Second.END_OF_TIME), Second.END_OF_TIME) - }) - - it('subtracts', () => { - assert.deepStrictEqual(Second.END_OF_TIME.minusS(new Second(15n, 69n)), Second.END_OF_TIME) - assert.deepStrictEqual(Second.END_OF_TIME.minusS(new Second(0n, 3n)), Second.END_OF_TIME) - assert.deepStrictEqual(Second.END_OF_TIME.minusS(new Second(-12n, 1n)), Second.END_OF_TIME) - assert.throws(() => new Second(15n, 69n).minusS(Second.END_OF_TIME)) - assert.throws(() => new Second(0n, 3n).minusS(Second.END_OF_TIME)) - assert.throws(() => new Second(-12n, 1n).minusS(Second.END_OF_TIME)) - assert.throws(() => Second.END_OF_TIME.minusS(Second.END_OF_TIME)) - }) - - it('multiplies', () => { - assert.deepStrictEqual(Second.END_OF_TIME.timesR(new Rat(15n, 69n)), Second.END_OF_TIME) - assert.throws(() => Second.END_OF_TIME.timesR(new Rat(0n, 3n))) - assert.throws(() => Second.END_OF_TIME.timesR(new Second(-12n, 1n))) - assert.deepStrictEqual(new Second(15n, 69n).timesR(Rat.INFINITY), Second.END_OF_TIME) - assert.throws(() => new Second(0n, 3n).timesR(Rat.INFINITY)) - assert.throws(() => new Second(-12n, 1n).timesR(Rat.INFINITY)) - }) - - it('divides', () => { - assert.deepStrictEqual(Second.END_OF_TIME.divideS(new Second(15n, 69n)), Rat.INFINITY) - assert.deepStrictEqual(Second.END_OF_TIME.divideS(new Second(0n, 3n)), Rat.INFINITY) - assert.throws(() => Second.END_OF_TIME.divideS(new Second(-12n, 1n)), /Numerator must be positive if denominator is zero/) - assert.deepStrictEqual(new Second(15n, 69n).divideS(Second.END_OF_TIME), new Rat(0n)) - assert.deepStrictEqual(new Second(0n, 3n).divideS(Second.END_OF_TIME), new Rat(0n)) - assert.deepStrictEqual(new Second(-12n, 1n).divideS(Second.END_OF_TIME), new Rat(0n)) - assert.throws(() => Second.END_OF_TIME.divideS(Second.END_OF_TIME)) - }) - - it('equals', () => { - assert.strictEqual(Second.END_OF_TIME.eqS(new Second(15n, 69n)), false) - assert.strictEqual(Second.END_OF_TIME.eqS(new Second(0n, 3n)), false) - assert.strictEqual(Second.END_OF_TIME.eqS(new Second(-12n, 1n)), false) - assert.throws(() => new Second(15n, 69n).eqS(Second.END_OF_TIME)) - assert.throws(() => new Second(0n, 3n).eqS(Second.END_OF_TIME)) - assert.throws(() => new Second(-12n, 1n).eqS(Second.END_OF_TIME)) - assert.throws(() => Second.END_OF_TIME.eqS(Second.END_OF_TIME)) - }) - - it('less than or equal', () => { - assert.strictEqual(Second.END_OF_TIME.leS(new Second(15n, 69n)), false) - assert.strictEqual(Second.END_OF_TIME.leS(new Second(0n, 3n)), false) - assert.strictEqual(Second.END_OF_TIME.leS(new Second(-12n, 1n)), false) - assert.throws(() => new Second(15n, 69n).leS(Second.END_OF_TIME)) - assert.throws(() => new Second(0n, 3n).leS(Second.END_OF_TIME)) - assert.throws(() => new Second(-12n, 1n).leS(Second.END_OF_TIME)) - assert.throws(() => Second.END_OF_TIME.leS(Second.END_OF_TIME)) - }) - - it('greater than', () => { - assert.strictEqual(Second.END_OF_TIME.gtS(new Second(15n, 69n)), true) - assert.strictEqual(Second.END_OF_TIME.gtS(new Second(0n, 3n)), true) - assert.strictEqual(Second.END_OF_TIME.gtS(new Second(-12n, 1n)), true) - assert.throws(() => new Second(15n, 69n).gtS(Second.END_OF_TIME)) - assert.throws(() => new Second(0n, 3n).gtS(Second.END_OF_TIME)) - assert.throws(() => new Second(-12n, 1n).gtS(Second.END_OF_TIME)) - assert.throws(() => Second.END_OF_TIME.gtS(Second.END_OF_TIME)) - }) - - it('converts to milliseconds', () => { - assert.throws(() => Second.END_OF_TIME.toMillis()) - }) + assert.strictEqual(new Second(new Rat(123n, 1_000n)).toMillis(), 123) }) }) diff --git a/test/segment.spec.js b/test/segment.spec.js index 7c837e5..f943253 100644 --- a/test/segment.spec.js +++ b/test/segment.spec.js @@ -11,33 +11,33 @@ describe('Segment', () => { it('disallows bad powers', () => { assert.throws(() => new Segment( { atomic: new Rat(0n) } - ), /TAI start must be a rational number of seconds/) + ), /TAI start must be a `Second`/) assert.throws(() => new Segment( { atomic: Second.fromMillis(0), unix: new Rat(0n) } - ), /Unix start must be a rational number of seconds/) + ), /Unix start must be a `Second`/) assert.throws(() => new Segment( { atomic: Second.fromMillis(0), unix: Second.fromMillis(0) }, { atomic: new Rat(1n) } - ), /TAI end must be a rational number of seconds/) + ), /TAI end must be a `Second` or `Second.END_OF_TIME`/) assert.throws(() => new Segment( { atomic: Second.fromMillis(0), unix: Second.fromMillis(0) }, { atomic: Second.fromMillis(1_000) }, - { unixPerAtomic: new Second(1n, 1n) } - ), /Slope must be a pure ratio/) + { unixPerAtomic: new Second(new Rat(1n, 1n)) } + ), /slope must be a `Rat`/) }) it('disallows rays which run backwards', () => { assert.throws(() => new Segment( { atomic: Second.fromMillis(0), unix: Second.fromMillis(0) }, - { atomic: new Second(-1n, 1_000_000_000_000n) } - ), /Segment length must be positive/) + { atomic: new Second(new Rat(-1n, 1_000_000_000_000n)) } + ), /segment length must be positive/) }) it('disallows zero-length rays which run backwards', () => { assert.throws(() => new Segment( { atomic: Second.fromMillis(0), unix: Second.fromMillis(0) }, { atomic: Second.fromMillis(0) } - ), /Segment length must be positive/) + ), /segment length must be positive/) }) describe('basic infinite ray', () => { @@ -121,7 +121,7 @@ describe('Segment', () => { assert.strictEqual(segment.atomicOnSegment(Second.fromMillis(1_999)), true) assert.deepStrictEqual(segment.atomicToUnix(Second.fromMillis(1_999)), - new Second(1_999n, 2_000n)) // truncates to 999ms + new Second(new Rat(1_999n, 2_000n))) // truncates to 999ms }) it('end point', () => {