All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.time4j.ZonalDateTime Maven / Gradle / Ivy

There is a newer version: 4.38
Show newest version
/*
 * -----------------------------------------------------------------------
 * Copyright © 2013-2015 Meno Hochschild, 
 * -----------------------------------------------------------------------
 * This file (ZonalDateTime.java) is part of project Time4J.
 *
 * Time4J is free software: You can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Time4J is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Time4J. If not, see .
 * -----------------------------------------------------------------------
 */

package net.time4j;

import net.time4j.engine.ChronoDisplay;
import net.time4j.engine.ChronoElement;
import net.time4j.format.RawValues;
import net.time4j.format.TemporalFormatter;
import net.time4j.scale.TimeScale;
import net.time4j.scale.UniversalTime;
import net.time4j.tz.TZID;
import net.time4j.tz.Timezone;
import net.time4j.tz.ZonalOffset;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.text.ParseException;
import java.text.ParsePosition;

import static net.time4j.PlainTime.SECOND_OF_MINUTE;
import static net.time4j.format.Attributes.TIMEZONE_ID;


/**
 * 

Combination of UTC-moment and timezone.

* *

An instance can be created by {@code Moment.inLocalView()} or * {@code Moment.inZonalView(...)}. This type mainly serves for various * type conversions and incorporates a valid local timestamp as well as an * universal time in UTC. If users wish to apply any kind of data * manipulation then an object of this type has first to be converted * to a local timestamp or to a global UTC-moment. Example:

* *
 *  Moment moment = ...;
 *  ZonalDateTime zdt = moment.inLocalView();
 *
 *  // manipulation on local timeline
 *  PlainTimestamp localTSP = zdt.toTimestamp().plus(30, ClockUnit.SECONDS);
 *
 *  // manipulation on global timeline
 *  Moment globalTSP = zdt.toMoment().plus(30, SI.SECONDS);
 * 
* * @author Meno Hochschild * @since 2.0 * @doctags.concurrency This class is immutable as long as the underlying timezone * data are immutable. * @see Moment#inLocalView() * @see Moment#inZonalView(TZID) * @see Moment#inZonalView(String) */ /*[deutsch] *

Kombination aus UTC-Moment und Zeitzone.

* *

Eine Instanz kann mit Hilfe von {@code Moment.inLocalView()} oder * {@code Moment.inZonalView(...)} erzeugt werden. Dieser Typ dient vorwiegend * der Typkonversion und verkörpert sowohl einen gültigen lokalen * Zeitstempel als auch eine Universalzeit in UTC. Wenn Anwender irgendeine * Art von Datenmanipulation anwenden möchten, dann muß ein * Objekt dieses Typs zuerst in einen lokalen Zeitstempel oder einen * globalen UTC-Moment umgewandelt werden. Beispiel:

* *
 *  Moment moment = ...;
 *  ZonalDateTime zdt = moment.inLocalView();
 *
 *  // manipulation on local timeline
 *  PlainTimestamp localTSP = zdt.toTimestamp().plus(30, ClockUnit.SECONDS);
 *
 *  // manipulation on global timeline
 *  Moment globalTSP = zdt.toMoment().plus(30, SI.SECONDS);
 * 
* * @author Meno Hochschild * @since 2.0 * @doctags.concurrency This class is immutable as long as the underlying timezone * data are immutable. * @see Moment#inLocalView() * @see Moment#inZonalView(TZID) * @see Moment#inZonalView(String) */ public final class ZonalDateTime implements ChronoDisplay, UniversalTime { //~ Instanzvariablen -------------------------------------------------- private final Moment moment; private final Timezone zone; private transient final PlainTimestamp timestamp; //~ Konstruktoren ----------------------------------------------------- private ZonalDateTime( Moment moment, Timezone tz ) { super(); this.zone = tz; ZonalOffset offset = tz.getOffset(moment); if (moment.isLeapSecond()) { if ( (offset.getFractionalAmount() != 0) || ((offset.getAbsoluteSeconds() % 60) != 0) ) { throw new IllegalArgumentException( "Leap second can only be represented " + " with timezone-offset in full minutes: " + offset); } } this.moment = moment; this.timestamp = PlainTimestamp.from(moment, offset); } private ZonalDateTime( PlainTimestamp tsp, ZonalOffset offset ) { super(); this.moment = tsp.at(offset); this.zone = Timezone.of(offset); this.timestamp = tsp; } //~ Methoden ---------------------------------------------------------- /** *

Erzeugt einen zonalen Moment.

* * @param moment global timestamp * @param tz timezone * @return ZonalDateTime * @throws IllegalArgumentException if leapsecond shall be formatted * with non-full-minute-timezone-offset */ static ZonalDateTime of( Moment moment, Timezone tz ) { return new ZonalDateTime(moment, tz); } /** *

Erzeugt einen zonalen Moment.

* * @param tsp zonal timestamp * @param offset timezone offset * @return ZonalDateTime */ static ZonalDateTime of( PlainTimestamp tsp, ZonalOffset offset ) { return new ZonalDateTime(tsp, offset); } @Override public boolean contains(ChronoElement element) { return ( this.timestamp.contains(element) || this.moment.contains(element) ); } @Override public V get(ChronoElement element) { if ( this.moment.isLeapSecond() && (element == SECOND_OF_MINUTE) ) { return element.getType().cast(Integer.valueOf(60)); } if (this.timestamp.contains(element)) { return this.timestamp.get(element); } else { return this.moment.get(element); } } // benutzt in ChronoFormatter/FractionProcessor @Override public V getMinimum(ChronoElement element) { if (this.timestamp.contains(element)) { return this.timestamp.getMinimum(element); } else { return this.moment.getMinimum(element); } } // benutzt in ChronoFormatter/FractionProcessor @Override public V getMaximum(ChronoElement element) { V max; if (this.timestamp.contains(element)) { max = this.timestamp.getMaximum(element); } else { max = this.moment.getMaximum(element); } if ( (element == SECOND_OF_MINUTE) && (this.timestamp.getYear() >= 1972) ) { PlainTimestamp ts = this.timestamp.with(element, max); if (!this.zone.isInvalid(ts, ts)) { Moment transformed = ts.in(this.zone); Moment test = transformed.plus(1, SI.SECONDS); if (test.isLeapSecond()) { return element.getType().cast(Integer.valueOf(60)); } } } return max; } /** *

This object always has a timezone.

* * @return {@code true} */ /*[deutsch] *

Dieses Objekt hat immer eine Zeitzone.

* * @return {@code true} */ @Override public boolean hasTimezone() { return true; } @Override public TZID getTimezone() { return this.zone.getID(); } /** *

Yields the timezone offset.

* * @return offset relative to UTC+00:00 * @since 2.0 */ /*[deutsch] *

Liefert den Zeitzonen-Offset.

* * @return offset relative to UTC+00:00 * @since 2.0 */ public ZonalOffset getOffset() { return this.zone.getOffset(this.moment); } /** *

Converts this object to a global UTC-moment.

* * @return Moment */ /*[deutsch] *

Konvertiert dieses Objekt zu einem globalen UTC-Moment.

* * @return Moment */ public Moment toMoment() { return this.moment; } /** *

Converts this object to a zonal timestamp.

* * @return PlainTimestamp */ /*[deutsch] *

Konvertiert dieses Objekt zu einem zonalen Zeitstempel.

* * @return PlainTimestamp */ public PlainTimestamp toTimestamp() { return this.timestamp; } @Override public long getElapsedTime(TimeScale scale) { return this.moment.getElapsedTime(scale); } @Override public int getNanosecond(TimeScale scale) { return this.moment.getNanosecond(scale); } @Override public boolean isLeapSecond() { return this.moment.isLeapSecond(); } @Override public long getPosixTime() { return this.moment.getPosixTime(); } @Override public int getNanosecond() { return this.moment.getNanosecond(); } /** *

Creates a formatted output of this instance.

* * @param printer helps to format this instance * @return formatted string * @since 3.0 */ /*[deutsch] *

Erzeugt eine formatierte Ausgabe dieser Instanz.

* * @param printer helps to format this instance * @return formatted string * @since 3.0 */ public String print(TemporalFormatter printer) { return printer.withTimezone(this.getTimezone()).format(this.moment); } /** *

Parses given text to a {@code ZonalDateTime}.

* * @param text text to be parsed * @param parser helps to parse given text * @return parsed zonal moment * @throws IndexOutOfBoundsException if the text is empty * @throws ParseException if the text is not parseable * @since 3.0 */ /*[deutsch] *

Interpretiert den angegebenen Text als {@code ZonalDateTime}.

* * @param text text to be parsed * @param parser helps to parse given text * @return parsed zonal moment * @throws IndexOutOfBoundsException if the text is empty * @throws ParseException if the text is not parseable * @since 3.0 */ public static ZonalDateTime parse( String text, TemporalFormatter parser ) throws ParseException { ParsePosition pos = new ParsePosition(0); RawValues rawValues = new RawValues(); Moment moment = parser.parse(text, pos, rawValues); Timezone tz; if (moment == null) { throw new ParseException("Cannot parse: " + text, pos.getErrorIndex()); } else if (rawValues.get().hasTimezone()) { tz = toTimezone(rawValues.get().getTimezone(), text); } else if (parser.getAttributes().contains(TIMEZONE_ID)) { tz = toTimezone(parser.getAttributes().get(TIMEZONE_ID), text); } else { throw new ParseException("Missing timezone: " + text, 0); } return ZonalDateTime.of(moment, tz); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } else if (obj instanceof ZonalDateTime) { ZonalDateTime that = (ZonalDateTime) obj; return ( this.moment.equals(that.moment) && this.zone.equals(that.zone) ); } else { return false; } } @Override public int hashCode() { return (this.moment.hashCode() ^ this.zone.hashCode()); } /** *

Yields a canonical representation in ISO-like-style.

* * @return String */ /*[deutsch] *

Liefert eine kanonische Darstellung ähnlich zu ISO-8601.

* * @return String */ @Override public String toString() { StringBuilder sb = new StringBuilder(40); sb.append(this.timestamp); sb.append(this.getOffset().canonical()); TZID tzid = this.getTimezone(); boolean offset = (tzid instanceof ZonalOffset); if (!offset) { sb.append('['); sb.append(tzid.canonical()); sb.append(']'); } return sb.toString(); } /** *

Writes this instance to given output (serialization).

* *

Warning: Serializing this instance is a heavy-weight-operation because the * whole relevant timezone data will be written to given stream, not only the timezone-id.

* * @param output object output * @throws IOException if writing fails * @since 3.1 */ /*[deutsch] *

Schreibt diese Instanz in den angegebenen Ausgabestrom (Serialisierung).

* *

Warnung: Die Serialisierung dieser Instanz ist schwergewichtig, weil alle * relevanten Zeitzonendaten komplett geschrieben werden, nicht nur die Zeitzonen-ID.

* * @param output object output * @throws IOException if writing fails * @since 3.1 */ public void write(ObjectOutput output) throws IOException { output.writeObject(this.moment); output.writeObject(this.zone); } /** *

This is the reverse operation of {@link #write(ObjectOutput)}.

* * @param input object input * @return reconstructed instance of serialized {@code ZonalDateTime} * @throws IOException if reading fails * @throws ClassNotFoundException if class-loading fails * @throws IllegalArgumentException in case of inconsistent data * @since 3.1 */ /*[deutsch] *

Das ist die Umkehroperation zu {@link #write(ObjectOutput)}.

* * @param input object input * @return reconstructed instance of serialized {@code ZonalDateTime} * @throws IOException if reading fails * @throws ClassNotFoundException if class-loading fails * @throws IllegalArgumentException in case of inconsistent data * @since 3.1 */ public static ZonalDateTime read(ObjectInput input) throws IOException, ClassNotFoundException { Moment moment = (Moment) input.readObject(); Timezone tz = (Timezone) input.readObject(); return new ZonalDateTime(moment, tz); } private static Timezone toTimezone( TZID tzid, String text ) throws ParseException { try { return Timezone.of(tzid); } catch (IllegalArgumentException iae) { ParseException pe = new ParseException("Timezone error: " + text, 0); pe.initCause(iae); throw pe; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy