net.hasor.utils.json.DateCache Maven / Gradle / Ivy
// ========================================================================
// Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package net.hasor.utils.json;
import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
/* ------------------------------------------------------------ */
/** Date Format Cache.
* Computes String representations of Dates and caches
* the results so that subsequent requests within the same minute
* will be fast.
*
* Only format strings that contain either "ss" or "ss.SSS" are
* handled.
*
* The timezone of the date may be included as an ID with the "zzz"
* format string or as an offset with the "ZZZ" format string.
*
* If consecutive calls are frequently very different, then this
* may be a little slower than a normal DateFormat.
*
*
*
*/
class DateCache {
public static String DEFAULT_FORMAT = "EEE MMM dd HH:mm:ss zzz yyyy";
private static long __hitWindow = 60 * 60;
private String _formatString;
private String _tzFormatString;
private SimpleDateFormat _tzFormat;
private String _minFormatString;
private SimpleDateFormat _minFormat;
private String _secFormatString;
private String _secFormatString0;
private String _secFormatString1;
private long _lastMinutes = -1;
private long _lastSeconds = -1;
private int _lastMs = -1;
private String _lastResult = null;
private Locale _locale = null;
private DateFormatSymbols _dfs = null;
/* ------------------------------------------------------------ */
/** Constructor.
* Make a DateCache that will use a default format. The default format
* generates the same results as Date.toString().
*/
public DateCache() {
this(DEFAULT_FORMAT);
getFormat().setTimeZone(TimeZone.getDefault());
}
/* ------------------------------------------------------------ */
/** Constructor.
* Make a DateCache that will use the given format
*/
public DateCache(String format) {
_formatString = format;
setTimeZone(TimeZone.getDefault());
}
/* ------------------------------------------------------------ */
public DateCache(String format, Locale l) {
_formatString = format;
_locale = l;
setTimeZone(TimeZone.getDefault());
}
/* ------------------------------------------------------------ */
public DateCache(String format, DateFormatSymbols s) {
_formatString = format;
_dfs = s;
setTimeZone(TimeZone.getDefault());
}
/* ------------------------------------------------------------ */
/** Set the timezone.
* @param tz TimeZone
*/
public synchronized void setTimeZone(TimeZone tz) {
setTzFormatString(tz);
if (_locale != null) {
_tzFormat = new SimpleDateFormat(_tzFormatString, _locale);
_minFormat = new SimpleDateFormat(_minFormatString, _locale);
} else if (_dfs != null) {
_tzFormat = new SimpleDateFormat(_tzFormatString, _dfs);
_minFormat = new SimpleDateFormat(_minFormatString, _dfs);
} else {
_tzFormat = new SimpleDateFormat(_tzFormatString);
_minFormat = new SimpleDateFormat(_minFormatString);
}
_tzFormat.setTimeZone(tz);
_minFormat.setTimeZone(tz);
_lastSeconds = -1;
_lastMinutes = -1;
}
/* ------------------------------------------------------------ */
public TimeZone getTimeZone() {
return _tzFormat.getTimeZone();
}
/* ------------------------------------------------------------ */
/** Set the timezone.
* @param timeZoneId TimeZoneId the ID of the zone as used by
* TimeZone.getTimeZone(id)
*/
public void setTimeZoneID(String timeZoneId) {
setTimeZone(TimeZone.getTimeZone(timeZoneId));
}
/* ------------------------------------------------------------ */
private synchronized void setTzFormatString(final TimeZone tz) {
int zIndex = _formatString.indexOf("ZZZ");
if (zIndex >= 0) {
String ss1 = _formatString.substring(0, zIndex);
String ss2 = _formatString.substring(zIndex + 3);
int tzOffset = tz.getRawOffset();
StringBuilder sb = new StringBuilder(_formatString.length() + 10);
sb.append(ss1);
sb.append("'");
if (tzOffset >= 0)
sb.append('+');
else {
tzOffset = -tzOffset;
sb.append('-');
}
int raw = tzOffset / (1000 * 60); // Convert to seconds
int hr = raw / 60;
int min = raw % 60;
if (hr < 10)
sb.append('0');
sb.append(hr);
if (min < 10)
sb.append('0');
sb.append(min);
sb.append('\'');
sb.append(ss2);
_tzFormatString = sb.toString();
} else
_tzFormatString = _formatString;
setMinFormatString();
}
/* ------------------------------------------------------------ */
private void setMinFormatString() {
int i = _tzFormatString.indexOf("ss.SSS");
int l = 6;
if (i >= 0)
throw new IllegalStateException("ms not supported");
i = _tzFormatString.indexOf("ss");
l = 2;
// Build a formatter that formats a second format string
String ss1 = _tzFormatString.substring(0, i);
String ss2 = _tzFormatString.substring(i + l);
_minFormatString = ss1 + "'ss'" + ss2;
}
/* ------------------------------------------------------------ */
/** Format a date according to our stored formatter.
* @param inDate
* @return Formatted date
*/
public synchronized String format(Date inDate) {
return format(inDate.getTime());
}
/* ------------------------------------------------------------ */
/** Format a date according to our stored formatter.
* @param inDate
* @return Formatted date
*/
public synchronized String format(long inDate) {
long seconds = inDate / 1000;
// Is it not suitable to cache?
if (seconds < _lastSeconds || _lastSeconds > 0 && seconds > _lastSeconds + __hitWindow) {
// It's a cache miss
Date d = new Date(inDate);
return _tzFormat.format(d);
}
// Check if we are in the same second
// and don't care about millis
if (_lastSeconds == seconds)
return _lastResult;
Date d = new Date(inDate);
// Check if we need a new format string
long minutes = seconds / 60;
if (_lastMinutes != minutes) {
_lastMinutes = minutes;
_secFormatString = _minFormat.format(d);
int i = _secFormatString.indexOf("ss");
int l = 2;
_secFormatString0 = _secFormatString.substring(0, i);
_secFormatString1 = _secFormatString.substring(i + l);
}
// Always format if we get here
_lastSeconds = seconds;
StringBuilder sb = new StringBuilder(_secFormatString.length());
sb.append(_secFormatString0);
int s = (int) (seconds % 60);
if (s < 10)
sb.append('0');
sb.append(s);
sb.append(_secFormatString1);
_lastResult = sb.toString();
return _lastResult;
}
/* ------------------------------------------------------------ */
/** Format to string buffer.
* @param inDate Date the format
* @param buffer StringBuilder
*/
public void format(long inDate, StringBuilder buffer) {
buffer.append(format(inDate));
}
/* ------------------------------------------------------------ */
/** Get the format.
*/
public SimpleDateFormat getFormat() {
return _minFormat;
}
/* ------------------------------------------------------------ */
public String getFormatString() {
return _formatString;
}
/* ------------------------------------------------------------ */
public String now() {
long now = System.currentTimeMillis();
_lastMs = (int) (now % 1000);
return format(now);
}
/* ------------------------------------------------------------ */
public int lastMs() {
return _lastMs;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy