001/*
002 * (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Stephane Lacoin
016 */
017package org.nuxeo.apidoc.introspection;
018
019import java.text.ParseException;
020import java.text.SimpleDateFormat;
021import java.util.Calendar;
022import java.util.Date;
023import java.util.TimeZone;
024import java.util.regex.Matcher;
025import java.util.regex.Pattern;
026
027/**
028 * Contains code from Abdera to format dates.
029 */
030public class DateTimeFormat {
031
032    /**
033     * Create the serialized string form from a java.util.Date
034     */
035    public static String format(Date date) {
036        return abderaFormat(date);
037    }
038
039    /**
040     * Parse the serialized string form into a java.util.Date
041     *
042     * @param value The serialized string form of the date
043     * @return The created java.util.Date
044     */
045    public static Date parse(String value) {
046        SimpleDateFormat formatter = new SimpleDateFormat(value.endsWith("Z") ? "yyyyMMdd'T'hhmmss'Z'"
047                : "yyyyMMdd'T'hhmmssZ");
048        try {
049            return formatter.parse(value);
050        } catch (ParseException e) {
051            return abderaParse(value);
052        }
053    }
054
055    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}))?");
056
057    public static String abderaFormat(Date date) {
058        StringBuilder sb = new StringBuilder();
059        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
060        c.setTime(date);
061        sb.append(c.get(Calendar.YEAR));
062        sb.append('-');
063        int f = c.get(Calendar.MONTH);
064        if (f < 9) {
065            sb.append('0');
066        }
067        sb.append(f + 1);
068        sb.append('-');
069        f = c.get(Calendar.DATE);
070        if (f < 10) {
071            sb.append('0');
072        }
073        sb.append(f);
074        sb.append('T');
075        f = c.get(Calendar.HOUR_OF_DAY);
076        if (f < 10) {
077            sb.append('0');
078        }
079        sb.append(f);
080        sb.append(':');
081        f = c.get(Calendar.MINUTE);
082        if (f < 10) {
083            sb.append('0');
084        }
085        sb.append(f);
086        sb.append(':');
087        f = c.get(Calendar.SECOND);
088        if (f < 10) {
089            sb.append('0');
090        }
091        sb.append(f);
092        sb.append('.');
093        f = c.get(Calendar.MILLISECOND);
094        if (f < 100) {
095            sb.append('0');
096        }
097        if (f < 10) {
098            sb.append('0');
099        }
100        sb.append(f);
101        sb.append('Z');
102        return sb.toString();
103    }
104
105    public static Date abderaParse(String value) {
106        Matcher m = PATTERN.matcher(value);
107        if (m.find()) {
108            Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
109            int hoff = 0, moff = 0, doff = -1;
110            if (m.group(9) != null) {
111                doff = m.group(9).equals("-") ? 1 : -1;
112                hoff = doff * (m.group(10) != null ? Integer.parseInt(m.group(10)) : 0);
113                moff = doff * (m.group(11) != null ? Integer.parseInt(m.group(11)) : 0);
114            }
115            c.set(Calendar.YEAR, Integer.parseInt(m.group(1)));
116            c.set(Calendar.MONTH, m.group(2) != null ? Integer.parseInt(m.group(2)) - 1 : 0);
117            c.set(Calendar.DATE, m.group(3) != null ? Integer.parseInt(m.group(3)) : 1);
118            c.set(Calendar.HOUR_OF_DAY, m.group(4) != null ? Integer.parseInt(m.group(4)) + hoff : 0);
119            c.set(Calendar.MINUTE, m.group(5) != null ? Integer.parseInt(m.group(5)) + moff : 0);
120            c.set(Calendar.SECOND, m.group(6) != null ? Integer.parseInt(m.group(6)) : 0);
121            c.set(Calendar.MILLISECOND, m.group(7) != null ? Integer.parseInt(m.group(7)) : 0);
122            return c.getTime();
123        } else {
124            throw new IllegalArgumentException("Invalid Date Format");
125        }
126    }
127
128}