ISODateComponent.java
/*
* Copyright 2006 - 2013
* Stefan Balev <stefan.balev@graphstream-project.org>
* Julien Baudry <julien.baudry@graphstream-project.org>
* Antoine Dutot <antoine.dutot@graphstream-project.org>
* Yoann Pigné <yoann.pigne@graphstream-project.org>
* Guilhelm Savin <guilhelm.savin@graphstream-project.org>
*
* This file is part of GraphStream <http://graphstream-project.org>.
*
* GraphStream is a library whose purpose is to handle static or dynamic
* graph, create them from scratch, file or any source and display them.
*
* This program is free software distributed under the terms of two licenses, the
* CeCILL-C license that fits European law, and the GNU Lesser General Public
* License. You can use, modify and/ or redistribute the software under the terms
* of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
* URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
*/
package org.graphstream.util.time;
import java.text.DateFormatSymbols;
import java.util.Calendar;
import java.util.Locale;
/**
* Defines components of {@link ISODateIO}.
*
*/
public abstract class ISODateComponent {
/**
* Directives shortcut of the component. This property can not be changed.
*/
protected final String directive;
/**
* Replacement of the directive. Could be a regular expression. The value
* catch will be sent to the component with
* <i>set(catched_value,Calendar)</i>. This property can not be changed.
*/
protected final String replace;
/**
* Build a new component composed of a directive name ("%.") and a
* replacement value.
*
* @param directive
* directive name, should start with a leading '%'.
* @param replace
* replace the directive with the value given here.
*/
public ISODateComponent(String directive, String replace) {
this.directive = directive;
this.replace = replace;
}
/**
* Access to the directive name of the component.
*
* @return directive of the component.
*/
public String getDirective() {
return directive;
}
/**
* Return true if this component is an alias. An alias can contain other
* directive name and its replacement should be parse again.
*
* @return true if component is an alias.
*/
public boolean isAlias() {
return false;
}
/**
* Get the replacement value of this component.
*
* @return replacement value
*/
public String getReplacement() {
return replace;
}
/**
* Handle the value catched with the replacement value.
*
* @param value
* value matching the replacement string
* @param calendar
* calendar we are working on
*/
public abstract void set(String value, Calendar calendar);
/**
* Get a string representation of this component for a given calendar.
*
* @param calendar
* the calendar
* @return string representation of this component.
*/
public abstract String get(Calendar calendar);
/**
* Defines an alias component. Such component does nothing else that replace
* them directive by another string.
*/
public static class AliasComponent extends ISODateComponent {
public AliasComponent(String shortcut, String replace) {
super(shortcut, replace);
}
public boolean isAlias() {
return true;
}
public void set(String value, Calendar calendar) {
// Nothing to do
}
public String get(Calendar calendar) {
return "";
}
}
/**
* Defines a text component. Such component does nothing else that append
* text to the resulting regular expression.
*/
public static class TextComponent extends ISODateComponent {
public TextComponent(String value) {
super(null, value);
}
public void set(String value, Calendar calendar) {
// Nothing to do
}
public String get(Calendar calendar) {
return replace;
}
}
/**
* Defines a component associated with a field of a calendar. When a value
* is handled, component will try to set the associated field of the
* calendar.
*/
public static class FieldComponent extends ISODateComponent {
protected final int field;
protected final int offset;
protected final String format;
public FieldComponent(String shortcut, String replace, int field,
String format) {
this(shortcut, replace, field, 0, format);
}
public FieldComponent(String shortcut, String replace, int field,
int offset, String format) {
super(shortcut, replace);
this.field = field;
this.offset = offset;
this.format = format;
}
public void set(String value, Calendar calendar) {
while (value.charAt(0) == '0' && value.length() > 1)
value = value.substring(1);
int val = Integer.parseInt(value);
calendar.set(field, val + offset);
}
public String get(Calendar calendar) {
return String.format(format, calendar.get(field));
}
}
/**
* Base for locale-dependent component.
*/
protected static abstract class LocaleDependentComponent extends
ISODateComponent {
protected Locale locale;
protected DateFormatSymbols symbols;
public LocaleDependentComponent(String shortcut, String replace) {
this(shortcut, replace, Locale.getDefault());
}
public LocaleDependentComponent(String shortcut, String replace,
Locale locale) {
super(shortcut, replace);
this.locale = locale;
this.symbols = DateFormatSymbols.getInstance(locale);
}
}
/**
* Component handling AM/PM.
*/
public static class AMPMComponent extends LocaleDependentComponent {
public AMPMComponent() {
super("%p", "AM|PM|am|pm");
}
public void set(String value, Calendar calendar) {
if (value.equalsIgnoreCase(symbols.getAmPmStrings()[Calendar.AM]))
calendar.set(Calendar.AM_PM, Calendar.AM);
else if (value
.equalsIgnoreCase(symbols.getAmPmStrings()[Calendar.PM]))
calendar.set(Calendar.AM_PM, Calendar.PM);
}
public String get(Calendar calendar) {
return symbols.getAmPmStrings()[calendar.get(Calendar.AM_PM)];
}
}
/**
* Component handling utc offset (+/- 0000).
*/
public static class UTCOffsetComponent extends ISODateComponent {
public UTCOffsetComponent() {
super("%z", "[-+]\\d{4}");
}
public void set(String value, Calendar calendar) {
String hs = value.substring(1, 3);
String ms = value.substring(3, 5);
if (hs.charAt(0) == '0')
hs = hs.substring(1);
if (ms.charAt(0) == '0')
ms = ms.substring(1);
int i = value.charAt(0) == '+' ? 1 : -1;
int h = Integer.parseInt(hs);
int m = Integer.parseInt(ms);
calendar.getTimeZone().setRawOffset(i * (h * 60 + m) * 60000);
}
public String get(Calendar calendar) {
int offset = calendar.getTimeZone().getRawOffset();
String sign = "+";
if (offset < 0) {
sign = "-";
offset = -offset;
}
offset /= 60000;
int h = offset / 60;
int m = offset % 60;
return String.format("%s%02d%02d", sign, h, m);
}
}
/**
* Component handling a number of milliseconds since the epoch (january, 1st
* 1970).
*/
public static class EpochComponent extends ISODateComponent {
public EpochComponent() {
super("%K", "\\d+");
}
public void set(String value, Calendar calendar) {
long e = Long.parseLong(value);
calendar.setTimeInMillis(e);
}
public String get(Calendar calendar) {
return String.format("%d", calendar.getTimeInMillis());
}
}
/**
* Defines a not implemented component. Such components throw an Error if
* used.
*/
public static class NotImplementedComponent extends ISODateComponent {
public NotImplementedComponent(String shortcut, String replace) {
super(shortcut, replace);
}
public void set(String value, Calendar cal) {
throw new Error("not implemented component");
}
public String get(Calendar calendar) {
throw new Error("not implemented component");
}
}
public static final ISODateComponent ABBREVIATED_WEEKDAY_NAME = new NotImplementedComponent(
"%a", "\\w+[.]");
public static final ISODateComponent FULL_WEEKDAY_NAME = new NotImplementedComponent(
"%A", "\\w+");
public static final ISODateComponent ABBREVIATED_MONTH_NAME = new NotImplementedComponent(
"%b", "\\w+[.]");
public static final ISODateComponent FULL_MONTH_NAME = new NotImplementedComponent(
"%B", "\\w+");
public static final ISODateComponent LOCALE_DATE_AND_TIME = new NotImplementedComponent(
"%c", null);
public static final ISODateComponent CENTURY = new NotImplementedComponent(
"%C", "\\d\\d");
public static final ISODateComponent DAY_OF_MONTH_2_DIGITS = new FieldComponent(
"%d", "[012]\\d|3[01]", Calendar.DAY_OF_MONTH, "%02d");
public static final ISODateComponent DATE = new AliasComponent("%D",
"%m/%d/%y");
public static final ISODateComponent DAY_OF_MONTH = new FieldComponent(
"%e", "\\d|[12]\\d|3[01]", Calendar.DAY_OF_MONTH, "%2d");
public static final ISODateComponent DATE_ISO8601 = new AliasComponent(
"%F", "%Y-%m-%d");
public static final ISODateComponent WEEK_BASED_YEAR_2_DIGITS = new FieldComponent(
"%g", "\\d\\d", Calendar.YEAR, "%02d");
public static final ISODateComponent WEEK_BASED_YEAR_4_DIGITS = new FieldComponent(
"%G", "\\d{4}", Calendar.YEAR, "%04d");
public static final ISODateComponent ABBREVIATED_MONTH_NAME_ALIAS = new AliasComponent(
"%h", "%b");
public static final ISODateComponent HOUR_OF_DAY = new FieldComponent("%H",
"[01]\\d|2[0123]", Calendar.HOUR_OF_DAY, "%02d");
public static final ISODateComponent HOUR = new FieldComponent("%I",
"0\\d|1[012]", Calendar.HOUR, "%02d");
public static final ISODateComponent DAY_OF_YEAR = new FieldComponent("%j",
"[012]\\d\\d|3[0-5]\\d|36[0-6]", Calendar.DAY_OF_YEAR, "%03d");
public static final ISODateComponent MILLISECOND = new FieldComponent("%k",
"\\d{3}", Calendar.MILLISECOND, "%03d");
public static final ISODateComponent EPOCH = new EpochComponent();
public static final ISODateComponent MONTH = new FieldComponent("%m",
"0[1-9]|1[012]", Calendar.MONTH, -1, "%02d");
public static final ISODateComponent MINUTE = new FieldComponent("%M",
"[0-5]\\d", Calendar.MINUTE, "%02d");
public static final ISODateComponent NEW_LINE = new AliasComponent("%n",
"\n");
public static final ISODateComponent AM_PM = new AMPMComponent();
public static final ISODateComponent LOCALE_CLOCK_TIME_12_HOUR = new NotImplementedComponent(
"%r", "");
public static final ISODateComponent HOUR_AND_MINUTE = new AliasComponent(
"%R", "%H:%M");
public static final ISODateComponent SECOND = new FieldComponent("%S",
"[0-5]\\d|60", Calendar.SECOND, "%02d");
public static final ISODateComponent TABULATION = new AliasComponent("%t",
"\t");
public static final ISODateComponent TIME_ISO8601 = new AliasComponent(
"%T", "%H:%M:%S");
public static final ISODateComponent DAY_OF_WEEK_1_7 = new FieldComponent(
"%u", "[1-7]", Calendar.DAY_OF_WEEK, -1, "%1d");
public static final ISODateComponent WEEK_OF_YEAR_FROM_SUNDAY = new FieldComponent(
"%U", "[0-4]\\d|5[0123]", Calendar.WEEK_OF_YEAR, 1, "%2d");
public static final ISODateComponent WEEK_NUMBER_ISO8601 = new NotImplementedComponent(
"%V", "0[1-9]|[2-4]\\d|5[0123]");
public static final ISODateComponent DAY_OF_WEEK_0_6 = new FieldComponent(
"%w", "[0-6]", Calendar.DAY_OF_WEEK, "%01d");
public static final ISODateComponent WEEK_OF_YEAR_FROM_MONDAY = new FieldComponent(
"%W", "[0-4]\\d|5[0123]", Calendar.WEEK_OF_YEAR, "%02d");
public static final ISODateComponent LOCALE_DATE_REPRESENTATION = new NotImplementedComponent(
"%x", "");
public static final ISODateComponent LOCALE_TIME_REPRESENTATION = new NotImplementedComponent(
"%X", "");
public static final ISODateComponent YEAR_2_DIGITS = new FieldComponent(
"%y", "\\d\\d", Calendar.YEAR, "%02d");
public static final ISODateComponent YEAR_4_DIGITS = new FieldComponent(
"%Y", "\\d{4}", Calendar.YEAR, "%04d");
public static final ISODateComponent UTC_OFFSET = new UTCOffsetComponent();
public static final ISODateComponent LOCALE_TIME_ZONE_NAME = new NotImplementedComponent(
"%Z", "\\w*");
public static final ISODateComponent PERCENT = new AliasComponent("%%", "%");
}