Skip to content

Commit 24e10ba

Browse files
authored
More efficient serialization of java.time.Instant (#540)
1 parent b023e3c commit 24e10ba

File tree

3 files changed

+25
-27
lines changed

3 files changed

+25
-27
lines changed

jsoniter-scala-core/js/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonWriter.scala

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,27 +1348,26 @@ final class JsonWriter private[jsoniter_scala](
13481348
val epochDay =
13491349
(if (epochSecond >= 0) epochSecond
13501350
else epochSecond - 86399) / 86400 // 86400 == seconds per day
1351+
val secsOfDay = (epochSecond - epochDay * 86400).toInt
13511352
var marchZeroDay = epochDay + 719468 // 719468 == 719528 - 60 == days 0000 to 1970 - days 1st Jan to 1st Mar
13521353
var adjustYear = 0
13531354
if (marchZeroDay < 0) { // adjust negative years to positive for calculation
13541355
val adjust400YearCycles = to400YearCycle(marchZeroDay + 1) - 1
13551356
adjustYear = adjust400YearCycles * 400
13561357
marchZeroDay -= adjust400YearCycles * 146097L
13571358
}
1358-
var yearEst = to400YearCycle(marchZeroDay * 400 + 591)
1359-
var marchDayOfYear = toMarchDayOfYear(marchZeroDay, yearEst)
1360-
if (marchDayOfYear < 0) { // fix estimate
1361-
yearEst -= 1
1362-
marchDayOfYear = toMarchDayOfYear(marchZeroDay, yearEst)
1359+
var year = to400YearCycle(marchZeroDay * 400 + 591)
1360+
var marchDayOfYear = toMarchDayOfYear(marchZeroDay, year)
1361+
if (marchDayOfYear < 0) { // fix year estimate
1362+
year -= 1
1363+
marchDayOfYear = toMarchDayOfYear(marchZeroDay, year)
13631364
}
1364-
yearEst += adjustYear // reset any negative year
13651365
val marchMonth = (marchDayOfYear * 5 + 2) / 153
1366-
val year = yearEst + marchMonth / 10 // convert march-based values back to january-based
1366+
year += marchMonth / 10 + adjustYear // reset any negative year and convert march-based values back to january-based
13671367
val month = marchMonth +
13681368
(if (marchMonth < 10) 3
13691369
else -9)
13701370
val day = marchDayOfYear - (marchMonth * 306 + 5) / 10 + 1
1371-
val secsOfDay = (epochSecond - epochDay * 86400).toInt
13721371
val hour = secsOfDay / 3600
13731372
val secsOfHour = secsOfDay - hour * 3600
13741373
val minute = secsOfHour * 17477 >> 20 // divide a small positive int by 60
@@ -1387,9 +1386,9 @@ final class JsonWriter private[jsoniter_scala](
13871386

13881387
private[this] def to400YearCycle(day: Long): Int = (day / 146097).toInt // 146097 == number of days in a 400 year cycle
13891388

1390-
private[this] def toMarchDayOfYear(marchZeroDay: Long, yearEst: Int): Int = {
1391-
val centuryEst = yearEst / 100
1392-
(marchZeroDay - yearEst * 365L).toInt - (yearEst >> 2) + centuryEst - (centuryEst >> 2)
1389+
private[this] def toMarchDayOfYear(marchZeroDay: Long, year: Int): Int = {
1390+
val century = year / 100
1391+
(marchZeroDay - year * 365L).toInt - (year >> 2) + century - (century >> 2)
13931392
}
13941393

13951394
private[this] def writeLocalDate(x: LocalDate): Unit = count = {

jsoniter-scala-core/jvm/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonReader.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2331,7 +2331,7 @@ final class JsonReader private[jsoniter_scala](
23312331

23322332
private[this] def toZoneOffset(isNeg: Boolean, offsetHour: Int, offsetMinute: Int, offsetSecond: Int): ZoneOffset = {
23332333
var offsetTotal = offsetHour * 3600 + offsetMinute * 60 + offsetSecond
2334-
var q1 = (offsetTotal * 2443359173L >> 41).toInt // divide a positive int by 900
2334+
var q1 = offsetTotal * 37283 >>> 25 // divide a small positive int by 900
23352335
if (offsetTotal > 64800) timezoneOffsetError() // 64800 == 18 * 60 * 60
23362336
if (q1 * 900 == offsetTotal) {
23372337
if (isNeg) q1 = -q1

jsoniter-scala-core/jvm/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonWriter.scala

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,28 +1292,27 @@ final class JsonWriter private[jsoniter_scala](
12921292
val epochDay =
12931293
(if (epochSecond >= 0) epochSecond
12941294
else epochSecond - 86399) / 86400 // 86400 == seconds per day
1295+
val secsOfDay = (epochSecond - epochDay * 86400).toInt
12951296
var marchZeroDay = epochDay + 719468 // 719468 == 719528 - 60 == days 0000 to 1970 - days 1st Jan to 1st Mar
12961297
var adjustYear = 0
12971298
if (marchZeroDay < 0) { // adjust negative years to positive for calculation
12981299
val adjust400YearCycles = to400YearCycle(marchZeroDay + 1) - 1
12991300
adjustYear = adjust400YearCycles * 400
13001301
marchZeroDay -= adjust400YearCycles * 146097L
13011302
}
1302-
var yearEst = to400YearCycle(marchZeroDay * 400 + 591)
1303-
var marchDayOfYear = toMarchDayOfYear(marchZeroDay, yearEst)
1304-
if (marchDayOfYear < 0) { // fix estimate
1305-
yearEst -= 1
1306-
marchDayOfYear = toMarchDayOfYear(marchZeroDay, yearEst)
1303+
var year = to400YearCycle(marchZeroDay * 400 + 591)
1304+
var marchDayOfYear = toMarchDayOfYear(marchZeroDay, year)
1305+
if (marchDayOfYear < 0) { // fix year estimate
1306+
year -= 1
1307+
marchDayOfYear = toMarchDayOfYear(marchZeroDay, year)
13071308
}
1308-
yearEst += adjustYear // reset any negative year
1309-
val marchMonth = ((marchDayOfYear * 17965876275L + 7186350510L) >> 39).toInt // (marchDayOfYear * 5 + 2) / 153
1310-
val year = yearEst + (marchMonth * 3435973837L >> 35).toInt // yearEst + marchMonth / 10 (convert march-based values back to january-based)
1309+
val marchMonth = (marchDayOfYear * 17135 + 6854) >> 19 // (marchDayOfYear * 5 + 2) / 153
1310+
year += (marchMonth * 3277 >> 15) + adjustYear // year += marchMonth / 10 + adjustYear (reset any negative year and convert march-based values back to january-based)
13111311
val month = marchMonth +
13121312
(if (marchMonth < 10) 3
13131313
else -9)
1314-
val day = marchDayOfYear - ((marchMonth * 1051407994122L - 17179869183L) >> 35).toInt // marchDayOfYear - (marchMonth * 306 + 5) / 10 + 1
1315-
val secsOfDay = (epochSecond - epochDay * 86400).toInt
1316-
val hour = (secsOfDay * 2443359173L >> 43).toInt // divide a positive int by 3600
1314+
val day = marchDayOfYear - ((marchMonth * 1002762 - 16383) >> 15) // marchDayOfYear - (marchMonth * 306 + 5) / 10 + 1
1315+
val hour = secsOfDay * 37283 >>> 27 // divide a small positive int by 3600
13171316
val secsOfHour = secsOfDay - hour * 3600
13181317
val minute = secsOfHour * 17477 >> 20 // divide a small positive int by 60
13191318
val second = secsOfHour - minute * 60
@@ -1331,9 +1330,9 @@ final class JsonWriter private[jsoniter_scala](
13311330

13321331
private[this] def to400YearCycle(day: Long): Int = (day / 146097).toInt // 146097 == number of days in a 400 year cycle
13331332

1334-
private[this] def toMarchDayOfYear(marchZeroDay: Long, yearEst: Int): Int = {
1335-
val centuryEst = yearEst / 100
1336-
(marchZeroDay - yearEst * 365L).toInt - (yearEst >> 2) + centuryEst - (centuryEst >> 2)
1333+
private[this] def toMarchDayOfYear(marchZeroDay: Long, year: Int): Int = {
1334+
val century = (year * 1374389535L >> 37).toInt // divide an int by 100 (the sign correction is not needed)
1335+
(marchZeroDay - year * 365L).toInt - (year >> 2) + century - (century >> 2)
13371336
}
13381337

13391338
private[this] def writeLocalDate(x: LocalDate): Unit = count = {
@@ -1608,7 +1607,7 @@ final class JsonWriter private[jsoniter_scala](
16081607
buf(p) = '-'
16091608
-totalSeconds
16101609
}
1611-
val q1 = (q0 * 2443359173L >> 43).toInt // divide a positive int by 3600
1610+
val q1 = q0 * 37283 >>> 27 // divide a small positive int by 3600
16121611
val r1 = q0 - q1 * 3600
16131612
var pos = write2Digits(q1, p + 1, buf, ds)
16141613
buf(pos) = ':'

0 commit comments

Comments
 (0)