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

org.dominokit.jacksonapt.utils.DefaultDateFormat Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2013 Nicolas Morel
 *
 * 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 org.dominokit.jacksonapt.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.dominokit.jacksonapt.GwtIncompatible;
import org.dominokit.jacksonapt.JacksonContext;
import org.dominokit.jacksonapt.JsonSerializerParameters;
import org.dominokit.jacksonapt.deser.map.key.DateKeyParser;
import org.dominokit.jacksonapt.deser.map.key.DefaultDateKeyParser;

/**
 * A date format wrapper that works in the JVM, this implementation will be stripped out during the
 * GWT/J2CL compilation. to see the browser implementation please check {@link JsDateFormat}
 */
@GwtIncompatible
public final class DefaultDateFormat implements JacksonContext.DateFormat {

  /**
   * Defines a commonly used date format that conforms to ISO-8601 date formatting standard, when it
   * includes basic undecorated timezone definition
   */
  public static final DateTimeFormatter DATE_FORMAT_STR_ISO8601 =
      DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

  /** Same as 'regular' 8601, but handles 'Z' as an alias for "+0000" (or "GMT") */
  public static final DateTimeFormatter DATE_FORMAT_STR_ISO8601_Z =
      DateTimeFormatter.ISO_ZONED_DATE_TIME;

  /** ISO-8601 with just the Date part, no time */
  public static final DateTimeFormatter DATE_FORMAT_STR_PLAIN =
      DateTimeFormatter.ofPattern("yyyy-MM-dd");

  /** This constant defines the date format specified by RFC 1123 / RFC 822. */
  public static final DateTimeFormatter DATE_FORMAT_STR_RFC1123 =
      DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss zzz");

  /** UTC TimeZone */
  public static final ZoneId UTC_TIMEZONE = ZoneOffset.UTC;

  private static final Map CACHE_PARSERS = new HashMap();

  /** Constructor for DefaultDateFormat. */
  public DefaultDateFormat() {}

  /**
   * {@inheritDoc}
   *
   * 

Format a date using {@link #DATE_FORMAT_STR_ISO8601} and {@link #UTC_TIMEZONE} */ public String format(Date date) { return format(DefaultDateFormat.DATE_FORMAT_STR_ISO8601, DefaultDateFormat.UTC_TIMEZONE, date); } /** * {@inheritDoc} * *

Format a date using {@link JsonSerializerParameters} or default values : {@link * #DATE_FORMAT_STR_ISO8601} and {@link #UTC_TIMEZONE} */ public String format(JsonSerializerParameters params, Date date) { DateTimeFormatter format; if (null == params.getPattern()) { format = DefaultDateFormat.DATE_FORMAT_STR_ISO8601; } else { format = DateTimeFormatter.ofPattern(params.getPattern()); } ZoneId timeZone; if (null == params.getTimezone()) { timeZone = DefaultDateFormat.UTC_TIMEZONE; } else { timeZone = (ZoneId) params.getTimezone(); } return format(format, timeZone, date); } /** * {@inheritDoc} * *

Format a date using the {@link DateTimeFormatter} given in parameter and {@link * #UTC_TIMEZONE}. */ public String format(DateTimeFormatter format, Date date) { return format(format, UTC_TIMEZONE, date); } /** * {@inheritDoc} * *

Format a date using {@link #DATE_FORMAT_STR_ISO8601} and {@link ZoneId} given in parameter */ public String format(ZoneId timeZone, Date date) { return DefaultDateFormat.DATE_FORMAT_STR_ISO8601.withZone(timeZone).format(date.toInstant()); } /** * Format a date using the {@link java.time.format.DateTimeFormatter} and {@link java.time.ZoneId} * given in parameters * * @param format format to use * @param timeZone timezone to use * @param date date to format * @return the formatted date */ public String format(DateTimeFormatter format, ZoneId timeZone, Date date) { if (date instanceof java.sql.Date || date instanceof java.sql.Time) return format.withZone(timeZone).format(new Date(date.getTime()).toInstant()); return format.withZone(timeZone).format(date.toInstant()); } /** * Parse a date using {@link #DATE_FORMAT_STR_ISO8601} and the browser timezone. * * @param date date to parse * @return the parsed date */ public Date parse(String date) { return parse(DefaultDateFormat.DATE_FORMAT_STR_ISO8601, date); } /** * {@inheritDoc} * *

Parse a date using the pattern given in parameter or {@link #DATE_FORMAT_STR_ISO8601} and * the browser timezone. */ public Date parse(boolean useBrowserTimezone, String pattern, Boolean hasTz, String date) { if (null == pattern) { try { return parse(DefaultDateFormat.DATE_FORMAT_STR_ISO8601, date); } catch (DateTimeParseException e) { return parse(DefaultDateFormat.DATE_FORMAT_STR_ISO8601_Z, date); } } else { String patternCacheKey = pattern + useBrowserTimezone; DateParser parser = CACHE_PARSERS.get(patternCacheKey); if (null == parser) { boolean patternHasTz = useBrowserTimezone || (hasTz == null ? hasTz(pattern) : hasTz.booleanValue()); if (patternHasTz) { parser = new DateParser(pattern); } else { // the pattern does not have a timezone, we use the UTC timezone as reference parser = new DateParserNoTz(pattern); } CACHE_PARSERS.put(patternCacheKey, parser); } return parser.parse(date); } } /** * Find if a pattern contains informations about the timezone. * * @param pattern pattern * @return true if the pattern contains informations about the timezone, false otherwise */ private boolean hasTz(String pattern) { boolean inQuote = false; for (int i = 0; i < pattern.length(); i++) { char ch = pattern.charAt(i); // If inside quote, except two quote connected, just copy or exit. if (inQuote) { if (ch == '\'') { if (i + 1 < pattern.length() && pattern.charAt(i + 1) == '\'') { // Quote appeared twice continuously, interpret as one quote. ++i; } else { inQuote = false; } } continue; } // Outside quote now. if ("Zzv".indexOf(ch) >= 0) { return true; } // Two consecutive quotes is a quote literal, inside or outside of quotes. if (ch == '\'') { if (i + 1 < pattern.length() && pattern.charAt(i + 1) == '\'') { i++; } else { inQuote = true; } } } return false; } /** * Parse a date using the {@link java.time.format.DateTimeFormatter} given in parameter and the * browser timezone. * * @param format format to use * @param date date to parse * @return the parsed date */ public Date parse(DateTimeFormatter format, String date) { return Date.from(Instant.from(format.parse(date))); } /** * Parse a date using the {@link java.time.format.DateTimeFormatter} given in parameter and the * browser timezone. * * @param format format to use * @param date date to parse * @return the parsed date */ public Date parse(SimpleDateFormat format, String date) { try { return format.parse(date); } catch (ParseException e) { return null; } } /** {@inheritDoc} */ @Override public DateKeyParser makeDateKeyParser() { return new DefaultDateKeyParser<>(); } private class DateParser { protected final SimpleDateFormat dateTimeFormat; protected DateParser(String pattern) { this.dateTimeFormat = new SimpleDateFormat(pattern); } protected Date parse(String date) { return DefaultDateFormat.this.parse(dateTimeFormat, date); } } private class DateParserNoTz extends DateParser { protected DateParserNoTz(String pattern) { super(pattern + " Z"); } @Override protected Date parse(String date) { return super.parse(date + " +0000"); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy