package com.ctrip.framework.apollo.util.parser; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Parsers { public static DateParser forDate() { return DateParser.INSTANCE; } public static DurationParser forDuration() { return DurationParser.INSTANCE; } public enum DateParser { INSTANCE; private static final String LONG_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS"; private static final String MEDIUM_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; private static final String SHORT_DATE_FORMAT = "yyyy-MM-dd"; /** * Will try to parse the date with Locale.US and formats as follows: * yyyy-MM-dd HH:mm:ss.SSS, yyyy-MM-dd HH:mm:ss and yyyy-MM-dd * * @param text the text to parse * @return the parsed date * @throws ParserException if the text cannot be parsed */ public Date parse(String text) throws ParserException { text = text.trim(); int length = text.length(); if (length == LONG_DATE_FORMAT.length()) { return parse(text, LONG_DATE_FORMAT); } if (length == MEDIUM_DATE_FORMAT.length()) { return parse(text, MEDIUM_DATE_FORMAT); } return parse(text, SHORT_DATE_FORMAT); } /** * Parse the text with the format specified and Locale.US * * @param text the text to parse * @param format the date format, see {@link java.text.SimpleDateFormat} for more information * @return the parsed date * @throws ParserException if the text cannot be parsed */ public Date parse(String text, String format) throws ParserException { return parse(text, format, Locale.US); } /** * Parse the text with the format and locale specified * * @param text the text to parse * @param format the date format, see {@link java.text.SimpleDateFormat} for more information * @param locale the locale * @return the parsed date * @throws ParserException if the text cannot be parsed */ public Date parse(String text, String format, Locale locale) throws ParserException { SimpleDateFormat dateFormat = getDateFormat(format, locale); try { return dateFormat.parse(text.trim()); } catch (ParseException e) { throw new ParserException("Error when parsing date(" + dateFormat.toPattern() + ") from " + text, e); } } private SimpleDateFormat getDateFormat(String format, Locale locale) { return new SimpleDateFormat(format, locale); } } public enum DurationParser { INSTANCE; private static final Pattern PATTERN = Pattern.compile("(?:([0-9]+)D)?(?:([0-9]+)H)?(?:([0-9]+)M)?(?:([0-9]+)S)?(?:([0-9]+)(?:MS)?)?", Pattern.CASE_INSENSITIVE); private static final int HOURS_PER_DAY = 24; private static final int MINUTES_PER_HOUR = 60; private static final int SECONDS_PER_MINUTE = 60; private static final int MILLIS_PER_SECOND = 1000; private static final int MILLIS_PER_MINUTE = MILLIS_PER_SECOND * SECONDS_PER_MINUTE; private static final int MILLIS_PER_HOUR = MILLIS_PER_MINUTE * MINUTES_PER_HOUR; private static final int MILLIS_PER_DAY = MILLIS_PER_HOUR * HOURS_PER_DAY; public long parseToMillis(String text) throws ParserException { Matcher matcher = PATTERN.matcher(text); if (matcher.matches()) { String dayMatch = matcher.group(1); String hourMatch = matcher.group(2); String minuteMatch = matcher.group(3); String secondMatch = matcher.group(4); String fractionMatch = matcher.group(5); if (dayMatch != null || hourMatch != null || minuteMatch != null || secondMatch != null || fractionMatch != null) { int daysAsMilliSecs = parseNumber(dayMatch, MILLIS_PER_DAY); int hoursAsMilliSecs = parseNumber(hourMatch, MILLIS_PER_HOUR); int minutesAsMilliSecs = parseNumber(minuteMatch, MILLIS_PER_MINUTE); int secondsAsMilliSecs = parseNumber(secondMatch, MILLIS_PER_SECOND); int milliseconds = parseNumber(fractionMatch, 1); return daysAsMilliSecs + hoursAsMilliSecs + minutesAsMilliSecs + secondsAsMilliSecs + milliseconds; } } throw new ParserException(String.format("Text %s cannot be parsed to duration)", text)); } private static int parseNumber(String parsed, int multiplier) { // regex limits to [0-9]+ if (parsed == null || parsed.trim().isEmpty()) { return 0; } return Integer.parseInt(parsed) * multiplier; } } }