@@ -27,6 +27,8 @@ import org.apache.spark.unsafe.types.UTF8String
2727
2828class DateTimeUtilsSuite extends SparkFunSuite {
2929
30+ val TimeZonePST = TimeZone .getTimeZone(" PST" )
31+
3032 private [this ] def getInUTCDays (timestamp : Long ): Int = {
3133 val tz = TimeZone .getDefault
3234 ((timestamp + tz.getOffset(timestamp)) / MILLIS_PER_DAY ).toInt
@@ -384,27 +386,35 @@ class DateTimeUtilsSuite extends SparkFunSuite {
384386 }
385387
386388 test(" hours" ) {
387- val c = Calendar .getInstance()
389+ val c = Calendar .getInstance(TimeZonePST )
388390 c.set(2015 , 2 , 18 , 13 , 2 , 11 )
389- assert(getHours(c.getTimeInMillis * 1000 ) === 13 )
391+ assert(getHours(c.getTimeInMillis * 1000 , TimeZonePST ) === 13 )
392+ assert(getHours(c.getTimeInMillis * 1000 , TimeZoneGMT ) === 20 )
390393 c.set(2015 , 12 , 8 , 2 , 7 , 9 )
391- assert(getHours(c.getTimeInMillis * 1000 ) === 2 )
394+ assert(getHours(c.getTimeInMillis * 1000 , TimeZonePST ) === 2 )
395+ assert(getHours(c.getTimeInMillis * 1000 , TimeZoneGMT ) === 10 )
392396 }
393397
394398 test(" minutes" ) {
395- val c = Calendar .getInstance()
399+ val c = Calendar .getInstance(TimeZonePST )
396400 c.set(2015 , 2 , 18 , 13 , 2 , 11 )
397- assert(getMinutes(c.getTimeInMillis * 1000 ) === 2 )
401+ assert(getMinutes(c.getTimeInMillis * 1000 , TimeZonePST ) === 2 )
402+ assert(getMinutes(c.getTimeInMillis * 1000 , TimeZoneGMT ) === 2 )
403+ assert(getMinutes(c.getTimeInMillis * 1000 , TimeZone .getTimeZone(" Australia/North" )) === 32 )
398404 c.set(2015 , 2 , 8 , 2 , 7 , 9 )
399- assert(getMinutes(c.getTimeInMillis * 1000 ) === 7 )
405+ assert(getMinutes(c.getTimeInMillis * 1000 , TimeZonePST ) === 7 )
406+ assert(getMinutes(c.getTimeInMillis * 1000 , TimeZoneGMT ) === 7 )
407+ assert(getMinutes(c.getTimeInMillis * 1000 , TimeZone .getTimeZone(" Australia/North" )) === 37 )
400408 }
401409
402410 test(" seconds" ) {
403- val c = Calendar .getInstance()
411+ val c = Calendar .getInstance(TimeZonePST )
404412 c.set(2015 , 2 , 18 , 13 , 2 , 11 )
405- assert(getSeconds(c.getTimeInMillis * 1000 ) === 11 )
413+ assert(getSeconds(c.getTimeInMillis * 1000 , TimeZonePST ) === 11 )
414+ assert(getSeconds(c.getTimeInMillis * 1000 , TimeZoneGMT ) === 11 )
406415 c.set(2015 , 2 , 8 , 2 , 7 , 9 )
407- assert(getSeconds(c.getTimeInMillis * 1000 ) === 9 )
416+ assert(getSeconds(c.getTimeInMillis * 1000 , TimeZonePST ) === 9 )
417+ assert(getSeconds(c.getTimeInMillis * 1000 , TimeZoneGMT ) === 9 )
408418 }
409419
410420 test(" hours / minutes / seconds" ) {
@@ -478,6 +488,21 @@ class DateTimeUtilsSuite extends SparkFunSuite {
478488 c2.set(Calendar .MILLISECOND , 123 )
479489 val ts2 = c2.getTimeInMillis * 1000L
480490 assert(timestampAddInterval(ts1, 36 , 123000 ) === ts2)
491+
492+ val c3 = Calendar .getInstance(TimeZonePST )
493+ c3.set(1997 , 1 , 27 , 16 , 0 , 0 )
494+ c3.set(Calendar .MILLISECOND , 0 )
495+ val ts3 = c3.getTimeInMillis * 1000L
496+ val c4 = Calendar .getInstance(TimeZonePST )
497+ c4.set(2000 , 1 , 27 , 16 , 0 , 0 )
498+ c4.set(Calendar .MILLISECOND , 123 )
499+ val ts4 = c4.getTimeInMillis * 1000L
500+ val c5 = Calendar .getInstance(TimeZoneGMT )
501+ c5.set(2000 , 1 , 29 , 0 , 0 , 0 )
502+ c5.set(Calendar .MILLISECOND , 123 )
503+ val ts5 = c5.getTimeInMillis * 1000L
504+ assert(timestampAddInterval(ts3, 36 , 123000 , TimeZonePST ) === ts4)
505+ assert(timestampAddInterval(ts3, 36 , 123000 , TimeZoneGMT ) === ts5)
481506 }
482507
483508 test(" monthsBetween" ) {
@@ -492,6 +517,17 @@ class DateTimeUtilsSuite extends SparkFunSuite {
492517 assert(monthsBetween(c1.getTimeInMillis * 1000L , c2.getTimeInMillis * 1000L ) === - 36 )
493518 c2.set(1996 , 2 , 31 , 0 , 0 , 0 )
494519 assert(monthsBetween(c1.getTimeInMillis * 1000L , c2.getTimeInMillis * 1000L ) === 11 )
520+
521+ val c3 = Calendar .getInstance(TimeZonePST )
522+ c3.set(2000 , 1 , 28 , 16 , 0 , 0 )
523+ val c4 = Calendar .getInstance(TimeZonePST )
524+ c4.set(1997 , 1 , 28 , 16 , 0 , 0 )
525+ assert(
526+ monthsBetween(c3.getTimeInMillis * 1000L , c4.getTimeInMillis * 1000L , TimeZonePST )
527+ === 36.0 )
528+ assert(
529+ monthsBetween(c3.getTimeInMillis * 1000L , c4.getTimeInMillis * 1000L , TimeZoneGMT )
530+ === 35.90322581 )
495531 }
496532
497533 test(" from UTC timestamp" ) {
@@ -548,6 +584,21 @@ class DateTimeUtilsSuite extends SparkFunSuite {
548584 }
549585
550586 test(" daysToMillis and millisToDays" ) {
587+ val c = Calendar .getInstance(TimeZonePST )
588+
589+ c.set(2015 , 11 , 31 , 16 , 0 , 0 )
590+ assert(millisToDays(c.getTimeInMillis, TimeZonePST ) === 16800 )
591+ assert(millisToDays(c.getTimeInMillis, TimeZoneGMT ) === 16801 )
592+
593+ c.set(2015 , 11 , 31 , 0 , 0 , 0 )
594+ c.set(Calendar .MILLISECOND , 0 )
595+ assert(daysToMillis(16800 , TimeZonePST ) === c.getTimeInMillis)
596+
597+ c.setTimeZone(TimeZoneGMT )
598+ c.set(2015 , 11 , 31 , 0 , 0 , 0 )
599+ c.set(Calendar .MILLISECOND , 0 )
600+ assert(daysToMillis(16800 , TimeZoneGMT ) === c.getTimeInMillis)
601+
551602 // There are some days are skipped entirely in some timezone, skip them here.
552603 val skipped_days = Map [String , Int ](
553604 " Kwajalein" -> 8632 ,
@@ -558,13 +609,11 @@ class DateTimeUtilsSuite extends SparkFunSuite {
558609 " Pacific/Kwajalein" -> 8632 ,
559610 " MIT" -> 15338 )
560611 for (tz <- DateTimeTestUtils .ALL_TIMEZONES ) {
561- DateTimeTestUtils .withDefaultTimeZone(tz) {
562- val skipped = skipped_days.getOrElse(tz.getID, Int .MinValue )
563- (- 20000 to 20000 ).foreach { d =>
564- if (d != skipped) {
565- assert(millisToDays(daysToMillis(d)) === d,
566- s " Round trip of ${d} did not work in tz ${tz}" )
567- }
612+ val skipped = skipped_days.getOrElse(tz.getID, Int .MinValue )
613+ (- 20000 to 20000 ).foreach { d =>
614+ if (d != skipped) {
615+ assert(millisToDays(daysToMillis(d, tz), tz) === d,
616+ s " Round trip of ${d} did not work in tz ${tz}" )
568617 }
569618 }
570619 }
0 commit comments