blob: 72ee6fc1d29cd1f380ad23afce7e6f9d31de8de3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.chemistry.opencmis.commons.impl;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class DateTimeHelper {
private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
private static final Pattern XML_DATETIME = Pattern
.compile("(\\d{4,9})-([01]\\d)-([0-3]\\d)T([0-2]\\d):([0-5]\\d):([0-5]\\d)(\\.(\\d+))?(([+-][0-2]\\d:[0-5]\\d)|Z)?");
private static final BigDecimal BD1000 = new BigDecimal(1000);
private static final String[] WDAYS = new String[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
private static final String[] MONTHS = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec" };
private static final Map<String, Integer> MONTHS_MAP = new HashMap<String, Integer>();
static {
for (int i = 0; i < MONTHS.length; i++) {
MONTHS_MAP.put(MONTHS[i], i);
}
}
private static final Pattern HTTP_DATETIME1 = Pattern
.compile("\\w{3}, ([0-3]\\d) (\\w{3}) (\\d{4}) ([0-2]\\d):([0-5]\\d):([0-5]\\d) GMT");
private static final Pattern HTTP_DATETIME2 = Pattern
.compile("\\w{6,9}, ([0-3]\\d)-(\\w{3})-(\\d{2}) ([0-2]\\d):([0-5]\\d):([0-5]\\d) GMT");
private static final Pattern HTTP_DATETIME3 = Pattern
.compile("\\w{3} (\\w{3}) ([0-3 ]\\d) ([0-2]\\d):([0-5]\\d):([0-5]\\d) (\\d{4})");
private DateTimeHelper() {
}
/**
* Parses a xsd:dateTime string.
*/
public static GregorianCalendar parseXmlDateTime(String s) {
if (s == null) {
return null;
}
final Matcher m = XML_DATETIME.matcher(s);
if (!m.matches()) {
return null;
}
try {
int year = Integer.parseInt(m.group(1));
int month = Integer.parseInt(m.group(2));
int day = Integer.parseInt(m.group(3));
int hour = Integer.parseInt(m.group(4));
int minute = Integer.parseInt(m.group(5));
int second = Integer.parseInt(m.group(6));
int millisecond = 0;
if (m.group(8) != null) {
millisecond = (new BigDecimal("0." + m.group(8))).multiply(BD1000).intValue();
}
TimeZone tz = GMT;
if (m.group(10) != null) {
tz = TimeZone.getTimeZone("GMT" + m.group(10));
}
final GregorianCalendar result = new GregorianCalendar();
result.clear();
result.setTimeZone(tz);
result.set(year, month - 1, day, hour, minute, second);
result.set(Calendar.MILLISECOND, millisecond);
return result;
} catch (NumberFormatException e) {
return null;
}
}
/**
* Returns a xsd:dateTime string.
*/
public static String formatXmlDateTime(long millis) {
final GregorianCalendar cal = new GregorianCalendar(GMT);
cal.setTimeInMillis(millis);
return formatXmlDateTime(cal);
}
/**
* Returns a xsd:dateTime string.
*/
public static String formatXmlDateTime(GregorianCalendar cal) {
if (cal == null) {
throw new IllegalArgumentException();
}
final StringBuilder sb = new StringBuilder();
add4d(sb, cal.get(Calendar.YEAR));
sb.append('-');
add2d(sb, cal.get(Calendar.MONTH) + 1);
sb.append('-');
add2d(sb, cal.get(Calendar.DAY_OF_MONTH));
sb.append('T');
add2d(sb, cal.get(Calendar.HOUR_OF_DAY));
sb.append(':');
add2d(sb, cal.get(Calendar.MINUTE));
sb.append(':');
add2d(sb, cal.get(Calendar.SECOND));
int ms = cal.get(Calendar.MILLISECOND);
if (ms > 0) {
sb.append('.');
add3d(sb, ms);
while (sb.charAt(sb.length() - 1) == '0') {
sb.deleteCharAt(sb.length() - 1);
}
}
int tz = cal.getTimeZone().getOffset(cal.getTimeInMillis());
if (tz == 0) {
sb.append('Z');
} else {
if (tz > 0) {
sb.append('+');
} else {
sb.append('-');
tz *= -1;
}
add2d(sb, tz / 3600000);
sb.append(':');
int tzm = tz % 3600000;
add2d(sb, tzm == 0 ? 0 : tzm / 60000);
}
return sb.toString();
}
/**
* Parses a HTTP date.
*/
public static Date parseHttpDateTime(String s) {
if (s == null) {
return null;
}
s = s.trim();
if (s.length() > 1 && s.charAt(0) == '\'' && s.endsWith("'")) {
s = s.substring(1, s.length() - 1);
}
final GregorianCalendar cal = new GregorianCalendar(GMT);
cal.set(Calendar.MILLISECOND, 0);
Matcher m = null;
m = HTTP_DATETIME1.matcher(s);
if (m.matches()) {
final Integer month = MONTHS_MAP.get(m.group(2));
if (month == null) {
return null;
}
cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(m.group(1)));
cal.set(Calendar.MONTH, month);
cal.set(Calendar.YEAR, Integer.parseInt(m.group(3)));
cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(m.group(4)));
cal.set(Calendar.MINUTE, Integer.parseInt(m.group(5)));
cal.set(Calendar.SECOND, Integer.parseInt(m.group(6)));
return cal.getTime();
}
m = HTTP_DATETIME2.matcher(s);
if (m.matches()) {
final Integer month = MONTHS_MAP.get(m.group(2));
if (month == null) {
return null;
}
cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(m.group(1)));
cal.set(Calendar.MONTH, month);
int year = Integer.parseInt(m.group(3));
if (year < 100) {
final int thisYear = (new GregorianCalendar(GMT)).get(Calendar.YEAR);
final int testYear = year + thisYear - thisYear % 100;
year = (testYear < thisYear + 20 ? testYear : testYear - 100);
}
cal.set(Calendar.YEAR, year);
cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(m.group(4)));
cal.set(Calendar.MINUTE, Integer.parseInt(m.group(5)));
cal.set(Calendar.SECOND, Integer.parseInt(m.group(6)));
return cal.getTime();
}
m = HTTP_DATETIME3.matcher(s);
if (m.matches()) {
final Integer month = MONTHS_MAP.get(m.group(1));
if (month == null) {
return null;
}
cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(m.group(2).trim()));
cal.set(Calendar.MONTH, month);
cal.set(Calendar.YEAR, Integer.parseInt(m.group(6)));
cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(m.group(3)));
cal.set(Calendar.MINUTE, Integer.parseInt(m.group(4)));
cal.set(Calendar.SECOND, Integer.parseInt(m.group(5)));
return cal.getTime();
}
return null;
}
/**
* Returns a HTTP date.
*/
public static String formatHttpDateTime(long millis) {
final GregorianCalendar cal = new GregorianCalendar(GMT);
cal.setTimeInMillis(millis);
final StringBuilder sb = new StringBuilder();
sb.append(WDAYS[cal.get(Calendar.DAY_OF_WEEK) - 1]);
sb.append(", ");
add2d(sb, cal.get(Calendar.DAY_OF_MONTH));
sb.append(' ');
sb.append(MONTHS[cal.get(Calendar.MONTH)]);
sb.append(' ');
add4d(sb, cal.get(Calendar.YEAR));
sb.append(' ');
add2d(sb, cal.get(Calendar.HOUR_OF_DAY));
sb.append(':');
add2d(sb, cal.get(Calendar.MINUTE));
sb.append(':');
add2d(sb, cal.get(Calendar.SECOND));
sb.append(" GMT");
return sb.toString();
}
/**
* Returns a HTTP date.
*/
public static String formatHttpDateTime(final Date date) {
return formatHttpDateTime(date.getTime());
}
/**
* Returns a HTTP date.
*/
public static String formatHttpDateTime(final GregorianCalendar cal) {
return formatHttpDateTime(cal.getTimeInMillis());
}
private static void add2d(final StringBuilder sb, int value) {
assert sb != null;
assert value >= 0;
if (value < 10) {
sb.append('0');
}
sb.append(value);
}
private static void add3d(final StringBuilder sb, int value) {
assert sb != null;
assert value >= 0;
if (value < 10) {
sb.append('0');
}
if (value < 100) {
sb.append('0');
}
sb.append(value);
}
private static void add4d(final StringBuilder sb, int value) {
assert sb != null;
assert value >= 0;
if (value < 10) {
sb.append('0');
}
if (value < 100) {
sb.append('0');
}
if (value < 1000) {
sb.append('0');
}
sb.append(value);
}
}