/*
* Copyright (c) 2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.carbon.humantask.core.utils;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
/**
* ISO 8601 date parsing utility. Most date parsing libraries only apply one pattern but
* can't be used to parse ISO 8601 that are a set a pattern (mostly elements can be omitted
* like time of just seconds).
*/
public final class ISO8601DateParser {
private ISO8601DateParser() {
}
public static Date parse(String date) throws java.text.ParseException {
String pattern;
StringBuilder buffer = new StringBuilder(date.trim());
boolean timezoned = false;
switch (buffer.length()) {
case 4:
// Year: yyyy (eg 1997)
pattern = "yyyy";
break;
case 7:
// Year and month: yyyy-MM (eg 1997-07)
pattern = "yyyy-MM";
break;
case 10:
// Complete date: yyyy-MM-dd (eg 1997-07-16)
pattern = "yyyy-MM-dd";
break;
default:
// Complete date plus hours and minutes: yyyy-MM-ddTHH:mmTZD (eg 1997-07-16T19:20+01:00)
// Complete date plus hours, minutes and seconds: yyyy-MM-ddTHH:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
// Complete date plus hours, minutes, seconds and a decimal fraction of a second: yyyy-MM-ddTHH:mm:ss.STZD (eg 1997-07-16T19:20:30.45+01:00)
pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS";
if (buffer.length() == 16) {
// add seconds
buffer.append(":00");
}
if (buffer.length() > 16 && buffer.charAt(16) != ':') {
// insert seconds
buffer.insert(16, ":00");
}
if (buffer.length() == 19) {
// add milliseconds
buffer.append(".000");
}
if (buffer.length() > 19 && buffer.charAt(19) != '.') {
// insert milliseconds
buffer.insert(19, ".000");
}
if (buffer.charAt(19) == '.' && (buffer.length() < 22 ||
(buffer.lastIndexOf("-") < 23 && buffer.lastIndexOf("-") > 19) ||
(buffer.lastIndexOf("+") < 23 && buffer.lastIndexOf("+") > 0))) {
buffer.insert(20, "0");
}
if (buffer.charAt(19) == '.' && (buffer.length() < 22 ||
(buffer.lastIndexOf("-") < 23 && buffer.lastIndexOf("-") > 19) ||
(buffer.lastIndexOf("+") < 23 && buffer.lastIndexOf("+") > 0))) {
buffer.insert(20, "0");
}
if (buffer.length() > 23) {
// append timezone
pattern = pattern + "Z";
timezoned = true;
}
if (buffer.length() == 24 && buffer.charAt(23) == 'Z') {
// replace 'Z' with '+0000'
buffer.replace(23, 24, "+0000");
}
if (buffer.length() == 29 && buffer.charAt(26) == ':') {
// delete '.' from 'HH:mm'
buffer.deleteCharAt(26);
}
}
// always set time zone on formatter
SimpleDateFormat format = new SimpleDateFormat(pattern);
if (timezoned) {
format.setTimeZone(TimeZone.getTimeZone("UTC"));
}
return format.parse(buffer.toString());
}
public static Calendar parseCal(String date) throws java.text.ParseException {
Date d = parse(date);
Calendar cal = Calendar.getInstance();
cal.setTime(d);
return cal;
}
public static String format(Date date) {
TimeZone timeZone = TimeZone.getDefault();
boolean utc = TimeZone.getTimeZone("UTC").equals(timeZone) ||
TimeZone.getTimeZone("GMT").equals(timeZone);
String pattern = utc ? "yyyy-MM-dd'T'HH:mm:ss'Z'" : "yyyy-MM-dd'T'HH:mm:ssZ";
SimpleDateFormat format = new SimpleDateFormat(pattern);
format.setTimeZone(timeZone);
StringBuilder buffer = new StringBuilder(format.format(date));
if (!utc) {
buffer.insert(buffer.length() - 2, ':');
}
return buffer.toString();
}
}