public final class

DateTimeWithZone

extends java.lang.Object

 java.lang.Object

↳androidx.car.app.model.DateTimeWithZone

Gradle dependencies

compile group: 'androidx.car.app', name: 'app', version: '1.2.0-rc01'

  • groupId: androidx.car.app
  • artifactId: app
  • version: 1.2.0-rc01

Artifact androidx.car.app:app:1.2.0-rc01 it located at Google repository (https://maven.google.com/)

Overview

A time with an associated time zone information.

In order to avoid time zone databases being out of sync between the app and the host, this model avoids using IANA database time zone IDs and instead relies on the app passing the time zone offset and its abbreviated name. Apps can use their time library of choice to retrieve the time zone information.

DateTimeWithZone.create(long, TimeZone) and DateTimeWithZone.create(ZonedDateTime) are provided for convenience if using java.util and java.time respectively. If using another library such as Joda time, DateTimeWithZone.create(long, int, String) can be used.

Summary

Methods
public static DateTimeWithZonecreate(long timeSinceEpochMillis, int zoneOffsetSeconds, java.lang.String zoneShortName)

Returns an instance of a DateTimeWithZone.

public static DateTimeWithZonecreate(long timeSinceEpochMillis, java.util.TimeZone timeZone)

Returns an instance of a DateTimeWithZone.

public static DateTimeWithZonecreate(java.time.ZonedDateTime zonedDateTime)

Returns an instance of a DateTimeWithZone.

public booleanequals(java.lang.Object other)

public longgetTimeSinceEpochMillis()

Returns the number of milliseconds from the epoch of 1970-01-01T00:00:00Z.

public intgetZoneOffsetSeconds()

Returns the offset of the time zone from UTC.

public java.lang.StringgetZoneShortName()

Returns the abbreviated name of the time zone, for example "PST" for Pacific Standard Time.

public inthashCode()

public java.lang.StringtoString()

from java.lang.Objectclone, finalize, getClass, notify, notifyAll, wait, wait, wait

Methods

public long getTimeSinceEpochMillis()

Returns the number of milliseconds from the epoch of 1970-01-01T00:00:00Z.

public int getZoneOffsetSeconds()

Returns the offset of the time zone from UTC.

public java.lang.String getZoneShortName()

Returns the abbreviated name of the time zone, for example "PST" for Pacific Standard Time.

public java.lang.String toString()

public int hashCode()

public boolean equals(java.lang.Object other)

public static DateTimeWithZone create(long timeSinceEpochMillis, int zoneOffsetSeconds, java.lang.String zoneShortName)

Returns an instance of a DateTimeWithZone.

Parameters:

timeSinceEpochMillis: The number of milliseconds from the epoch of 1970-01-01T00:00:00Z
zoneOffsetSeconds: The offset of the time zone from UTC at the date specified by timeInUtcMillis. This offset must be in the range -18:00 to +18:00, which corresponds to -64800 to +64800
zoneShortName: The abbreviated name of the time zone, for example, "PST" for Pacific Standard Time. This string may be used to display to the user along with the date when needed, for example, if this time zone is different than the current system time zone

public static DateTimeWithZone create(long timeSinceEpochMillis, java.util.TimeZone timeZone)

Returns an instance of a DateTimeWithZone.

Parameters:

timeSinceEpochMillis: The number of milliseconds from the epoch of 1970-01-01T00:00:00Z
timeZone: The time zone at the date specified by timeInUtcMillis. The abbreviated name of this time zone, formatted using the default locale, may be displayed to the user when needed, for example, if this time zone is different than the current system time zone

public static DateTimeWithZone create(java.time.ZonedDateTime zonedDateTime)

Returns an instance of a DateTimeWithZone.

Parameters:

zonedDateTime: The time with a time zone. The abbreviated name of this time zone, formatted using the default locale, may be displayed to the user when needed, for example, if this time zone is different than the current system time zone

Source

/*
 * Copyright 2020 The Android Open Source Project
 *
 * 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 androidx.car.app.model;

import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;

import android.annotation.SuppressLint;

import androidx.annotation.DoNotInline;
import androidx.annotation.IntRange;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.car.app.annotations.CarProtocol;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.TextStyle;
import java.util.Date;
import java.util.Locale;
import java.util.Objects;
import java.util.TimeZone;

/**
 * A time with an associated time zone information.
 *
 * <p>In order to avoid time zone databases being out of sync between the app and the host, this
 * model avoids using <a href="https://www.iana.org/time-zones">IANA database</a> time zone IDs and
 * instead relies on the app passing the time zone offset and its abbreviated name. Apps can use
 * their time library of choice to retrieve the time zone information.
 *
 * <p>{@link #create(long, TimeZone)} and {@link #create(ZonedDateTime)} are provided for
 * convenience if using {@code java.util} and {@code java.time} respectively. If using another
 * library such as Joda time, {@link #create(long, int, String)} can be used.
 */
@SuppressWarnings("MissingSummary")
@CarProtocol
public final class DateTimeWithZone {
    /** The maximum allowed offset for a time zone, in seconds. */
    private static final long MAX_ZONE_OFFSET_SECONDS = 18 * HOURS.toSeconds(1);

    @Keep
    private final long mTimeSinceEpochMillis;
    @Keep
    private final int mZoneOffsetSeconds;
    @Nullable
    @Keep
    private final String mZoneShortName;

    /** Returns the number of milliseconds from the epoch of 1970-01-01T00:00:00Z. */
    public long getTimeSinceEpochMillis() {
        return mTimeSinceEpochMillis;
    }

    /** Returns the offset of the time zone from UTC. */
    @SuppressLint("MethodNameUnits")
    public int getZoneOffsetSeconds() {
        return mZoneOffsetSeconds;
    }

    /**
     * Returns the abbreviated name of the time zone, for example "PST" for Pacific Standard
     * Time.
     */
    @Nullable
    public String getZoneShortName() {
        return mZoneShortName;
    }

    @Override
    @NonNull
    public String toString() {
        return "[time since epoch (ms): " + mTimeSinceEpochMillis
                + "( " + new Date(mTimeSinceEpochMillis) + ") "
                + " zone offset (s): " + mZoneOffsetSeconds
                + ", zone: " + mZoneShortName + "]";
    }

    @Override
    public int hashCode() {
        return Objects.hash(mTimeSinceEpochMillis, mZoneOffsetSeconds, mZoneShortName);
    }

    @Override
    public boolean equals(@Nullable Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof DateTimeWithZone)) {
            return false;
        }
        DateTimeWithZone otherDateTime = (DateTimeWithZone) other;

        return mTimeSinceEpochMillis == otherDateTime.mTimeSinceEpochMillis
                && mZoneOffsetSeconds == otherDateTime.mZoneOffsetSeconds
                && Objects.equals(mZoneShortName, otherDateTime.mZoneShortName);
    }

    /**
     * Returns an instance of a {@link DateTimeWithZone}.
     *
     * @param timeSinceEpochMillis The number of milliseconds from the epoch of
     *                             1970-01-01T00:00:00Z
     * @param zoneOffsetSeconds    The offset of the time zone from UTC at the date specified by
     *                             {@code timeInUtcMillis}. This offset must be in the range
     *                             {@code -18:00} to {@code +18:00}, which corresponds to -64800
     *                             to +64800
     * @param zoneShortName        The abbreviated name of the time zone, for example, "PST" for
     *                             Pacific Standard Time. This string may be used to display to
     *                             the user along with the date when needed, for example, if this
     *                             time zone is different than the current system time zone
     * @throws IllegalArgumentException if {@code timeSinceEpochMillis} is a negative value, if
     *                                  {@code zoneOffsetSeconds} is not within the required range,
     *                                  or if {@code zoneShortName} is empty
     * @throws NullPointerException     if {@code zoneShortName} is {@code null}
     */
    @NonNull
    public static DateTimeWithZone create(
            long timeSinceEpochMillis, @IntRange(from = -64800, to = 64800) int zoneOffsetSeconds,
            @NonNull String zoneShortName) {
        if (timeSinceEpochMillis < 0) {
            throw new IllegalArgumentException(
                    "Time since epoch must be greater than or equal to zero");
        }
        if (Math.abs(zoneOffsetSeconds) > MAX_ZONE_OFFSET_SECONDS) {
            throw new IllegalArgumentException("Zone offset not in valid range: -18:00 to +18:00");
        }
        if (requireNonNull(zoneShortName).isEmpty()) {
            throw new IllegalArgumentException("The time zone short name can not be null or empty");
        }
        return new DateTimeWithZone(timeSinceEpochMillis, zoneOffsetSeconds, zoneShortName);
    }

    /**
     * Returns an instance of a {@link DateTimeWithZone}.
     *
     * @param timeSinceEpochMillis The number of milliseconds from the epoch of
     *                             1970-01-01T00:00:00Z
     * @param timeZone             The time zone at the date specified by {@code timeInUtcMillis}.
     *                             The abbreviated name of this time zone, formatted using the
     *                             default locale, may be displayed to the user when needed, for
     *                             example, if this time zone is different than the current
     *                             system time zone
     * @throws IllegalArgumentException if {@code timeSinceEpochMillis} is a negative value
     * @throws NullPointerException     if {@code timeZone} is {@code null}
     */
    @NonNull
    public static DateTimeWithZone create(long timeSinceEpochMillis, @NonNull TimeZone timeZone) {
        if (timeSinceEpochMillis < 0) {
            throw new IllegalArgumentException(
                    "timeSinceEpochMillis must be greater than or equal to zero");
        }
        return create(
                timeSinceEpochMillis,
                (int) MILLISECONDS.toSeconds(
                        requireNonNull(timeZone).getOffset(timeSinceEpochMillis)),
                timeZone.getDisplayName(false, TimeZone.SHORT));
    }

    /**
     * Returns an instance of a {@link DateTimeWithZone}.
     *
     * @param zonedDateTime The time with a time zone. The abbreviated name of this time zone,
     *                      formatted using the default locale, may be displayed to the user when
     *                      needed, for example, if this time zone is different than the current
     *                      system time zone
     * @throws NullPointerException if {@code zonedDateTime} is {@code null}
     */
    @RequiresApi(26)
    @NonNull
    public static DateTimeWithZone create(@NonNull ZonedDateTime zonedDateTime) {
        return Api26Impl.create(zonedDateTime);
    }

    private DateTimeWithZone() {
        mTimeSinceEpochMillis = 0;
        mZoneOffsetSeconds = 0;
        mZoneShortName = null;
    }

    private DateTimeWithZone(
            long timeSinceEpochMillis, int zoneOffsetSeconds, @Nullable String timeZoneShortName) {
        mTimeSinceEpochMillis = timeSinceEpochMillis;
        mZoneOffsetSeconds = zoneOffsetSeconds;
        mZoneShortName = timeZoneShortName;
    }

    /**
     * Version-specific static inner class to avoid verification errors that negatively affect
     * run-time performance.
     */
    @RequiresApi(26)
    private static final class Api26Impl {
        private Api26Impl() {
        }

        @DoNotInline
        @NonNull
        public static DateTimeWithZone create(@NonNull ZonedDateTime zonedDateTime) {
            LocalDateTime localDateTime = requireNonNull(zonedDateTime).toLocalDateTime();
            ZoneId zoneId = zonedDateTime.getZone();
            ZoneOffset zoneOffset = zoneId.getRules().getOffset(localDateTime);
            return DateTimeWithZone.create(
                    SECONDS.toMillis(localDateTime.toEpochSecond(zoneOffset)),
                    zoneOffset.getTotalSeconds(),
                    zoneId.getDisplayName(TextStyle.SHORT, Locale.getDefault()));
        }
    }
}