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