/** * Serialize ISOChronology instances using a small stub. This reduces the * serialized size, and deserialized instances come from the cache. */ private Object writeReplace() { return new Stub(getZone()); }
/** * A suitable hash code for the chronology. * * @return the hash code * @since 1.6 */ public int hashCode() { return "ISO".hashCode() * 11 + getZone().hashCode(); }
/** * A suitable hash code for the chronology. * * @return the hash code * @since 1.6 */ public int hashCode() { return "ISO".hashCode() * 11 + getZone().hashCode(); }
/** * Gets a debugging toString. * * @return a debugging string */ public String toString() { String str = "ISOChronology"; DateTimeZone zone = getZone(); if (zone != null) { str = str + '[' + zone.getID() + ']'; } return str; }
/** * Serialize ISOChronology instances using a small stub. This reduces the * serialized size, and deserialized instances come from the cache. */ private Object writeReplace() { return new Stub(getZone()); }
/** * Gets a debugging toString. * * @return a debugging string */ public String toString() { String str = "ISOChronology"; DateTimeZone zone = getZone(); if (zone != null) { str = str + '[' + zone.getID() + ']'; } return str; }
public static ReadMapping dateReadMapping() { return longReadMapping(DATE, (resultSet, columnIndex) -> { /* * JDBC returns a date using a timestamp at midnight in the JVM timezone, or earliest time after that if there was no midnight. * This works correctly for all dates and zones except when the missing local times 'gap' is 24h. I.e. this fails when JVM time * zone is Pacific/Apia and date to be returned is 2011-12-30. * * `return resultSet.getObject(columnIndex, LocalDate.class).toEpochDay()` avoids these problems but * is currently known not to work with Redshift (old Postgres connector) and SQL Server. */ long localMillis = resultSet.getDate(columnIndex).getTime(); // Convert it to a ~midnight in UTC. long utcMillis = ISOChronology.getInstance().getZone().getMillisKeepLocal(UTC, localMillis); // convert to days return MILLISECONDS.toDays(utcMillis); }); }
/** * Gets the Chronology in a specific time zone. * * @param zone the zone to get the chronology in, null is default * @return the chronology */ public Chronology withZone(DateTimeZone zone) { if (zone == null) { zone = DateTimeZone.getDefault(); } if (zone == getZone()) { return this; } return getInstance(zone); }
public static int modulo24Hour(ISOChronology chronology, long millis) { return chronology.millisOfDay().get(millis) - chronology.getZone().getOffset(millis); }
@ScalarOperator(CAST) @SqlType(StandardTypes.TIMESTAMP) public static long castToTimestamp(ConnectorSession session, @SqlType(StandardTypes.DATE) long value) { if (session.isLegacyTimestamp()) { long utcMillis = TimeUnit.DAYS.toMillis(value); // date is encoded as milliseconds at midnight in UTC // convert to midnight in the session timezone ISOChronology chronology = getChronology(session.getTimeZoneKey()); return utcMillis - chronology.getZone().getOffset(utcMillis); } else { return TimeUnit.DAYS.toMillis(value); } }
@ScalarOperator(CAST) @SqlType(StandardTypes.TIMESTAMP_WITH_TIME_ZONE) public static long castToTimestampWithTimeZone(ConnectorSession session, @SqlType(StandardTypes.DATE) long value) { long utcMillis = TimeUnit.DAYS.toMillis(value); // date is encoded as milliseconds at midnight in UTC // convert to midnight in the session timezone ISOChronology chronology = getChronology(session.getTimeZoneKey()); long millis = utcMillis - chronology.getZone().getOffset(utcMillis); return packDateTimeWithZone(millis, session.getTimeZoneKey()); }
@ScalarFunction("date") @ScalarOperator(CAST) @SqlType(StandardTypes.DATE) public static long castToDate(@SqlType(StandardTypes.TIMESTAMP_WITH_TIME_ZONE) long value) { // round down the current timestamp to days ISOChronology chronology = unpackChronology(value); long date = chronology.dayOfYear().roundFloor(unpackMillisUtc(value)); // date is currently midnight in timezone of the original value // convert to UTC long millis = date + chronology.getZone().getOffset(date); return TimeUnit.MILLISECONDS.toDays(millis); }
@ScalarOperator(CAST) @SqlType(StandardTypes.TIMESTAMP) public static long castToTimestamp(ConnectorSession session, @SqlType(StandardTypes.TIME_WITH_TIME_ZONE) long value) { if (session.isLegacyTimestamp()) { return unpackMillisUtc(value); } else { // This is hack that we need to use as the timezone interpretation depends on date (not only on time) // TODO remove REFERENCE_TIMESTAMP_UTC when removing support for political time zones in TIME WIT TIME ZONE long currentMillisOfDay = ChronoField.MILLI_OF_DAY.getFrom(Instant.ofEpochMilli(REFERENCE_TIMESTAMP_UTC).atZone(ZoneOffset.UTC)); long timeMillisUtcInCurrentDay = REFERENCE_TIMESTAMP_UTC - currentMillisOfDay + unpackMillisUtc(value); ISOChronology chronology = getChronology(unpackZoneKey(value)); return unpackMillisUtc(value) + chronology.getZone().getOffset(timeMillisUtcInCurrentDay); } }
@ScalarFunction("date") @ScalarOperator(CAST) @SqlType(StandardTypes.DATE) public static long castToDate(ConnectorSession session, @SqlType(StandardTypes.TIMESTAMP) long value) { ISOChronology chronology; if (session.isLegacyTimestamp()) { // round down the current timestamp to days chronology = getChronology(session.getTimeZoneKey()); long date = chronology.dayOfYear().roundFloor(value); // date is currently midnight in timezone of the session // convert to UTC long millis = date + chronology.getZone().getOffset(date); return TimeUnit.MILLISECONDS.toDays(millis); } else { return TimeUnit.MILLISECONDS.toDays(value); } }
@ScalarOperator(CAST) @SqlType(StandardTypes.TIMESTAMP) public static long castToTimestamp(ConnectorSession session, @SqlType(StandardTypes.TIMESTAMP_WITH_TIME_ZONE) long value) { if (session.isLegacyTimestamp()) { return unpackMillisUtc(value); } else { ISOChronology chronology = getChronology(unpackZoneKey(value)); return chronology.getZone().convertUTCToLocal(unpackMillisUtc(value)); } }
@Description("current timestamp without time zone") @ScalarFunction("localtimestamp") @SqlType(StandardTypes.TIMESTAMP) public static long localTimestamp(ConnectorSession session) { if (session.isLegacyTimestamp()) { return session.getStartTime(); } ISOChronology localChronology = getChronology(session.getTimeZoneKey()); return localChronology.getZone().convertUTCToLocal(session.getStartTime()); }
@ScalarOperator(CAST) @SqlType(StandardTypes.TIMESTAMP_WITH_TIME_ZONE) public static long castToTimestampWithTimeZone(ConnectorSession session, @SqlType(StandardTypes.TIMESTAMP) long value) { if (session.isLegacyTimestamp()) { return packDateTimeWithZone(value, session.getTimeZoneKey()); } else { ISOChronology localChronology = getChronology(session.getTimeZoneKey()); // This cast does treat TIMESTAMP as wall time in session TZ. This means that in order to get // its UTC representation we need to shift the value by the offset of TZ. return packDateTimeWithZone(localChronology.getZone().convertLocalToUTC(value, false), session.getTimeZoneKey()); } }
@ScalarOperator(CAST) @SqlType(StandardTypes.TIME_WITH_TIME_ZONE) public static long castToTimeWithTimeZone(ConnectorSession session, @SqlType(StandardTypes.TIME) long value) { if (session.isLegacyTimestamp()) { return packDateTimeWithZone(value, session.getTimeZoneKey()); } else { ISOChronology localChronology = getChronology(session.getTimeZoneKey()); // This cast does treat TIME as wall time in session TZ. This means that in order to get // its UTC representation we need to shift the value by the offset of TZ. // We use value offset in this place to be sure that we will have same hour represented // in TIME WITH TIME ZONE. Calculating real TZ offset will happen when really required. // This is done due to inadequate TIME WITH TIME ZONE representation. return packDateTimeWithZone(localChronology.getZone().convertLocalToUTC(value, false), session.getTimeZoneKey()); } }
@ScalarOperator(CAST) @SqlType(StandardTypes.TIME_WITH_TIME_ZONE) public static long castToTimeWithTimeZone(ConnectorSession session, @SqlType(StandardTypes.TIMESTAMP) long value) { if (session.isLegacyTimestamp()) { int timeMillis = modulo24Hour(getChronology(session.getTimeZoneKey()), value); return packDateTimeWithZone(timeMillis, session.getTimeZoneKey()); } else { ISOChronology localChronology = getChronology(session.getTimeZoneKey()); // This cast does treat TIMESTAMP as wall time in session TZ. This means that in order to get // its UTC representation we need to shift the value by the offset of TZ. return packDateTimeWithZone(localChronology.getZone().convertLocalToUTC(modulo24Hour(value), false), session.getTimeZoneKey()); } }
@ScalarOperator(CAST) @SqlType(StandardTypes.TIME_WITH_TIME_ZONE) public static long castToTimeWithTimeZone(ConnectorSession session, @SqlType(StandardTypes.TIMESTAMP_WITH_TIME_ZONE) long value) { if (session.isLegacyTimestamp()) { int millis = modulo24Hour(unpackChronology(value), unpackMillisUtc(value)); return packDateTimeWithZone(millis, unpackZoneKey(value)); } else { long millis = modulo24Hour(castToTimestamp(session, value)); ISOChronology localChronology = unpackChronology(value); // This cast does treat TIME as wall time in given TZ. This means that in order to get // its UTC representation we need to shift the value by the offset of TZ. // We use value offset in this place to be sure that we will have same hour represented // in TIME WITH TIME ZONE. Calculating real TZ offset will happen when really required. // This is done due to inadequate TIME WITH TIME ZONE representation. return packDateTimeWithZone(millis - localChronology.getZone().getOffset(millis), unpackZoneKey(value)); } }