@@ -201,48 +201,48 @@ class RebaseDateTimeSuite extends SparkFunSuite with Matchers with SQLHelper {
201201 test(" optimization of micros rebasing - Gregorian to Julian" ) {
202202 outstandingZoneIds.foreach { zid =>
203203 withClue(s " zone id = $zid" ) {
204- withDefaultTimeZone(zid) {
205- val start = instantToMicros( LocalDateTime .of( 1 , 1 , 1 , 0 , 0 , 0 )
206- .atZone(zid )
207- .toInstant )
208- val end = instantToMicros( LocalDateTime .of( 2100 , 1 , 1 , 0 , 0 , 0 )
209- .atZone(zid )
210- .toInstant)
211- var micros = start
212- do {
213- val rebased = rebaseGregorianToJulianMicros (zid, micros)
214- val rebasedAndOptimized = rebaseGregorianToJulianMicros(micros)
215- assert(rebasedAndOptimized === rebased)
216- micros += ( MICROS_PER_DAY * 30 * ( 0.5 + Math .random())).toLong
217- } while (micros <= end)
218- }
204+ val start = instantToMicros( LocalDateTime .of( 1 , 1 , 1 , 0 , 0 , 0 )
205+ .atZone(zid )
206+ .toInstant )
207+ val end = instantToMicros( LocalDateTime .of( 2100 , 1 , 1 , 0 , 0 , 0 )
208+ .atZone(zid )
209+ .toInstant )
210+ var micros = start
211+ do {
212+ val rebased = rebaseGregorianToJulianMicros( TimeZone .getTimeZone(zid), micros)
213+ val rebasedAndOptimized = withDefaultTimeZone (zid) {
214+ rebaseGregorianToJulianMicros(micros)
215+ }
216+ assert(rebasedAndOptimized === rebased)
217+ micros += ( MICROS_PER_DAY * 30 * ( 0.5 + Math .random())).toLong
218+ } while (micros <= end)
219219 }
220220 }
221221 }
222222
223223 test(" optimization of micros rebasing - Julian to Gregorian" ) {
224224 outstandingZoneIds.foreach { zid =>
225225 withClue(s " zone id = $zid" ) {
226- withDefaultTimeZone(zid) {
227- val start = rebaseGregorianToJulianMicros(
228- instantToMicros( LocalDateTime .of( 1 , 1 , 1 , 0 , 0 , 0 ).atZone(zid).toInstant))
229- val end = rebaseGregorianToJulianMicros(
230- instantToMicros( LocalDateTime .of( 2100 , 1 , 1 , 0 , 0 , 0 ).atZone(zid).toInstant))
231- var micros = start
232- do {
233- val rebased = rebaseJulianToGregorianMicros (zid, micros)
234- val rebasedAndOptimized = rebaseJulianToGregorianMicros(micros)
235- assert(rebasedAndOptimized === rebased)
236- micros += ( MICROS_PER_DAY * 30 * ( 0.5 + Math .random())).toLong
237- } while (micros <= end)
238- }
226+ val start = rebaseGregorianToJulianMicros(
227+ instantToMicros( LocalDateTime .of( 1 , 1 , 1 , 0 , 0 , 0 ).atZone(zid).toInstant))
228+ val end = rebaseGregorianToJulianMicros(
229+ instantToMicros( LocalDateTime .of( 2100 , 1 , 1 , 0 , 0 , 0 ).atZone(zid).toInstant))
230+ var micros = start
231+ do {
232+ val rebased = rebaseJulianToGregorianMicros( TimeZone .getTimeZone(zid), micros)
233+ val rebasedAndOptimized = withDefaultTimeZone (zid) {
234+ rebaseJulianToGregorianMicros(micros)
235+ }
236+ assert(rebasedAndOptimized === rebased)
237+ micros += ( MICROS_PER_DAY * 30 * ( 0.5 + Math .random())).toLong
238+ } while (micros <= end)
239239 }
240240 }
241241 }
242242
243243 private def generateRebaseJson (
244- adjustFunc : Long => Long ,
245- rebaseFunc : (ZoneId , Long ) => Long ,
244+ adjustFunc : ( TimeZone , Long ) => Long ,
245+ rebaseFunc : (TimeZone , Long ) => Long ,
246246 dir : String ,
247247 fileName : String ): Unit = {
248248 import java .nio .file .{Files , Paths }
@@ -260,14 +260,15 @@ class RebaseDateTimeSuite extends SparkFunSuite with Matchers with SQLHelper {
260260 .sortBy(_.getId)
261261 .foreach { zid =>
262262 withDefaultTimeZone(zid) {
263- val start = adjustFunc(instantToMicros(LocalDateTime .of(1 , 1 , 1 , 0 , 0 , 0 )
264- .atZone(zid)
265- .toInstant))
263+ val tz = TimeZone .getTimeZone(zid)
264+ val start = adjustFunc(
265+ tz,
266+ instantToMicros(LocalDateTime .of(1 , 1 , 1 , 0 , 0 , 0 ).atZone(zid).toInstant))
266267 // sun.util.calendar.ZoneInfo resolves DST after 2037 year incorrectly.
267268 // See https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8073446
268- val end = adjustFunc(instantToMicros( LocalDateTime .of( 2037 , 1 , 1 , 0 , 0 , 0 )
269- .atZone(zid)
270- .toInstant))
269+ val end = adjustFunc(
270+ tz,
271+ instantToMicros( LocalDateTime .of( 2037 , 1 , 1 , 0 , 0 , 0 ).atZone(zid) .toInstant))
271272
272273 var micros = start
273274 var diff = Long .MaxValue
@@ -276,7 +277,7 @@ class RebaseDateTimeSuite extends SparkFunSuite with Matchers with SQLHelper {
276277 val switches = new ArrayBuffer [Long ]()
277278 val diffs = new ArrayBuffer [Long ]()
278279 while (micros < end) {
279- val rebased = rebaseFunc(zid , micros)
280+ val rebased = rebaseFunc(tz , micros)
280281 val curDiff = rebased - micros
281282 if (curDiff != diff) {
282283 if (step > MICROS_PER_SECOND ) {
@@ -308,7 +309,7 @@ class RebaseDateTimeSuite extends SparkFunSuite with Matchers with SQLHelper {
308309
309310 ignore(" generate 'gregorian-julian-rebase-micros.json'" ) {
310311 generateRebaseJson(
311- adjustFunc = identity[ Long ] ,
312+ adjustFunc = ( _ : TimeZone , micros : Long ) => micros ,
312313 rebaseFunc = rebaseGregorianToJulianMicros,
313314 dir = " /Users/maximgekk/tmp" ,
314315 fileName = " gregorian-julian-rebase-micros.json" )
@@ -383,26 +384,27 @@ class RebaseDateTimeSuite extends SparkFunSuite with Matchers with SQLHelper {
383384
384385 test(" rebase not-existed timestamps in the hybrid calendar" ) {
385386 outstandingZoneIds.foreach { zid =>
386- withDefaultTimeZone(zid) {
387- Seq (
388- " 1582-10-04T23:59:59.999999" -> " 1582-10-04 23:59:59.999999" ,
389- " 1582-10-05T00:00:00.000000" -> " 1582-10-15 00:00:00.000000" ,
390- " 1582-10-06T01:02:03.000001" -> " 1582-10-15 01:02:03.000001" ,
391- " 1582-10-07T00:00:00.000000" -> " 1582-10-15 00:00:00.000000" ,
392- " 1582-10-08T23:59:59.999999" -> " 1582-10-15 23:59:59.999999" ,
393- " 1582-10-09T23:59:59.001001" -> " 1582-10-15 23:59:59.001001" ,
394- " 1582-10-10T00:11:22.334455" -> " 1582-10-15 00:11:22.334455" ,
395- " 1582-10-11T11:12:13.111111" -> " 1582-10-15 11:12:13.111111" ,
396- " 1582-10-12T10:11:12.131415" -> " 1582-10-15 10:11:12.131415" ,
397- " 1582-10-13T00:00:00.123321" -> " 1582-10-15 00:00:00.123321" ,
398- " 1582-10-14T23:59:59.999999" -> " 1582-10-15 23:59:59.999999" ,
399- " 1582-10-15T00:00:00.000000" -> " 1582-10-15 00:00:00.000000"
400- ).foreach { case (gregTs, hybridTs) =>
401- withClue(s " tz = ${zid.getId} greg ts = $gregTs hybrid ts = $hybridTs" ) {
402- val hybridMicros = parseToJulianMicros(hybridTs)
403- val gregorianMicros = parseToGregMicros(gregTs, zid)
404-
405- assert(rebaseGregorianToJulianMicros(zid, gregorianMicros) === hybridMicros)
387+ Seq (
388+ " 1582-10-04T23:59:59.999999" -> " 1582-10-04 23:59:59.999999" ,
389+ " 1582-10-05T00:00:00.000000" -> " 1582-10-15 00:00:00.000000" ,
390+ " 1582-10-06T01:02:03.000001" -> " 1582-10-15 01:02:03.000001" ,
391+ " 1582-10-07T00:00:00.000000" -> " 1582-10-15 00:00:00.000000" ,
392+ " 1582-10-08T23:59:59.999999" -> " 1582-10-15 23:59:59.999999" ,
393+ " 1582-10-09T23:59:59.001001" -> " 1582-10-15 23:59:59.001001" ,
394+ " 1582-10-10T00:11:22.334455" -> " 1582-10-15 00:11:22.334455" ,
395+ " 1582-10-11T11:12:13.111111" -> " 1582-10-15 11:12:13.111111" ,
396+ " 1582-10-12T10:11:12.131415" -> " 1582-10-15 10:11:12.131415" ,
397+ " 1582-10-13T00:00:00.123321" -> " 1582-10-15 00:00:00.123321" ,
398+ " 1582-10-14T23:59:59.999999" -> " 1582-10-15 23:59:59.999999" ,
399+ " 1582-10-15T00:00:00.000000" -> " 1582-10-15 00:00:00.000000"
400+ ).foreach { case (gregTs, hybridTs) =>
401+ withClue(s " tz = ${zid.getId} greg ts = $gregTs hybrid ts = $hybridTs" ) {
402+ val hybridMicros = withDefaultTimeZone(zid) { parseToJulianMicros(hybridTs) }
403+ val gregorianMicros = parseToGregMicros(gregTs, zid)
404+
405+ val tz = TimeZone .getTimeZone(zid)
406+ assert(rebaseGregorianToJulianMicros(tz, gregorianMicros) === hybridMicros)
407+ withDefaultTimeZone(zid) {
406408 assert(rebaseGregorianToJulianMicros(gregorianMicros) === hybridMicros)
407409 }
408410 }
@@ -416,38 +418,39 @@ class RebaseDateTimeSuite extends SparkFunSuite with Matchers with SQLHelper {
416418 // clocks were moved backward to become Sunday, 18 November, 1945 01:00:00 AM.
417419 // In this way, the overlap happened w/o Daylight Saving Time.
418420 val hkZid = getZoneId(" Asia/Hong_Kong" )
421+ var expected = " 1945-11-18 01:30:00.0"
422+ var ldt = LocalDateTime .of(1945 , 11 , 18 , 1 , 30 , 0 )
423+ var earlierMicros = instantToMicros(ldt.atZone(hkZid).withEarlierOffsetAtOverlap().toInstant)
424+ var laterMicros = instantToMicros(ldt.atZone(hkZid).withLaterOffsetAtOverlap().toInstant)
425+ var overlapInterval = MICROS_PER_HOUR
426+ if (earlierMicros + overlapInterval != laterMicros) {
427+ // Old JDK might have an outdated time zone database.
428+ // See https://bugs.openjdk.java.net/browse/JDK-8228469: "Hong Kong ... Its 1945 transition
429+ // from JST to HKT was on 11-18 at 02:00, not 09-15 at 00:00"
430+ expected = " 1945-09-14 23:30:00.0"
431+ ldt = LocalDateTime .of(1945 , 9 , 14 , 23 , 30 , 0 )
432+ earlierMicros = instantToMicros(ldt.atZone(hkZid).withEarlierOffsetAtOverlap().toInstant)
433+ laterMicros = instantToMicros(ldt.atZone(hkZid).withLaterOffsetAtOverlap().toInstant)
434+ // If time zone db doesn't have overlapping at all, set the overlap interval to zero.
435+ overlapInterval = laterMicros - earlierMicros
436+ }
437+ val hkTz = TimeZone .getTimeZone(hkZid)
438+ val rebasedEarlierMicros = rebaseGregorianToJulianMicros(hkTz, earlierMicros)
439+ val rebasedLaterMicros = rebaseGregorianToJulianMicros(hkTz, laterMicros)
440+ assert(rebasedEarlierMicros + overlapInterval === rebasedLaterMicros)
419441 withDefaultTimeZone(hkZid) {
420- var expected = " 1945-11-18 01:30:00.0"
421- var ldt = LocalDateTime .of(1945 , 11 , 18 , 1 , 30 , 0 )
422- var earlierMicros = instantToMicros(ldt.atZone(hkZid).withEarlierOffsetAtOverlap().toInstant)
423- var laterMicros = instantToMicros(ldt.atZone(hkZid).withLaterOffsetAtOverlap().toInstant)
424- var overlapInterval = MICROS_PER_HOUR
425- if (earlierMicros + overlapInterval != laterMicros) {
426- // Old JDK might have an outdated time zone database.
427- // See https://bugs.openjdk.java.net/browse/JDK-8228469: "Hong Kong ... Its 1945 transition
428- // from JST to HKT was on 11-18 at 02:00, not 09-15 at 00:00"
429- expected = " 1945-09-14 23:30:00.0"
430- ldt = LocalDateTime .of(1945 , 9 , 14 , 23 , 30 , 0 )
431- earlierMicros = instantToMicros(ldt.atZone(hkZid).withEarlierOffsetAtOverlap().toInstant)
432- laterMicros = instantToMicros(ldt.atZone(hkZid).withLaterOffsetAtOverlap().toInstant)
433- // If time zone db doesn't have overlapping at all, set the overlap interval to zero.
434- overlapInterval = laterMicros - earlierMicros
435- }
436- val rebasedEarlierMicros = rebaseGregorianToJulianMicros(hkZid, earlierMicros)
437- val rebasedLaterMicros = rebaseGregorianToJulianMicros(hkZid, laterMicros)
438442 def toTsStr (micros : Long ): String = toJavaTimestamp(micros).toString
439443 assert(toTsStr(rebasedEarlierMicros) === expected)
440444 assert(toTsStr(rebasedLaterMicros) === expected)
441- assert(rebasedEarlierMicros + overlapInterval === rebasedLaterMicros)
442445 // Check optimized rebasing
443446 assert(rebaseGregorianToJulianMicros(earlierMicros) === rebasedEarlierMicros)
444447 assert(rebaseGregorianToJulianMicros(laterMicros) === rebasedLaterMicros)
445448 // Check reverse rebasing
446449 assert(rebaseJulianToGregorianMicros(rebasedEarlierMicros) === earlierMicros)
447450 assert(rebaseJulianToGregorianMicros(rebasedLaterMicros) === laterMicros)
448- // Check reverse not-optimized rebasing
449- assert(rebaseJulianToGregorianMicros(hkZid, rebasedEarlierMicros) === earlierMicros)
450- assert(rebaseJulianToGregorianMicros(hkZid, rebasedLaterMicros) === laterMicros)
451451 }
452+ // Check reverse not-optimized rebasing
453+ assert(rebaseJulianToGregorianMicros(hkTz, rebasedEarlierMicros) === earlierMicros)
454+ assert(rebaseJulianToGregorianMicros(hkTz, rebasedLaterMicros) === laterMicros)
452455 }
453456}
0 commit comments