/* * Freeplane - mind map editor * Copyright (C) 2011 dimitry * * This file author is dimitry * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.freeplane.features.format; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Date; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.freeplane.core.util.FactoryMethod; import org.freeplane.core.util.SerializationMethod; /** * @author Dimitry Polivaev * Mar 2, 2011 */ @SuppressWarnings("serial") @FactoryMethod("deserialize") @SerializationMethod("serialize") public class FormattedDate extends Date implements IFormattedObject { public static final String ISO_DATE_FORMAT_PATTERN = "yyyy-MM-dd"; public static final String ISO_DATE_TIME_FORMAT_PATTERN = "yyyy-MM-dd'T'HH:mmZ"; public static final Pattern ISO_DATE_TIME_REGEXP_PATTERN = Pattern.compile("\\d{4}(-?)\\d{2}(-?)\\d{2}" // + "(([ T])?\\d{2}(:?)\\d{2}(:?)(\\d{2})?(\\.\\d{3})?([-+]\\d{4})?)?"); private SimpleDateFormat df; private String defaultType; public FormattedDate(FormattedDate date) { this(date.getTime(), date.getDateFormat()); } public FormattedDate(Date date, String pattern) { super(date.getTime()); this.df = FormatController.getController().getDateFormat(pattern); } public FormattedDate(long date, SimpleDateFormat df) { super(date); this.df = df; } /**@deprecated use {@link #createDefaultFormattedDate(long, String)} instead. */ public FormattedDate(long date) { this(date, FormatController.getController().getDefaultDateFormat()); this.defaultType = IFormattedObject.TYPE_DATE; } public static FormattedDate createDefaultFormattedDate(long time, String type) { final FormattedDate formattedDate = new FormattedDate(time, (SimpleDateFormat) FormatController.getController().getDefaultFormat(type)); formattedDate.defaultType = type; return formattedDate; } @Override public String toString() { return df.format(this); } /** default formats are not saved to file. */ public static String serialize(final FormattedDate date) { return toStringISO(date) + "|" + (date.defaultType != null ? date.defaultType : date.df.toPattern()); } public static String toStringISO(final Date date) { // use local timezone return FormatController.getController().getDateFormat(ISO_DATE_TIME_FORMAT_PATTERN).format(date); } public static String toStringShortISO(final Date date) { return FormatController.getController().getDateFormat(ISO_DATE_FORMAT_PATTERN).format(date); } public static Object deserialize(String text) { final int index = text.indexOf('|'); final FormattedDate date; final String arg; if (index == -1) { date = toDateISO(text); arg = IFormattedObject.TYPE_DATE; } else { date = toDateISO(text.substring(0, index)); arg = text.substring(index + 1); } if (date == null) return text; if (arg.equals(IFormattedObject.TYPE_DATE) || arg.equals(IFormattedObject.TYPE_DATETIME)) { date.defaultType = arg; date.df = (SimpleDateFormat) FormatController.getController().getDefaultFormat(arg); } else { date.df = FormatController.getController().getDateFormat(arg); } return date; } public static FormattedDate toDate(String text) { return toDateISO(text); } public static boolean isDate(String text) { if (text == null) return false; return ISO_DATE_TIME_REGEXP_PATTERN.matcher(text).matches(); } public static FormattedDate toDateISO(String text) { // 1 2 34 5 6 7 8 9 // \\d{4}(-?)\\d{2}(-?)\\d{2}(([ T])?\\d{2}(:?)\\d{2}(:?)(\\d{2})?(\\.\\d{3})?([-+]\\d{4})?)? final Matcher matcher = ISO_DATE_TIME_REGEXP_PATTERN.matcher(text); if (matcher.matches()) { StringBuilder builder = new StringBuilder("yyyy"); builder.append(matcher.group(1)); builder.append("MM"); builder.append(matcher.group(2)); builder.append("dd"); if (matcher.group(3) != null) { if (matcher.group(4) != null) { builder.append('\''); builder.append(matcher.group(4)); builder.append('\''); } builder.append("HH"); builder.append(matcher.group(5)); builder.append("mm"); if (matcher.group(7) != null) { builder.append(matcher.group(6)); builder.append("ss"); } if (matcher.group(8) != null) { builder.append(".SSS"); } if (matcher.group(9) != null) { builder.append("Z"); } } final String pattern = builder.toString(); return parseDate(text, pattern); } return null; } static private FormattedDate parseDate(String text, final String pattern) { SimpleDateFormat parser = FormatController.getController().getDateFormat(pattern); final ParsePosition pos = new ParsePosition(0); final Date date = parser.parse(text, pos); if (date != null && pos.getIndex() == text.length()) { return new FormattedDate(date.getTime(), parser); } return null; } public boolean containsTime() { return df.toPattern().contains("m"); } public SimpleDateFormat getDateFormat() { return df; } public String getPattern() { return df.toPattern(); } public Date getObject() { return this; } @Override public boolean equals(Object obj) { return obj instanceof FormattedDate && super.equals(obj) && ((FormattedDate) obj).getDateFormat().equals(df); } @Override public int hashCode() { return 37 * super.hashCode() + df.hashCode(); } }