Skip to content

Commit

Permalink
HIVE-28337: TestMetaStoreUtils fails for invalid timestamps
Browse files Browse the repository at this point in the history
  • Loading branch information
KiranVelumuri committed Jul 1, 2024
1 parent 7f87a3b commit eea8f9c
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,13 @@ public static String normalizeDate(String date) {
* @return Timestamp in string format.
*/
public static String convertTimestampToString(Timestamp timestamp) {
return TIMESTAMP_FORMATTER.format(timestamp.toLocalDateTime());
TimeZone defaultTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

String str = TIMESTAMP_FORMATTER.format(timestamp.toLocalDateTime());

TimeZone.setDefault(defaultTimeZone);
return str;
}

/**
Expand All @@ -132,8 +138,14 @@ public static String convertTimestampToString(Timestamp timestamp) {
* @return java.sql.Timestamp object.
*/
public static Timestamp convertStringToTimestamp(String timestamp) {
TimeZone defaultTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

LocalDateTime val = LocalDateTime.from(TIMESTAMP_FORMATTER.parse(timestamp));
return Timestamp.valueOf(val);
Timestamp ts = Timestamp.valueOf(val);

TimeZone.setDefault(defaultTimeZone);
return ts;
}

// Indicates a type was derived from the deserializer rather than Hive's metadata.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,52 @@ public class TestMetaStoreUtils {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
private final TimeZone timezone;
private final String date;
private final String timestamp;
private final String timestampString;
private final Timestamp timestamp;

public TestMetaStoreUtils(String zoneId, LocalDateTime timestamp) {
this.timezone = TimeZone.getTimeZone(zoneId);
this.timestamp = timestamp.format(FORMATTER);
this.timestampString = timestamp.format(FORMATTER);
this.date = timestamp.toLocalDate().format(DateTimeFormatter.ISO_LOCAL_DATE);

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
this.timestamp = Timestamp.valueOf(timestamp);
TimeZone.setDefault(DEFAULT);
}

@Parameterized.Parameters(name = "zoneId={0}, timestamp={1}")
public static Collection<Object[]> generateZoneTimestampPairs() {
List<Object[]> params = new ArrayList<>();
long minDate = LocalDate.of(0, 1, 1).atStartOfDay().toEpochSecond(ZoneOffset.UTC);
long minDate = LocalDate.of(1, 1, 1).atStartOfDay().toEpochSecond(ZoneOffset.UTC);
long maxDate = LocalDate.of(9999, 12, 31).atStartOfDay().toEpochSecond(ZoneOffset.UTC);
new Random(23).longs(500, minDate, maxDate).forEach(i -> {
LocalDateTime datetime = LocalDateTime.ofEpochSecond(i, 0, ZoneOffset.UTC);
for (String zone : ZoneId.SHORT_IDS.values()) {
params.add(new Object[] { zone, datetime });
}
});
generateDaylightSavingTimestampPairs(params);
return params;
}

public static void generateDaylightSavingTimestampPairs(List<Object[]> params) {
// For U.S timezones, the timestamp 2024-03-10 02:01:00 falls between the transition from 02:00 AM to 03:00 AM for daylight savings
params.add(new Object[] {"America/Anchorage", LocalDateTime.ofEpochSecond(1710036060L, 0, ZoneOffset.UTC)});
params.add(new Object[] {"America/St_Johns", LocalDateTime.ofEpochSecond(1710036060L, 0, ZoneOffset.UTC)});
params.add(new Object[] {"America/Chicago", LocalDateTime.ofEpochSecond(1710036060L, 0, ZoneOffset.UTC)});
params.add(new Object[] {"America/Indiana/Indianapolis", LocalDateTime.ofEpochSecond(1710036060L, 0, ZoneOffset.UTC)});
params.add(new Object[] {"America/Los_Angeles", LocalDateTime.ofEpochSecond(1710036060L, 0, ZoneOffset.UTC)});

// For Paris timezone, the timestamp 2024-03-31 02:02:02 falls between the transition from 02:00 AM to 03:00 AM for daylight savings
params.add(new Object[] {"Europe/Paris", LocalDateTime.ofEpochSecond(1711850522L, 0, ZoneOffset.UTC)});

// For New Zealand timezone, the timestamp 2024-09-29 02:03:04 falls between the transition from 02:00 AM to 03:00 AM for daylight savings
params.add(new Object[] {"Pacific/Auckland", LocalDateTime.ofEpochSecond(1727575384L, 0, ZoneOffset.UTC)});

// For Sydney timezone, the timestamp 2024-10-06 02:04:06 falls between the transition from 02:00 AM to 03:00 AM for daylight savings
params.add(new Object[] {"Australia/Sydney", LocalDateTime.ofEpochSecond(1728180246L, 0, ZoneOffset.UTC)});
}

@Before
public void setup() {
TimeZone.setDefault(timezone);
Expand All @@ -82,7 +106,7 @@ public void testDateToString() {

@Test
public void testTimestampToString() {
assertEquals(timestamp, MetaStoreUtils.convertTimestampToString(Timestamp.valueOf(timestamp)));
assertEquals(timestampString, MetaStoreUtils.convertTimestampToString(timestamp));
}

@Test
Expand All @@ -92,7 +116,7 @@ public void testStringToDate() {

@Test
public void testStringToTimestamp() {
assertEquals(Timestamp.valueOf(timestamp), MetaStoreUtils.convertStringToTimestamp(timestamp));
assertEquals(timestamp, MetaStoreUtils.convertStringToTimestamp(timestampString));
}

@AfterClass
Expand Down

0 comments on commit eea8f9c

Please sign in to comment.