/* * Copyright 2006 Robert Hanson <iamroberthanson AT gmail.com> * * 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 net.autosauler.ballance.client.utils; import java.util.Date; /** * This is a simple regular expression based parser for date notations. While * our aim is to fully support in the future the JDK date parser, currently only * numeric notations and literals are supported such as * <code>dd/MM/yyyy HH:mm:ss.SSSS</code>. Each entity is parsed with the same * number of digits, i.e. for <code>dd</code> two digits will be parsed while * for <code>d</code> only one will be parsed. * * @author <a href="mailto:g.georgovassilis@gmail.com">George Georgovassilis</a> * */ public class SimpleDateParser { @SuppressWarnings("unused") private final static String DAY_IN_MONTH = "d"; @SuppressWarnings("unused") private final static String MONTH = "M"; @SuppressWarnings("unused") private final static String YEAR = "y"; @SuppressWarnings("unused") private final static String LITERAL = "\\"; private final static int DATE_PATTERN = 0; private final static int REGEX_PATTERN = 1; private final static int COMPONENT = 2; private final static int REGEX = 0; private final static int INSTRUCTION = 1; private final static String[] TOKENS[] = { { "SSSS", "(\\d\\d\\d\\d)", DateLocale.TOKEN_MILLISECOND }, { "SSS", "(\\d\\d\\d)", DateLocale.TOKEN_MILLISECOND }, { "SS", "(\\d\\d)", DateLocale.TOKEN_MILLISECOND }, { "S", "(\\d)", DateLocale.TOKEN_MILLISECOND }, { "ss", "(\\d\\d)", DateLocale.TOKEN_SECOND }, { "s", "(\\d)", DateLocale.TOKEN_SECOND }, { "mm", "(\\d\\d)", DateLocale.TOKEN_MINUTE }, { "m", "(\\d)", DateLocale.TOKEN_MINUTE }, { "HH", "(\\d\\d)", DateLocale.TOKEN_HOUR_24 }, { "H", "(\\d)", DateLocale.TOKEN_HOUR_24 }, { "dd", "(\\d\\d)", DateLocale.TOKEN_DAY_OF_MONTH }, { "d", "(\\d)", DateLocale.TOKEN_DAY_OF_MONTH }, { "MM", "(\\d\\d)", DateLocale.TOKEN_MONTH }, { "M", "(\\d)", DateLocale.TOKEN_MONTH }, { "yyyy", "(\\d\\d\\d\\d)", DateLocale.TOKEN_YEAR }, { "yyy", "(\\d\\d\\d)", DateLocale.TOKEN_YEAR }, { "yy", "(\\d\\d)", DateLocale.TOKEN_YEAR }, { "y", "(\\d)", DateLocale.TOKEN_YEAR } }; private static void _parse(String format, String[] args) { if (format.length() == 0) { return; } if (format.startsWith("'")) { format = format.substring(1); int end = format.indexOf("'"); if (end == -1) { throw new IllegalArgumentException("Unmatched single quotes."); } args[REGEX] += Pattern.quote(format.substring(0, end)); format = format.substring(end + 1); } for (int i = 0; i < TOKENS.length; i++) { String[] row = TOKENS[i]; String datePattern = row[DATE_PATTERN]; if (!format.startsWith(datePattern)) { continue; } format = format.substring(datePattern.length()); args[REGEX] += row[REGEX_PATTERN]; args[INSTRUCTION] += row[COMPONENT]; _parse(format, args); return; } args[REGEX] += Pattern.quote("" + format.charAt(0)); format = format.substring(1); _parse(format, args); }; @SuppressWarnings("deprecation") private static void load(Date date, String text, String component) { if (component.equals(DateLocale.TOKEN_MILLISECOND)) { // TODO: implement } if (component.equals(DateLocale.TOKEN_SECOND)) { date.setSeconds(Integer.parseInt(text)); } if (component.equals(DateLocale.TOKEN_MINUTE)) { date.setMinutes(Integer.parseInt(text)); } if (component.equals(DateLocale.TOKEN_HOUR_24)) { date.setHours(Integer.parseInt(text)); } if (component.equals(DateLocale.TOKEN_DAY_OF_MONTH)) { date.setDate(Integer.parseInt(text)); } if (component.equals(DateLocale.TOKEN_MONTH)) { date.setMonth(Integer.parseInt(text) - 1); } if (component.equals(DateLocale.TOKEN_YEAR)) { // TODO: fix for short patterns date.setYear(Integer.parseInt(text) - 1900); } } public static Date parse(String input, String pattern) { return new SimpleDateParser(pattern).parse(input); } private final Pattern regularExpression; private String instructions = ""; public SimpleDateParser(String format) { String[] args = new String[] { "", "" }; _parse(format, args); regularExpression = new Pattern(args[REGEX]); instructions = args[INSTRUCTION]; } public Date parse(String input) { @SuppressWarnings("deprecation") Date date = new Date(0, 0, 0, 0, 0, 0); String matches[] = regularExpression.match(input); if (matches == null) { throw new IllegalArgumentException(input + " does not match " + regularExpression.pattern()); } if (matches.length - 1 != instructions.length()) { throw new IllegalArgumentException("Different group count - " + input + " does not match " + regularExpression.pattern()); } for (int group = 0; group < instructions.length(); group++) { String match = matches[group + 1]; load(date, match, "" + instructions.charAt(group)); } return date; } }