55import java .io .Reader ;
66import java .math .BigDecimal ;
77import java .math .BigInteger ;
8+ import java .sql .Date ;
89import java .sql .SQLException ;
910import java .sql .Timestamp ;
1011import java .time .Duration ;
1718import java .time .format .DateTimeParseException ;
1819import java .util .Arrays ;
1920import java .util .Collection ;
20- import java .util .Date ;
2121import java .util .UUID ;
22- import java .util .concurrent .TimeUnit ;
2322
2423import com .google .common .io .ByteStreams ;
2524import com .google .common .io .CharStreams ;
@@ -370,6 +369,11 @@ private static PrimitiveValue castToDate(PrimitiveType type, Object x) throws SQ
370369 return PrimitiveValue .newDate (LocalDate .ofEpochDay ((Integer ) x ));
371370 } else if (x instanceof Long ) {
372371 return PrimitiveValue .newDate (LocalDate .ofEpochDay ((Long ) x ));
372+ } else if (x instanceof Timestamp ) {
373+ // Normalize date - use system timezone to detect correct date
374+ Instant instant = Instant .ofEpochMilli (((Timestamp ) x ).getTime ());
375+ LocalDate ld = instant .atZone (ZoneId .systemDefault ()).toLocalDate ();
376+ return PrimitiveValue .newDate (ld );
373377 } else if (x instanceof Date ) {
374378 // Normalize date - use system timezone to detect correct date
375379 Instant instant = Instant .ofEpochMilli (((Date ) x ).getTime ());
@@ -394,11 +398,16 @@ private static PrimitiveValue castToDateTime(PrimitiveType type, Object x) throw
394398 return PrimitiveValue .newDatetime (((LocalDate ) x ).atStartOfDay ());
395399 } else if (x instanceof Long ) {
396400 return PrimitiveValue .newDatetime (LocalDateTime .ofEpochSecond ((Long ) x , 0 , ZoneOffset .UTC ));
397- } else if (x instanceof Date ) {
401+ } else if (x instanceof Timestamp ) {
398402 // Normalize date - use system timezone to detect correct date
399- Instant instant = Instant .ofEpochMilli (((Date ) x ).getTime ());
403+ Instant instant = Instant .ofEpochMilli (((Timestamp ) x ).getTime ());
400404 LocalDateTime ldt = instant .atZone (ZoneId .systemDefault ()).toLocalDateTime ();
401405 return PrimitiveValue .newDatetime (ldt );
406+ } else if (x instanceof Date ) {
407+ // Normalize date - use system timezone to detect correct date
408+ Instant instant = Instant .ofEpochMilli (((Date ) x ).getTime ());
409+ LocalDate ld = instant .atZone (ZoneId .systemDefault ()).toLocalDate ();
410+ return PrimitiveValue .newDatetime (ld .atStartOfDay ());
402411 } else if (x instanceof String ) {
403412 try {
404413 return PrimitiveValue .newDatetime (LocalDateTime .parse ((String ) x ));
@@ -413,29 +422,23 @@ private static PrimitiveValue castToTimestamp(PrimitiveType type, Object x) thro
413422 if (x instanceof Instant ) {
414423 return PrimitiveValue .newTimestamp ((Instant ) x );
415424 } else if (x instanceof Long ) {
416- return PrimitiveValue .newTimestamp (TimeUnit . MILLISECONDS . toMicros ((Long ) x ));
425+ return PrimitiveValue .newTimestamp (Instant . ofEpochMilli ((Long ) x ));
417426 } else if (x instanceof LocalDate ) {
418- return PrimitiveValue .newTimestamp (((LocalDate ) x ).toEpochDay () * 24 * 60 * 60 * 1000000 );
427+ return PrimitiveValue .newTimestamp (((LocalDate ) x ).atStartOfDay (). toInstant ( ZoneOffset . UTC ) );
419428 } else if (x instanceof LocalDateTime ) {
420- // LocalDateTime is usually used as Datetime analog, so truncate it to seconds
421- long seconds = ((LocalDateTime ) x ).toInstant (ZoneOffset .UTC ).getEpochSecond ();
422- return PrimitiveValue .newTimestamp (seconds * 1000000 );
429+ long epochSeconds = ((LocalDateTime ) x ).toEpochSecond (ZoneOffset .UTC );
430+ return PrimitiveValue .newTimestamp (Instant .ofEpochSecond (epochSeconds ));
423431 } else if (x instanceof Timestamp ) {
424- return PrimitiveValue .newTimestamp (TimeUnit . MILLISECONDS . toMicros ((( Timestamp ) x ).getTime () ));
432+ return PrimitiveValue .newTimestamp ((( Timestamp ) x ).toInstant ( ));
425433 } else if (x instanceof Date ) {
426- // Normalize date to UTC
427- // Normalize date - use system timezone to detect correct datetime
428- Instant instant = Instant .ofEpochMilli (((Date ) x ).getTime ());
429- LocalDate ld = instant .atZone (ZoneId .systemDefault ()).toLocalDate ();
430- return PrimitiveValue .newTimestamp (ld .toEpochDay () * 24 * 60 * 60 * 1000000 );
434+ Instant instant = ((Date ) x ).toLocalDate ().atStartOfDay ().toInstant (ZoneOffset .UTC );
435+ return PrimitiveValue .newTimestamp (instant );
431436 } else if (x instanceof String ) {
432- Instant parsed ;
433437 try {
434- parsed = Instant .parse ((String ) x );
438+ return PrimitiveValue . newTimestamp ( Instant .parse ((String ) x ) );
435439 } catch (DateTimeParseException e ) {
436440 throw castNotSupported (type , x , e );
437441 }
438- return PrimitiveValue .newTimestamp (parsed );
439442 }
440443 throw castNotSupported (type , x );
441444 }
0 commit comments