/*
Copyright (C) 2000-2010  Ministere de la culture et de la communication (France), AJLSM
See LICENCE file
 */
package fr.gouv.culture.sdx.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 * Utility methods for handling dates in SDX.
 */
public class Date {

    /** Formats a date as "yyyy/mm/dd hh:mm:ss".
     *
     * @param date The date to format.
     * @return The formatted date.
     */
    public static String formatDate(java.util.Date date) {
        // return formatDate(date, "yyyy/MM/dd HH:mm:ss");
        return formatUtcISO8601Date(date);
    }

    public static String formatUtcISO8601Date(java.util.Date date) {
        return formatDate(date, "yyyy-MM-dd'T'HH:mm:ss") + "Z";
    }

    public static String formatUtcISO8601Date() {
        return formatUtcISO8601Date(new java.util.Date());
    }

    public static java.util.Date getUtcIso8601Date() {
        return getUtcIso8601Date(new java.util.Date());
    }

    public static java.util.Date getUtcIso8601Date(java.util.Date date) {
        GregorianCalendar cal = new GregorianCalendar();
        java.util.Date theDate = null;
        int offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
        // Convert to UTC
        theDate = new java.util.Date(date.getTime() - offset);
        return theDate;
    }

    /** Formats a date according to the specified format.
     *
     * @param date The date to format.
     * @param format The desired format.
     * @return The formated date.
     */
    public static String formatDate(java.util.Date date, String format) {
        //TODO : next method would return null for an invalid date ?! -pb
        if (date == null || format == null) return "";

        SimpleDateFormat df = new SimpleDateFormat(format);
        try {
            return df.format(date);
        } catch (Exception e) {
            return "";
        }
    }

    /**	Parse a date formated according the ISO-8601 format : yyyy-MM-dd'T'HH:mm:ss
     *
     * @param str	The date as a String.
     * @return		The date as a Date or <CODE>NULL</CODE> if the string can't be parsed as a date.
     */
    public static java.util.Date parseUtcISO8601Date(String str) {
        if (!Utilities.checkString(str)) return null;
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        df.setLenient(false);
        try {
            return df.parse(str);
        } catch (ParseException e) {
            return null;
        }
    }

    /**	Parse a date formated according the ISO-8601 format : yyyy-MM-dd'T'HH:mm:ss or yyyy-MM-dd
     *
     * @param str	The date as a String.
     * return		The date as a Date or <CODE>NULL</CODE> if the string can't be parsed as a date.
     */
    public static java.util.Date parseUtcISO8601DateDayOrSecond(String str) {
        if (!Utilities.checkString(str)) return null;
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        df.setLenient(false);
        try {
            return df.parse(str);
        } catch (ParseException e1) {
            try {
                df = new SimpleDateFormat("yyyy-MM-dd");
                df.setLenient(false);
                return df.parse(str);
            } catch (ParseException e2) {
                return null;
            }
        }
    }

    /** Parses a string as a date.
     *
     * Several formats are available. The following ones will be checked
     * in that order :
     * 	<PRE>
     * 		yyyy/mm/dd hh:mm:ss
     * 		yyyy-mm-dd hh:mm:ss
     * 		yyyy/mm/dd hh:mm
     * 		yyyy-mm-dd hh:mm
     * 		yyyy/mm/dd hh
     * 		yyyy-mm-dd hh
     * 		yyyy/mm/dd
     * 		yyyy-mm-dd
     * 		yyyy/mm
     * 		yyyy-mm
     * 		yyyy
     * 	</PRE>
     * @param str The string to parse.
     * @return A date, or <CODE>null</CODE> if the string can't be parsed as a date.
     */
    public static java.util.Date parseDate(String str) {
        if (!Utilities.checkString(str)) return null;
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
//      SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

        try {
            return df.parse(str);
        } catch (ParseException ef) {
            df.applyPattern("yyyy-MM-dd'T'HH:mm:ss");
            try {
                return df.parse(str);
            } catch (ParseException e) {
                df.applyPattern("yyyy/MM/dd HH:mm:ss");
                try {
                    return df.parse(str);
                } catch (ParseException ee) {
                    df.applyPattern("yyyy-MM-dd HH:mm");
                    try {
                        return df.parse(str);
                    } catch (ParseException eee) {
                        df.applyPattern("yyyy/MM/dd HH:mm");
                        try {
                            return df.parse(str);
                        } catch (ParseException eeee) {
                            df.applyPattern("yyyy-MM-dd HH:mm");
                            try {
                                return df.parse(str);
                            } catch (ParseException eeeee) {
                                df.applyPattern("yyyy/MM/dd HH");
                                try {
                                    return df.parse(str);
                                } catch (ParseException eeeeee) {
                                    df.applyPattern("yyyy-MM-dd HH");
                                    try {
                                        return df.parse(str);
                                    } catch (ParseException eeeeeee) {
                                        df.applyPattern("yyyy/MM/dd");
                                        try {
                                            return df.parse(str);
                                        } catch (ParseException eeeeeeee) {
                                            df.applyPattern("yyyy-MM-dd");
                                            try {
                                                return df.parse(str);
                                            } catch (ParseException eeeeeeeee) {
                                                df.applyPattern("yyyy/MM");
                                                try {
                                                    return df.parse(str);
                                                } catch (ParseException eeeeeeeeee) {
                                                    df.applyPattern("yyyy-MM");
                                                    try {
                                                        return df.parse(str);
                                                    } catch (ParseException eeeeeeeeeeee) {
                                                        df.applyPattern("yyyy");
                                                        try {
                                                            return df.parse(str);
                                                        } catch (ParseException eeeeeeeeeeeee) {
                                                            return null;
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }


}
