The valid range and number of bits required by each date/time field is as the following: + * + *
| Field | Range | #Bits |
|---|---|---|
| Year | [1, 9999] | 14 |
| Month | [1, 12] | 4 |
| Day | [1, 31] | 5 |
| Hour | [0, 23] | 5 |
| Minute | [0, 59] | 6 |
| Second | [0, 59]* | 6 |
| Micros | [0, 999999] | 20 |
| Nanos | [0, 999999999] | 30 |
* Leap second is not supported. + * + *
When encoding the TIME or DATETIME into a bit field, larger date/time field is on the more + * significant side. + */ +public final class CivilTimeEncoder { + private static final int NANO_LENGTH = 30; + private static final int MICRO_LENGTH = 20; + + private static final int NANO_SHIFT = 0; + private static final int MICRO_SHIFT = 0; + private static final int SECOND_SHIFT = 0; + private static final int MINUTE_SHIFT = 6; + private static final int HOUR_SHIFT = 12; + private static final int DAY_SHIFT = 17; + private static final int MONTH_SHIFT = 22; + private static final int YEAR_SHIFT = 26; + + private static final long NANO_MASK = 0x3FFFFFFFL; + private static final long MICRO_MASK = 0xFFFFFL; + private static final long SECOND_MASK = 0x3FL; + private static final long MINUTE_MASK = 0xFC0L; + private static final long HOUR_MASK = 0x1F000L; + private static final long DAY_MASK = 0x3E0000L; + private static final long MONTH_MASK = 0x3C00000L; + private static final long YEAR_MASK = 0xFFFC000000L; + + private static final long TIME_SECONDS_MASK = 0x1FFFFL; + private static final long TIME_MICROS_MASK = 0x1FFFFFFFFFL; + private static final long TIME_NANOS_MASK = 0x7FFFFFFFFFFFL; + private static final long DATETIME_SECONDS_MASK = 0xFFFFFFFFFFL; + private static final long DATETIME_MICROS_MASK = 0xFFFFFFFFFFFFFFFL; + + /** + * Encodes {@code time} as a 4-byte integer with seconds precision. + * + *
Encoding is as the following: + * + *
+ * 3 2 1 + * MSB 10987654321098765432109876543210 LSB + * | H || M || S | + *+ * + * @see #decodePacked32TimeSeconds(int) + */ + @SuppressWarnings("GoodTime-ApiWithNumericTimeUnit") + private static int encodePacked32TimeSeconds(LocalTime time) { + checkValidTimeSeconds(time); + int bitFieldTimeSeconds = 0x0; + bitFieldTimeSeconds |= time.getHour() << HOUR_SHIFT; + bitFieldTimeSeconds |= time.getMinute() << MINUTE_SHIFT; + bitFieldTimeSeconds |= time.getSecond() << SECOND_SHIFT; + return bitFieldTimeSeconds; + } + + /** + * Decodes {@code bitFieldTimeSeconds} as a {@link LocalTime} with seconds precision. + * + *
Encoding is as the following: + * + *
+ * 3 2 1 + * MSB 10987654321098765432109876543210 LSB + * | H || M || S | + *+ * + * @see #encodePacked32TimeSeconds(LocalTime) + */ + @SuppressWarnings("GoodTime-ApiWithNumericTimeUnit") + private static LocalTime decodePacked32TimeSeconds(int bitFieldTimeSeconds) { + checkValidBitField(bitFieldTimeSeconds, TIME_SECONDS_MASK); + int hourOfDay = getFieldFromBitField(bitFieldTimeSeconds, HOUR_MASK, HOUR_SHIFT); + int minuteOfHour = getFieldFromBitField(bitFieldTimeSeconds, MINUTE_MASK, MINUTE_SHIFT); + int secondOfMinute = getFieldFromBitField(bitFieldTimeSeconds, SECOND_MASK, SECOND_SHIFT); + // LocalTime validates the input parameters. + try { + return LocalTime.of(hourOfDay, minuteOfHour, secondOfMinute); + } catch (DateTimeException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } + } + + /** + * Encodes {@code time} as a 8-byte integer with microseconds precision. + * + *
Encoding is as the following: + * + *
+ * 6 5 4 3 2 1 + * MSB 3210987654321098765432109876543210987654321098765432109876543210 LSB + * | H || M || S ||-------micros-----| + *+ * + * @see #decodePacked64TimeMicros(long) + * @see #encodePacked64TimeMicros(LocalTime) + */ + @SuppressWarnings("GoodTime") + public static long encodePacked64TimeMicros(LocalTime time) { + checkValidTimeMicros(time); + return (((long) encodePacked32TimeSeconds(time)) << MICRO_LENGTH) | (time.getNano() / 1_000L); + } + + /** + * Decodes {@code bitFieldTimeMicros} as a {@link LocalTime} with microseconds precision. + * + *
Encoding is as the following: + * + *
+ * 6 5 4 3 2 1 + * MSB 3210987654321098765432109876543210987654321098765432109876543210 LSB + * | H || M || S ||-------micros-----| + *+ * + * @see #encodePacked64TimeMicros(LocalTime) + */ + @SuppressWarnings("GoodTime-ApiWithNumericTimeUnit") + public static LocalTime decodePacked64TimeMicros(long bitFieldTimeMicros) { + checkValidBitField(bitFieldTimeMicros, TIME_MICROS_MASK); + int bitFieldTimeSeconds = (int) (bitFieldTimeMicros >> MICRO_LENGTH); + LocalTime timeSeconds = decodePacked32TimeSeconds(bitFieldTimeSeconds); + int microOfSecond = getFieldFromBitField(bitFieldTimeMicros, MICRO_MASK, MICRO_SHIFT); + checkValidMicroOfSecond(microOfSecond); + LocalTime time = timeSeconds.withNano(microOfSecond * 1000); + checkValidTimeMicros(time); + return time; + } + + /** + * Encodes {@code dateTime} as a 8-byte integer with seconds precision. + * + *
Encoding is as the following: + * + *
+ * 6 5 4 3 2 1 + * MSB 3210987654321098765432109876543210987654321098765432109876543210 LSB + * |--- year ---||m || D || H || M || S | + *+ * + * @see #decodePacked64DatetimeSeconds(long) + */ + @SuppressWarnings("GoodTime-ApiWithNumericTimeUnit") + private static long encodePacked64DatetimeSeconds(LocalDateTime dateTime) { + checkValidDateTimeSeconds(dateTime); + long bitFieldDatetimeSeconds = 0x0L; + bitFieldDatetimeSeconds |= (long) dateTime.getYear() << YEAR_SHIFT; + bitFieldDatetimeSeconds |= (long) dateTime.getMonthValue() << MONTH_SHIFT; + bitFieldDatetimeSeconds |= (long) dateTime.getDayOfMonth() << DAY_SHIFT; + bitFieldDatetimeSeconds |= (long) encodePacked32TimeSeconds(dateTime.toLocalTime()); + return bitFieldDatetimeSeconds; + } + + /** + * Decodes {@code bitFieldDatetimeSeconds} as a {@link LocalDateTime} with seconds precision. + * + *
Encoding is as the following: + * + *
+ * 6 5 4 3 2 1 + * MSB 3210987654321098765432109876543210987654321098765432109876543210 LSBa + * |--- year ---||m || D || H || M || S | + *+ * + * @see #encodePacked64DatetimeSeconds(LocalDateTime) + */ + @SuppressWarnings("GoodTime-ApiWithNumericTimeUnit") + private static LocalDateTime decodePacked64DatetimeSeconds(long bitFieldDatetimeSeconds) { + checkValidBitField(bitFieldDatetimeSeconds, DATETIME_SECONDS_MASK); + int bitFieldTimeSeconds = (int) (bitFieldDatetimeSeconds & TIME_SECONDS_MASK); + LocalTime timeSeconds = decodePacked32TimeSeconds(bitFieldTimeSeconds); + int year = getFieldFromBitField(bitFieldDatetimeSeconds, YEAR_MASK, YEAR_SHIFT); + int monthOfYear = getFieldFromBitField(bitFieldDatetimeSeconds, MONTH_MASK, MONTH_SHIFT); + int dayOfMonth = getFieldFromBitField(bitFieldDatetimeSeconds, DAY_MASK, DAY_SHIFT); + try { + LocalDateTime dateTime = + LocalDateTime.of( + year, + monthOfYear, + dayOfMonth, + timeSeconds.getHour(), + timeSeconds.getMinute(), + timeSeconds.getSecond()); + checkValidDateTimeSeconds(dateTime); + return dateTime; + } catch (DateTimeException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } + } + + /** + * Encodes {@code dateTime} as a 8-byte integer with microseconds precision. + * + *
Encoding is as the following: + * + *
+ * 6 5 4 3 2 1 + * MSB 3210987654321098765432109876543210987654321098765432109876543210 LSB + * |--- year ---||m || D || H || M || S ||-------micros-----| + *+ * + * @see #decodePacked64DatetimeMicros(long) + */ + @SuppressWarnings({"GoodTime-ApiWithNumericTimeUnit", "JavaLocalDateTimeGetNano"}) + public static long encodePacked64DatetimeMicros(LocalDateTime dateTime) { + checkValidDateTimeMicros(dateTime); + return (encodePacked64DatetimeSeconds(dateTime) << MICRO_LENGTH) + | (dateTime.getNano() / 1_000L); + } + + /** + * Decodes {@code bitFieldDatetimeMicros} as a {@link LocalDateTime} with microseconds precision. + * + *
Encoding is as the following: + * + *
+ * 6 5 4 3 2 1 + * MSB 3210987654321098765432109876543210987654321098765432109876543210 LSB + * |--- year ---||m || D || H || M || S ||-------micros-----| + *+ * + * @see #encodePacked64DatetimeMicros(LocalDateTime) + */ + @SuppressWarnings("GoodTime-ApiWithNumericTimeUnit") + public static LocalDateTime decodePacked64DatetimeMicros(long bitFieldDatetimeMicros) { + checkValidBitField(bitFieldDatetimeMicros, DATETIME_MICROS_MASK); + long bitFieldDatetimeSeconds = bitFieldDatetimeMicros >> MICRO_LENGTH; + LocalDateTime dateTimeSeconds = decodePacked64DatetimeSeconds(bitFieldDatetimeSeconds); + int microOfSecond = getFieldFromBitField(bitFieldDatetimeMicros, MICRO_MASK, MICRO_SHIFT); + checkValidMicroOfSecond(microOfSecond); + LocalDateTime dateTime = dateTimeSeconds.withNano(microOfSecond * 1_000); + checkValidDateTimeMicros(dateTime); + return dateTime; + } + + private static int getFieldFromBitField(long bitField, long mask, int shift) { + return (int) ((bitField & mask) >> shift); + } + + private static void checkValidTimeSeconds(LocalTime time) { + checkArgument(time.getHour() >= 0 && time.getHour() <= 23); + checkArgument(time.getMinute() >= 0 && time.getMinute() <= 59); + checkArgument(time.getSecond() >= 0 && time.getSecond() <= 59); + } + + private static void checkValidDateTimeSeconds(LocalDateTime dateTime) { + checkArgument(dateTime.getYear() >= 1 && dateTime.getYear() <= 9999); + checkArgument(dateTime.getMonthValue() >= 1 && dateTime.getMonthValue() <= 12); + checkArgument(dateTime.getDayOfMonth() >= 1 && dateTime.getDayOfMonth() <= 31); + checkValidTimeSeconds(dateTime.toLocalTime()); + } + + private static void checkValidTimeMicros(LocalTime time) { + checkValidTimeSeconds(time); + checkArgument(time.equals(time.truncatedTo(ChronoUnit.MICROS))); + } + + private static void checkValidDateTimeMicros(LocalDateTime dateTime) { + checkValidDateTimeSeconds(dateTime); + checkArgument(dateTime.equals(dateTime.truncatedTo(ChronoUnit.MICROS))); + } + + private static void checkValidMicroOfSecond(int microOfSecond) { + checkArgument(microOfSecond >= 0 && microOfSecond <= 999999); + } + + private static void checkValidBitField(long bitField, long mask) { + checkArgument((bitField & ~mask) == 0x0L); + } + + private CivilTimeEncoder() {} +} diff --git a/google-cloud-bigquerystorage/src/test/java/com/google/cloud/bigquery/storage/v1beta2/CivilTimeEncoderTest.java b/google-cloud-bigquerystorage/src/test/java/com/google/cloud/bigquery/storage/v1beta2/CivilTimeEncoderTest.java new file mode 100644 index 0000000000..5711a05617 --- /dev/null +++ b/google-cloud-bigquerystorage/src/test/java/com/google/cloud/bigquery/storage/v1beta2/CivilTimeEncoderTest.java @@ -0,0 +1,334 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.bigquery.storage.v1beta2; + +import static org.junit.Assert.assertEquals; + +import java.util.logging.Logger; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.threeten.bp.LocalDateTime; +import org.threeten.bp.LocalTime; + +@RunWith(JUnit4.class) +public class CivilTimeEncoderTest { + private static final Logger LOG = Logger.getLogger(CivilTimeEncoderTest.class.getName()); + + // Time + @Test + public void encodeAndDecodePacked64TimeMicros_validTime() { + // 00:00:00.000000 + // 0b000000000000000000000000000|00000|000000|000000|00000000000000000000 + // 0x0 + assertEquals(0x0L, CivilTimeEncoder.encodePacked64TimeMicros(LocalTime.of(0, 0, 0, 0))); + assertEquals(LocalTime.of(0, 0, 0, 0), CivilTimeEncoder.decodePacked64TimeMicros(0x0L)); + + // 00:01:02.003000 + // 0b000000000000000000000000000|00000|000001|000010|00000000101110111000 + // 0x4200BB8 + assertEquals( + 0x4200BB8L, CivilTimeEncoder.encodePacked64TimeMicros(LocalTime.of(0, 1, 2, 3_000_000))); + assertEquals( + LocalTime.of(0, 1, 2, 3_000_000), CivilTimeEncoder.decodePacked64TimeMicros(0x4200BB8L)); + + // 12:00:00.000000 + // 0b000000000000000000000000000|01100|000000|000000|00000000000000000000 + // 0xC00000000 + assertEquals( + 0xC00000000L, CivilTimeEncoder.encodePacked64TimeMicros(LocalTime.of(12, 0, 0, 0))); + assertEquals( + LocalTime.of(12, 0, 0, 0), CivilTimeEncoder.decodePacked64TimeMicros(0xC00000000L)); + + // 13:14:15.016000 + // 0b000000000000000000000000000|01101|001110|001111|00000011111010000000 + // 0xD38F03E80 + assertEquals( + 0xD38F03E80L, + CivilTimeEncoder.encodePacked64TimeMicros(LocalTime.of(13, 14, 15, 16_000_000))); + assertEquals( + LocalTime.of(13, 14, 15, 16_000_000), + CivilTimeEncoder.decodePacked64TimeMicros(0xD38F03E80L)); + + // 23:59:59.999000 + // 0b000000000000000000000000000|10111|111011|111011|11110011111001011000 + // 0x17EFBF3E58 + assertEquals( + 0x17EFBF3E58L, + CivilTimeEncoder.encodePacked64TimeMicros(LocalTime.of(23, 59, 59, 999_000_000))); + assertEquals( + LocalTime.of(23, 59, 59, 999_000_000), + CivilTimeEncoder.decodePacked64TimeMicros(0x17EFBF3E58L)); + } + + @Test + public void encodePacked64TimeMicros_giveErrorWhenPrecisionIsLost() { + try { // 00:00:00.000000999 + // 0b000000000000000000000000000|00000|000000|000000|00000000000000000000 + // 0x0 + assertEquals(0x0L, CivilTimeEncoder.encodePacked64TimeMicros(LocalTime.of(0, 0, 0, 999))); + Assert.fail(); + } catch (IllegalArgumentException e) { + } + } + + @Test + public void decodePacked64TimeMicros_invalidBitField_throwsIllegalArgumentException() { + try { + // 00:00:00.000000 + // 0b000000000000000000000000001|00000|000000|000000|00000000000000000000 + // 0x2000000000 + CivilTimeEncoder.decodePacked64TimeMicros(0x2000000000L); + Assert.fail(); + } catch (IllegalArgumentException e) { + assertEquals(null, e.getMessage()); + } + } + + @Test + public void decodePacked64TimeMicros_invalidMicroOfSecond_throwsIllegalArgumentException() { + try { + // 00:00:00.1000000 + // 0b000000000000000000000000000|00000|000000|000000|11110100001001000000 + // 0xF4240 + CivilTimeEncoder.decodePacked64TimeMicros(0xF4240L); + Assert.fail(); + } catch (IllegalArgumentException e) { + assertEquals(null, e.getMessage()); + } + } + + @Test + public void decodePacked64TimeMicros_invalidSecondOfMinute_throwsIllegalArgumentException() { + try { + // 00:00:60.000000 + // 0b000000000000000000000000000|00000|000000|111100|00000000000000000000 + // 0x3C00000 + CivilTimeEncoder.decodePacked64TimeMicros(0x3C00000L); + Assert.fail(); + } catch (IllegalArgumentException e) { + assertEquals("Invalid value for SecondOfMinute (valid values 0 - 59): 60", e.getMessage()); + } + } + + @Test + public void decodePacked64TimeMicros_invalidMinuteOfHour_throwsIllegalArgumentException() { + try { + // 00:60:00.000000 + // 0b000000000000000000000000000|00000|111100|000000|00000000000000000000 + // 0xF0000000 + CivilTimeEncoder.decodePacked64TimeMicros(0xF0000000L); + Assert.fail(); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void decodePacked64TimeMicros_invalidHourOfDay_throwsIllegalArgumentException() { + try { + // 24:00:00.000000 + // 0b000000000000000000000000000|11000|000000|000000|00000000000000000000 + // 0x1800000000 + CivilTimeEncoder.decodePacked64TimeMicros(0x1800000000L); + Assert.fail(); + } catch (IllegalArgumentException e) { + assertEquals("Invalid value for HourOfDay (valid values 0 - 23): 24", e.getMessage()); + } + } + + // Date Time + @Test + public void encodeAndDecodePacked64DatetimeMicros_validDateTime() { + // 0001/01/01 00:00:00 + // 0b0000000000000000000000|00000000000001|0001|00001|00000|000000|000000 + // 0x4420000 + assertEquals( + 0x442000000000L, + CivilTimeEncoder.encodePacked64DatetimeMicros(LocalDateTime.of(1, 1, 1, 0, 0, 0, 0))); + assertEquals( + LocalDateTime.of(1, 1, 1, 0, 0, 0, 0), + CivilTimeEncoder.decodePacked64DatetimeMicros(0x442000000000L)); + + // 0001/02/03 00:01:02 + // 0b0000000000000000000000|00000000000001|0010|00011|00000|000001|000010 + // 0x4860042 + assertEquals( + 0x486004200BB8L, + CivilTimeEncoder.encodePacked64DatetimeMicros( + LocalDateTime.of(1, 2, 3, 0, 1, 2, 3_000_000))); + assertEquals( + LocalDateTime.of(1, 2, 3, 0, 1, 2, 3_000_000), + CivilTimeEncoder.decodePacked64DatetimeMicros(0x486004200BB8L)); + + // 0001/01/01 12:00:00 + // 0b0000000000000000000000|00000000000001|0001|00001|01100|000000|000000 + // 0x442C000 + assertEquals( + 0x442C00000000L, + CivilTimeEncoder.encodePacked64DatetimeMicros(LocalDateTime.of(1, 1, 1, 12, 0, 0, 0))); + assertEquals( + LocalDateTime.of(1, 1, 1, 12, 0, 0, 0), + CivilTimeEncoder.decodePacked64DatetimeMicros(0x442C00000000L)); + + // 0001/01/01 13:14:15 + // 0b0000000000000000000000|00000000000001|0001|00001|01101|001110|001111 + // 0x442D38F + assertEquals( + 0x442D38F03E80L, + CivilTimeEncoder.encodePacked64DatetimeMicros( + LocalDateTime.of(1, 1, 1, 13, 14, 15, 16_000_000))); + assertEquals( + LocalDateTime.of(1, 1, 1, 13, 14, 15, 16_000_000), + CivilTimeEncoder.decodePacked64DatetimeMicros(0x442D38F03E80L)); + + // 9999/12/31 23:59:59 + // 0b0000000000000000000000|10011100001111|1100|11111|10111|111011|111011 + // 0x9C3F3F7EFB + assertEquals( + 0x9C3F3F7EFBF3E58L, + CivilTimeEncoder.encodePacked64DatetimeMicros( + LocalDateTime.of(9999, 12, 31, 23, 59, 59, 999_000_000))); + assertEquals( + LocalDateTime.of(9999, 12, 31, 23, 59, 59, 999_000_000), + CivilTimeEncoder.decodePacked64DatetimeMicros(0x9C3F3F7EFBF3E58L)); + } + + @Test + public void encodePacked64DateTimeMicros_giveErrorWhenPrecisionIsLost() { + // 0001/01/01 00:00:00.000000999 + // 0b0000000000000000000000|00000000000001|0001|00001|00000|000000|000000 + // 0x4420000 + try { + CivilTimeEncoder.encodePacked64DatetimeMicros(LocalDateTime.of(1, 1, 1, 0, 0, 0, 999)); + Assert.fail(); + } catch (IllegalArgumentException e) { + } + } + + @Test + public void encodePacked64DatetimeMicros_invalidYear_throwsIllegalArgumentException() { + // 10000/01/01 00:00:00.000000 + // 0b00|10011100010000|0001|00001|00000|000000|000000|00000000000000000000 + // 0x9C4042000000000 + LocalDateTime dateTime = LocalDateTime.of(10000, 1, 1, 0, 0, 0, 0); + try { + CivilTimeEncoder.encodePacked64DatetimeMicros(dateTime); + Assert.fail(); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void decodePacked64DatetimeMicros_validBitFieldDatetimeMicros() {} + + @Test + public void decodePacked64DatetimeMicros_invalidBitField() { + try { + // 0001/01/01 00:00:00 + // 0b0000000000000000000001|00000000000001|0001|00001|00000|000000|000000 + // 0x10004420000 + CivilTimeEncoder.decodePacked64DatetimeMicros(0x10004420000L); + Assert.fail(); + } catch (IllegalArgumentException e) { + } + } + + @Test + public void decodePacked64DatetimeMicros_invalidMicroOfSecond_throwsIllegalArgumentException() { + try { + // 0001/01/01 00:00:00.1000000 + // 0b00|00000000000001|0001|00001|00000|000000|000000|11110100001001000000 + // 0x4420000F4240 + CivilTimeEncoder.decodePacked64DatetimeMicros(0x4420000F4240L); + Assert.fail(); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void decodePacked64DatetimeMicros_invalidSecondOfMinute_throwsIllegalArgumentException() { + try { + // 0001/01/01 00:00:60.000000 + // 0b00|00000000000001|0001|00001|00000|000000|111100|00000000000000000000 + // 0x442003C00000 + CivilTimeEncoder.decodePacked64DatetimeMicros(0x442003C00000L); + Assert.fail(); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void decodePacked64DatetimeMicros_invalidMinuteOfHour_throwsIllegalArgumentException() { + try { + // 0001/01/01 00:60:00.000000 + // 0b00|00000000000001|0001|00001|00000|111100|000000|00000000000000000000 + // 0x4420F0000000 + CivilTimeEncoder.decodePacked64DatetimeMicros(0x4420F0000000L); + Assert.fail(); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void decodePacked64DatetimeMicros_invalidHourOfDay_throwsIllegalArgumentException() { + try { + // 0001/01/01 24:00:00.000000 + // 0b00|00000000000001|0001|00001|11000|000000|000000|00000000000000000000 + // 0x443800000000 + CivilTimeEncoder.decodePacked64DatetimeMicros(0x443800000000L); + Assert.fail(); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void decodePacked64DatetimeMicros_invalidDayOfMonth_throwsIllegalArgumentException() { + try { + // 0001/01/00 00:00:00.000000 + // 0b00|00000000000001|0001|00000|00000|000000|000000|00000000000000000000 + // 0x440000000000 + CivilTimeEncoder.decodePacked64DatetimeMicros(0x440000000000L); + Assert.fail(); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void decodePacked64DatetimeMicros_invalidMonthOfYear_throwsIllegalArgumentException() { + try { + // 0001/13/01 00:00:00.000000 + // 0b00|00000000000001|1101|00001|00000|000000|000000|00000000000000000000 + // 0x742000000000 + CivilTimeEncoder.decodePacked64DatetimeMicros(0x742000000000L); + Assert.fail(); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void decodePacked64DatetimeMicros_invalidYear_throwsIllegalArgumentException() { + try { + // 10000/01/01 00:00:00.000000 + // 0b00|10011100010000|0001|00001|00000|000000|000000|00000000000000000000 + // 0x9C4042000000000 + CivilTimeEncoder.decodePacked64DatetimeMicros(0x9C4042000000000L); + Assert.fail(); + } catch (IllegalArgumentException expected) { + } + } +} From 3835c8083b912a13d4ff4d7d08adca5e98c6ae99 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot
This is to be used to managed streaming write when you are working with PENDING streams or - * want to explicitly manage offset. In that most common cases when writing with COMMITTED stream - * without offset, please use a simpler writer {@code DirectWriter}. + * This is to be used to managed streaming write when you are working with PENDING streams or want + * to explicitly manage offset. In that most common cases when writing with COMMITTED stream without + * offset, please use a simpler writer {@code DirectWriter}. * *
A {@link StreamWrier} provides built-in capabilities to: handle batching of messages; * controlling memory utilization (through flow control) and request cleanup (only keeps write @@ -80,7 +78,10 @@ * *
{@link StreamWriter} will use the credentials set on the channel, which uses application
* default credentials through {@link GoogleCredentials#getApplicationDefault} by default.
+ *
+ * @deprecated use {@link #StreamWriterV2()} instead.
*/
+@Deprecated
public class StreamWriter implements AutoCloseable {
private static final Logger LOG = Logger.getLogger(StreamWriter.class.getName());
From 4442583af775513d00cc22d632af18d983309e35 Mon Sep 17 00:00:00 2001
From: JacobStocklass <35313153+JacobStocklass@users.noreply.github.com>
Date: Wed, 24 Mar 2021 23:45:24 +0000
Subject: [PATCH 12/15] test: E2E test for time encoding (#941)
* Place Holder Stress Test for Setup
* Making a basic long running test for the Write API
* Simple stress test placeholder in folder st.
* Add simple time caclulation
* Cleaning up before submitting pull
* caching changes
* Cleaning up and adding TODO
* Added copywrite info at beginning of file
* Removing error causing lines
* Moving Before class into single test to fix permissions issues
* Ran mvn format, should fix lint errors
* Resolving comments, removing unneccsary code
* Fixing comments and cleaning up
* Moved creation of client back into BeforeClass and resolved some other comments
* Formating fix
* Changed name from ST to IT to fix errors
* Formatting
* Aggregating data and logging once
* Refactoring down to only the simple case. Complex case will be handled in a different PR
* Quick rename
* Adding complex schema default stream test
* Formatting
* Adding Time Encoding Integration Test Placeholder
* Removing Stress test from this branch and moving it to the appropriate branch
* Add integration test to make sure that encoding and decoding across a table insertion holds up
* Added Integration test, renamed functions and got rid of redundant functions
* Fix License Header
* Java Lang set to 8 in order to use Java Local Time
* Removing nano functions, cleaning up comments
* Added round trip test to unit tests
* Moving to threeten time instead of java time
* Removing Java Time Dependency
* Lint
* Adding Time Encoding Integration Test Placeholder
* Removing Stress test from this branch and moving it to the appropriate branch
* Add integration test to make sure that encoding and decoding across a table insertion holds up
* Added Integration test, renamed functions and got rid of redundant functions
* Fix License Header
* Java Lang set to 8 in order to use Java Local Time
* Removing nano functions, cleaning up comments
* Added round trip test to unit tests
* Moving to threeten time instead of java time
* Removing Java Time Dependency
* Lint
* Remove E2E test for another PR. Split Unit tests into better named tests
* Lint
* Combining Encode and Decode Test for easier reading
* Removing unused methods
* Adding Time Encoding Integration Test Placeholder
* Removing Stress test from this branch and moving it to the appropriate branch
* Add integration test to make sure that encoding and decoding across a table insertion holds up
* Added Integration test, renamed functions and got rid of redundant functions
* Fix License Header
* Java Lang set to 8 in order to use Java Local Time
* Removing nano functions, cleaning up comments
* Added round trip test to unit tests
* Moving to threeten time instead of java time
* Removing Java Time Dependency
* Lint
* Remove E2E test for another PR. Split Unit tests into better named tests
* Lint
* Combining Encode and Decode Test for easier reading
* Removing unused methods
* E2E test for time encoding with supporting change to BQTableSchemaToProtoDescriptor
* Remove INT64 fields and make Time fields repeated
* Lint
* Dealing with errors in BQTableSchemaToProtoDescriptorTest
* Fixing testing to accept new Time format as integer.
* deps: update dependency com.google.cloud:google-cloud-bigquery to v1.127.10 (#955)
* chore: regenerate README (#950)
This PR was generated using Autosynth. :rainbow:
Log from Synthtool
```
2021-03-18 22:45:20,095 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-bigquerystorage/.github/readme/synth.py.
On branch autosynth-readme
nothing to commit, working tree clean
2021-03-18 22:45:21,018 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata.
```
Log from Synthtool
```
2021-03-22 15:32:14,816 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-bigquerystorage/.github/readme/synth.py.
On branch autosynth-readme
nothing to commit, working tree clean
2021-03-22 15:32:15,852 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata.
```
Log from Synthtool
```
2021-03-24 23:45:28,083 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-bigquerystorage/.github/readme/synth.py.
On branch autosynth-readme
nothing to commit, working tree clean
2021-03-24 23:45:29,183 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata.
```