/* * 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.ode.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 class ISO8601DateParser { public static Date parse(String date) throws java.text.ParseException { String pattern; StringBuffer buffer = new StringBuffer(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); StringBuffer buffer = new StringBuffer(format.format(date)); if (!utc) { buffer.insert(buffer.length() - 2, ':'); } return buffer.toString(); } }