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
045     *            The serialized string form of the date
046     * @return The created java.util.Date
047     */
048    public static Date parse(String value) {
049        SimpleDateFormat formatter = new SimpleDateFormat(value.endsWith("Z") ? "yyyyMMdd'T'hhmmss'Z'"
050                : "yyyyMMdd'T'hhmmssZ");
051        try {
052            return formatter.parse(value);
053        } catch (ParseException e) {
054            return abderaParse(value);
055        }
056    }
057
058    private static final Pattern PATTERN = Pattern.compile(
059            "(\\d{4})(?:-(\\d{2}))?(?:-(\\d{2}))?(?:[Tt](?:(\\d{2}))?(?::(\\d{2}))?(?::(\\d{2}))?(?:\\.(\\d{3}))?)?([Zz])?(?:([+-])(\\d{2}):(\\d{2}))?");
060
061    public static String abderaFormat(Date date) {
062        StringBuilder sb = new StringBuilder();
063        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
064        c.setTime(date);
065        sb.append(c.get(Calendar.YEAR));
066        sb.append('-');
067        int f = c.get(Calendar.MONTH);
068        if (f < 9) {
069            sb.append('0');
070        }
071        sb.append(f + 1);
072        sb.append('-');
073        f = c.get(Calendar.DATE);
074        if (f < 10) {
075            sb.append('0');
076        }
077        sb.append(f);
078        sb.append('T');
079        f = c.get(Calendar.HOUR_OF_DAY);
080        if (f < 10) {
081            sb.append('0');
082        }
083        sb.append(f);
084        sb.append(':');
085        f = c.get(Calendar.MINUTE);
086        if (f < 10) {
087            sb.append('0');
088        }
089        sb.append(f);
090        sb.append(':');
091        f = c.get(Calendar.SECOND);
092        if (f < 10) {
093            sb.append('0');
094        }
095        sb.append(f);
096        sb.append('.');
097        f = c.get(Calendar.MILLISECOND);
098        if (f < 100) {
099            sb.append('0');
100        }
101        if (f < 10) {
102            sb.append('0');
103        }
104        sb.append(f);
105        sb.append('Z');
106        return sb.toString();
107    }
108
109    public static Date abderaParse(String value) {
110        Matcher m = PATTERN.matcher(value);
111        if (m.find()) {
112            Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
113            int hoff = 0, moff = 0, doff = -1;
114            if (m.group(9) != null) {
115                doff = m.group(9).equals("-") ? 1 : -1;
116                hoff = doff * (m.group(10) != null ? Integer.parseInt(m.group(10)) : 0);
117                moff = doff * (m.group(11) != null ? Integer.parseInt(m.group(11)) : 0);
118            }
119            c.set(Calendar.YEAR, Integer.parseInt(m.group(1)));
120            c.set(Calendar.MONTH, m.group(2) != null ? Integer.parseInt(m.group(2)) - 1 : 0);
121            c.set(Calendar.DATE, m.group(3) != null ? Integer.parseInt(m.group(3)) : 1);
122            c.set(Calendar.HOUR_OF_DAY, m.group(4) != null ? Integer.parseInt(m.group(4)) + hoff : 0);
123            c.set(Calendar.MINUTE, m.group(5) != null ? Integer.parseInt(m.group(5)) + moff : 0);
124            c.set(Calendar.SECOND, m.group(6) != null ? Integer.parseInt(m.group(6)) : 0);
125            c.set(Calendar.MILLISECOND, m.group(7) != null ? Integer.parseInt(m.group(7)) : 0);
126            return c.getTime();
127        } else {
128            throw new IllegalArgumentException("Invalid Date Format");
129        }
130    }
131
132}