package com.srbenoit.util;

import java.util.Calendar;

/**
 * A thread-safe singleton class to perform calendar operations. This is needed as the <code>
 * Calendar</code> class is not thread safe.
 */
public final class SharedCalendar {

    /** the calendar */
    private final static Calendar CAL;

    static {
        CAL = Calendar.getInstance();
    }

    /**
     * Private constructor to enforce singleton model.
     */
    private SharedCalendar() {

        // No action
    }

    /**
     * Gets the year of a particular timestamp.
     *
     * @param   millis  the timestamp in milliseconds
     * @return  the year
     */
    public static int yearOf(final long millis) {

        return get(Calendar.YEAR, millis);
    }

    /**
     * Gets the month of a particular timestamp.
     *
     * @param   millis  the timestamp in milliseconds
     * @return  the month
     */
    public static int monthOf(final long millis) {

        return get(Calendar.MONTH, millis) + 1;
    }

    /**
     * Gets the day of the month of a particular timestamp.
     *
     * @param   millis  the timestamp in milliseconds
     * @return  the day of the month
     */
    public static int dayOfMonthOf(final long millis) {

        return get(Calendar.DAY_OF_MONTH, millis);
    }

    /**
     * Gets the day of the year of a particular timestamp.
     *
     * @param   millis  the timestamp in milliseconds
     * @return  the day of the week
     */
    public static int dayOfYearOf(final long millis) {

        return get(Calendar.DAY_OF_YEAR, millis);
    }

    /**
     * Gets the day of the week of a particular timestamp.
     *
     * @param   millis  the timestamp in milliseconds
     * @return  the day of the week
     */
    public static int dayOfWeekOf(final long millis) {

        return get(Calendar.DAY_OF_WEEK, millis);
    }

    /**
     * Gets the hour of the day of a particular timestamp.
     *
     * @param   millis  the timestamp in milliseconds
     * @return  the hour of the day
     */
    public static int hourOfDayOf(final long millis) {

        return get(Calendar.HOUR_OF_DAY, millis);
    }

    /**
     * Gets the hour of a particular timestamp.
     *
     * @param   millis  the timestamp in milliseconds
     * @return  the hour (0-11)
     */
    public static int hourOf(final long millis) {

        return get(Calendar.HOUR, millis);
    }

    /**
     * Gets the minute of a particular timestamp.
     *
     * @param   millis  the timestamp in milliseconds
     * @return  the minute
     */
    public static int minuteOf(final long millis) {

        return get(Calendar.MINUTE, millis);
    }

    /**
     * Gets the second of a particular timestamp.
     *
     * @param   millis  the timestamp in milliseconds
     * @return  the second
     */
    public static int secondOf(final long millis) {

        return get(Calendar.SECOND, millis);
    }

    /**
     * Gets the millisecond of a particular timestamp.
     *
     * @param   millis  the timestamp in milliseconds
     * @return  the millisecond
     */
    public static int millisecondOf(final long millis) {

        return get(Calendar.MILLISECOND, millis);
    }

    /**
     * Gets a particular calendar field for a particular timestamp.
     *
     * @param   field   the calendar field to get
     * @param   millis  the timestamp in milliseconds
     * @return  the value of that field
     */
    private static int get(final int field, final long millis) {

        synchronized (CAL) {
            CAL.setTimeInMillis(millis);

            return CAL.get(field);
        }
    }
}
