001/*
002 * (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Stephane Lacoin
018 */
019package org.nuxeo.apidoc.introspection;
020
021import java.text.ParseException;
022import java.text.SimpleDateFormat;
023import java.util.Calendar;
024import java.util.Date;
025import java.util.TimeZone;
026import java.util.regex.Matcher;
027import java.util.regex.Pattern;
028
029/**
030 * Contains code from Abdera to format dates.
031 */
032public class DateTimeFormat {
033
034    /**
035     * Create the serialized string form from a java.util.Date
036     */
037    public static String format(Date date) {
038        return abderaFormat(date);
039    }
040
041    /**
042     * Parse the serialized string form into a java.util.Date
043     *
044     * @param value The serialized string form of the date
045     * @return The created java.util.Date
046     */
047    public static Date parse(String value) {
048        SimpleDateFormat formatter = new SimpleDateFormat(value.endsWith("Z") ? "yyyyMMdd'T'hhmmss'Z'"
049                : "yyyyMMdd'T'hhmmssZ");
050        try {
051            return formatter.parse(value);
052        } catch (ParseException e) {
053            return abderaParse(value);
054        }
055    }
056
057    private static final Pattern PATTERN = Pattern.compile("(\\d{4})(?:-(\\d{2}))?(?:-(\\d{2}))?(?:[Tt](?:(\\d{2}))?(?::(\\d{2}))?(?::(\\d{2}))?(?:\\.(\\d{3}))?)?([Zz])?(?:([+-])(\\d{2}):(\\d{2}))?");
058
059    public static String abderaFormat(Date date) {
060        StringBuilder sb = new StringBuilder();
061        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
062        c.setTime(date);
063        sb.append(c.get(Calendar.YEAR));
064        sb.append('-');
065        int f = c.get(Calendar.MONTH);
066        if (f < 9) {
067            sb.append('0');
068        }
069        sb.append(f + 1);
070        sb.append('-');
071        f = c.get(Calendar.DATE);
072        if (f < 10) {
073            sb.append('0');
074        }
075        sb.append(f);
076        sb.append('T');
077        f = c.get(Calendar.HOUR_OF_DAY);
078        if (f < 10) {
079            sb.append('0');
080        }
081        sb.append(f);
082        sb.append(':');
083        f = c.get(Calendar.MINUTE);
084        if (f < 10) {
085            sb.append('0');
086        }
087        sb.append(f);
088        sb.append(':');
089        f = c.get(Calendar.SECOND);
090        if (f < 10) {
091            sb.append('0');
092        }
093        sb.append(f);
094        sb.append('.');
095        f = c.get(Calendar.MILLISECOND);
096        if (f < 100) {
097            sb.append('0');
098        }
099        if (f < 10) {
100            sb.append('0');
101        }
102        sb.append(f);
103        sb.append('Z');
104        return sb.toString();
105    }
106
107    public static Date abderaParse(String value) {
108        Matcher m = PATTERN.matcher(value);
109        if (m.find()) {
110            Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
111            int hoff = 0, moff = 0, doff = -1;
112            if (m.group(9) != null) {
113                doff = m.group(9).equals("-") ? 1 : -1;
114                hoff = doff * (m.group(10) != null ? Integer.parseInt(m.group(10)) : 0);
115                moff = doff * (m.group(11) != null ? Integer.parseInt(m.group(11)) : 0);
116            }
117            c.set(Calendar.YEAR, Integer.parseInt(m.group(1)));
118            c.set(Calendar.MONTH, m.group(2) != null ? Integer.parseInt(m.group(2)) - 1 : 0);
119            c.set(Calendar.DATE, m.group(3) != null ? Integer.parseInt(m.group(3)) : 1);
120            c.set(Calendar.HOUR_OF_DAY, m.group(4) != null ? Integer.parseInt(m.group(4)) + hoff : 0);
121            c.set(Calendar.MINUTE, m.group(5) != null ? Integer.parseInt(m.group(5)) + moff : 0);
122            c.set(Calendar.SECOND, m.group(6) != null ? Integer.parseInt(m.group(6)) : 0);
123            c.set(Calendar.MILLISECOND, m.group(7) != null ? Integer.parseInt(m.group(7)) : 0);
124            return c.getTime();
125        } else {
126            throw new IllegalArgumentException("Invalid Date Format");
127        }
128    }
129
130}