001package com.box.sdk;
002
003import java.text.DateFormat;
004import java.text.ParseException;
005import java.text.SimpleDateFormat;
006import java.util.Date;
007import java.util.TimeZone;
008
009/**
010 * Contains methods for parsing and formatting dates for use with the Box API.
011 */
012public final class BoxDateFormat {
013    private static final ThreadLocal<DateFormat> THREAD_LOCAL_DATE_FORMAT_SECONDS = ThreadLocal.withInitial(() -> {
014        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
015        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
016        return sdf;
017    });
018
019    private static final ThreadLocal<DateFormat> THREAD_LOCAL_DATE_FORMAT_MILLISECONDS = ThreadLocal.withInitial(() -> {
020        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
021        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
022        return sdf;
023    });
024
025    private static final ThreadLocal<DateFormat> THREAD_LOCAL_DATE_ONLY = ThreadLocal.withInitial(() -> {
026        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
027        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
028        return sdf;
029    });
030
031    private BoxDateFormat() {
032    }
033
034    /**
035     * Parses a date string returned by the Box API into a {@link Date} object.
036     *
037     * @param dateString a string containing the date.
038     * @return the parsed date.
039     * @throws ParseException if the string cannot be parsed into a valid date.
040     */
041    public static Date parse(String dateString) throws ParseException {
042        try {
043            return THREAD_LOCAL_DATE_FORMAT_SECONDS.get().parse(dateString);
044        } catch (ParseException pe) {
045            return THREAD_LOCAL_DATE_FORMAT_MILLISECONDS.get().parse(dateString);
046        }
047    }
048
049    /**
050     * Parses a date in format of yyyy-MM-dd.
051     *
052     * @param date date to parse.
053     * @return parsed date.
054     * @throws ParseException if the string cannot be parsed into a valid date.
055     */
056    public static Date parseDateOnly(String date) throws ParseException {
057        return THREAD_LOCAL_DATE_ONLY.get().parse(date);
058    }
059
060    /**
061     * Formats a date as a string that can be sent to the Box API.
062     *
063     * @param date the date to format.
064     * @return a string containing the formatted date.
065     */
066    public static String format(Date date) {
067        return THREAD_LOCAL_DATE_FORMAT_SECONDS.get().format(date);
068    }
069
070    /**
071     * Formats a date as a string yyyy-MM-dd that can be sent to the Box API.
072     *
073     * @param date the date to format.
074     * @return a yyyy-MM-dd string containing the formatted date.
075     */
076    public static String formatAsDateOnly(Date date) {
077        return THREAD_LOCAL_DATE_ONLY.get().format(date);
078    }
079}