blob: 4baaa4fbf786d4cfac9a2cbf30b1d421cb9f6b3c [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.
*
* Authors:
* Florent Guillaume, Nuxeo
*/
package org.apache.chemistry.opencmis.server.support.query;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Helper dealing with conversion of {@link Calendar} to and from the string
* format specified by CMISQL.
*/
public final class CalendarHelper {
private static final Pattern CMISQL_PATTERN = Pattern.compile( //
"(\\d{4})-(\\d{2})-(\\d{2})[Tt]" + "(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?"
+ "(?:[Zz]|([+-]\\d{2}:\\d{2}))?");
private CalendarHelper() {
// utility class
}
/**
* Converts a CMISQL date string representation to a
* {@link GregorianCalendar}.
* <p>
* Parses {@code YYYY-HH-MMThh:mm:ss.sss+hh:mm}, or a {@code Z} for the
* timezone, and with {@code .sss} being optional.
*
* @param datetime
* the string representation in CMISQL format
* @return the created instance
*/
public static GregorianCalendar fromString(String datetime) {
Matcher m = CMISQL_PATTERN.matcher(datetime);
if (!m.matches()) {
throw new IllegalArgumentException("Invalid datetime format: " + datetime);
}
String tz = m.group(8);
GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"
+ (tz == null ? "" : tz)));
cal.set(Calendar.YEAR, Integer.parseInt(m.group(1)));
cal.set(Calendar.MONTH, Integer.parseInt(m.group(2)) - 1);
cal.set(Calendar.DATE, 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)));
String decimals = m.group(7);
int ms = decimals == null ? 0 : Integer.parseInt((decimals + "00").substring(0, 3));
cal.set(Calendar.MILLISECOND, ms);
return cal;
}
/**
* Converts a Calendar to its CMISQL string representation.
*
* @param cal
* a {@link Calendar}
* @return the CMISQL string representation
*/
public static String toString(Calendar cal) {
StringBuilder buf = new StringBuilder(28);
toString(cal, buf);
return buf.toString();
}
/**
* Converts a Calendar to its CMISQL string representation.
*
* @param cal
* a {@link Calendar}
* @param buf
* a buffer in which to add the CMISQL string representation
*/
public static void toString(Calendar cal, StringBuilder buf) {
buf.append(cal.get(Calendar.YEAR));
buf.append('-');
int f = cal.get(Calendar.MONTH);
if (f < 9) {
buf.append('0');
}
buf.append(f + 1);
buf.append('-');
f = cal.get(Calendar.DATE);
if (f < 10) {
buf.append('0');
}
buf.append(f);
buf.append('T');
f = cal.get(Calendar.HOUR_OF_DAY);
if (f < 10) {
buf.append('0');
}
buf.append(f);
buf.append(':');
f = cal.get(Calendar.MINUTE);
if (f < 10) {
buf.append('0');
}
buf.append(f);
buf.append(':');
f = cal.get(Calendar.SECOND);
if (f < 10) {
buf.append('0');
}
buf.append(f);
buf.append('.');
f = cal.get(Calendar.MILLISECOND);
if (f < 100) {
buf.append('0');
}
if (f < 10) {
buf.append('0');
}
buf.append(f);
int offset = cal.getTimeZone().getOffset(cal.getTimeInMillis()) / 60000;
if (offset == 0) {
buf.append('Z');
} else {
char sign;
if (offset < 0) {
offset = -offset;
sign = '-';
} else {
sign = '+';
}
buf.append(sign);
f = offset / 60;
if (f < 10) {
buf.append('0');
}
buf.append(f);
buf.append(':');
f = offset % 60;
if (f < 10) {
buf.append('0');
}
buf.append(f);
}
}
}