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

net.time4j.format.LocalizedGMTProcessor Maven / Gradle / Ivy

There is a newer version: 4.38
Show newest version
/*
 * -----------------------------------------------------------------------
 * Copyright © 2013-2014 Meno Hochschild, 
 * -----------------------------------------------------------------------
 * This file (LocalizedGMTProcessor.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.format;

import net.time4j.base.UnixTime;
import net.time4j.engine.AttributeQuery;
import net.time4j.engine.ChronoDisplay;
import net.time4j.engine.ChronoElement;
import net.time4j.tz.OffsetSign;
import net.time4j.tz.TZID;
import net.time4j.tz.Timezone;
import net.time4j.tz.ZonalOffset;

import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import static net.time4j.tz.OffsetSign.AHEAD_OF_UTC;
import static net.time4j.tz.OffsetSign.BEHIND_UTC;


/**
 * 

Verarbeitet einen lokalisierten Zeitzonen-Offset.

* * @author Meno Hochschild */ final class LocalizedGMTProcessor implements FormatProcessor { //~ Statische Felder/Initialisierungen -------------------------------- private static final char UNICODE_LRM = '\u200E'; //~ Instanzvariablen -------------------------------------------------- private final boolean abbreviated; //~ Konstruktoren ----------------------------------------------------- /** *

Erzeugt eine neue Instanz.

* * @param abbreviated short form of localized gmt offset? */ LocalizedGMTProcessor(boolean abbreviated) { super(); this.abbreviated = abbreviated; } //~ Methoden ---------------------------------------------------------- @Override public void print( ChronoDisplay formattable, Appendable buffer, AttributeQuery attributes, Set positions, FormatStep step ) throws IOException { int start = -1; int printed = 0; if (buffer instanceof CharSequence) { start = ((CharSequence) buffer).length(); } TZID tzid = null; ZonalOffset offset; if (formattable.hasTimezone()) { tzid = formattable.getTimezone(); } if (tzid == null) { offset = getOffset(formattable, step, attributes); } else if (tzid instanceof ZonalOffset) { offset = (ZonalOffset) tzid; } else if (formattable instanceof UnixTime) { offset = Timezone.of(tzid).getOffset((UnixTime) formattable); } else { throw new IllegalArgumentException( "Cannot extract timezone offset from: " + formattable); } Locale locale = step.getAttribute(Attributes.LOCALE, attributes, Locale.ROOT); String gmtPrefix = CalendarText.getGMTPrefix(locale); buffer.append(gmtPrefix); printed = gmtPrefix.length(); int total = offset.getIntegralAmount(); int fraction = offset.getFractionalAmount(); if ((total != 0) || (fraction != 0)) { // hack for arabic locales: LRM-marker for following sign required if ("ar".equals(locale.getLanguage())) { buffer.append(UNICODE_LRM); printed++; } buffer.append((offset.getSign() == BEHIND_UTC) ? '-' : '+'); printed++; int h = offset.getAbsoluteHours(); int m = offset.getAbsoluteMinutes(); if ((h < 10) && !this.abbreviated) { buffer.append('0'); printed++; } String hours = String.valueOf(h); for (int i = 0; i < hours.length(); i++) { buffer.append(hours.charAt(i)); printed++; } if ((m != 0) || !this.abbreviated) { buffer.append(':'); printed++; if (m < 10) { buffer.append('0'); printed++; } String minutes = String.valueOf(m); for (int i = 0; i < minutes.length(); i++) { buffer.append(minutes.charAt(i)); printed++; } } } if ( (start != -1) && (printed > 0) && (positions != null) ) { positions.add( new ElementPosition( TimezoneElement.TIMEZONE_ID, start, start + printed)); } } @Override public void parse( CharSequence text, ParseLog status, AttributeQuery attributes, Map, Object> parsedResult, FormatStep step ) { int len = text.length(); int start = status.getPosition(); int pos = start; if (pos >= len) { status.setError(start, "Missing localized GMT offset."); return; } Locale locale = step.getAttribute(Attributes.LOCALE, attributes, Locale.ROOT); String gmtPrefix = CalendarText.getGMTPrefix(locale); String[] zeroOffsets = { "GMT", gmtPrefix, "UTC", "UT" }; boolean found = false; boolean caseInsensitive = step.getAttribute( Attributes.PARSE_CASE_INSENSITIVE, attributes, Boolean.TRUE ).booleanValue(); for (String zeroOffset : zeroOffsets) { int zl = zeroOffset.length(); if (len - pos >= zl) { String compare = text.subSequence(pos, pos + zl).toString(); if ( (caseInsensitive && compare.equalsIgnoreCase(zeroOffset)) || (!caseInsensitive && compare.equals(zeroOffset)) ) { found = true; pos += zl; break; } } } if (!found) { status.setError( start, "Missing prefix in localized offset: " + gmtPrefix); return; } else if (pos >= len) { parsedResult.put(TimezoneElement.TIMEZONE_ID, ZonalOffset.UTC); status.setPosition(pos); return; } char c = text.charAt(pos); // hack for arabic locales: LRM-marker before sign possible if ( (c == UNICODE_LRM) && "ar".equals(locale.getLanguage()) ) { if (pos + 1 >= len) { parsedResult.put(TimezoneElement.TIMEZONE_ID, ZonalOffset.UTC); status.setPosition(pos); return; } pos++; c = text.charAt(pos); } OffsetSign sign; if (c == '+') { sign = AHEAD_OF_UTC; pos++; } else if (c == '-') { sign = BEHIND_UTC; pos++; } else { parsedResult.put(TimezoneElement.TIMEZONE_ID, ZonalOffset.UTC); status.setPosition(pos); return; } int hours = parseHours(text, pos); if (hours == -1000) { status.setError( pos, "Missing hour part in localized GMT offset."); return; } if (hours < 0) { hours = ~hours; pos++; } else { pos += 2; } if (pos >= len) { if (this.abbreviated) { parsedResult.put( TimezoneElement.TIMEZONE_ID, ZonalOffset.ofHours(sign, hours)); status.setPosition(pos); } else { status.setError( pos, "Missing minute part in localized GMT offset."); } return; } Leniency leniency = step.getAttribute( Attributes.LENIENCY, attributes, Leniency.SMART ); if (text.charAt(pos) == ':') { pos++; } else if (this.abbreviated) { parsedResult.put( TimezoneElement.TIMEZONE_ID, ZonalOffset.ofHours(sign, hours)); status.setPosition(pos); return; } else if (leniency.isStrict()) { status.setError(pos, "Colon expected in localized GMT offset."); return; } int minutes = parseMinutes(text, pos); if (minutes == -1000) { status.setError( pos, "Minute part in localized GMT offset " + "does not match expected pattern mm."); return; } pos += 2; ZonalOffset offset = ZonalOffset.ofHoursMinutes(sign, hours, minutes); parsedResult.put(TimezoneElement.TIMEZONE_ID, offset); status.setPosition(pos); } @Override public ChronoElement getElement() { return TimezoneElement.TIMEZONE_ID; } @Override public FormatProcessor withElement(ChronoElement element) { return this; } @Override public boolean isNumerical() { return false; } private static ZonalOffset getOffset( ChronoDisplay formattable, FormatStep step, AttributeQuery attributes ) { AttributeQuery aq = step.getQuery(attributes); if (aq.contains(Attributes.TIMEZONE_ID)) { TZID tzid = aq.get(Attributes.TIMEZONE_ID); if (tzid instanceof ZonalOffset) { return (ZonalOffset) tzid; } } throw new IllegalArgumentException( "Cannot extract timezone offset from format attributes for: " + formattable); } private static int parseMinutes( CharSequence text, int pos ) { int total = 0; for (int i = 0; i < 2; i++) { char c; if (pos + i >= text.length()) { c = '\u0000'; } else { c = text.charAt(pos + i); } if ((c >= '0') && (c <= '9')) { total = total * 10 + (c - '0'); } else { return -1000; } } return total; } private static int parseHours( CharSequence text, int pos ) { int total = 0; for (int i = 0; i < 2; i++) { char c; if (pos + i >= text.length()) { c = '\u0000'; } else { c = text.charAt(pos + i); } if ((c >= '0') && (c <= '9')) { total = total * 10 + (c - '0'); } else if (i == 0) { return -1000; } else { return ~total; } } return total; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy