001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyrighted [year] [name of copyright owner]". 013 * 014 * Copyright © 2011-2015 ForgeRock AS. All rights reserved. 015 */ 016package org.forgerock.audit.util; 017 018import java.util.Date; 019 020import org.joda.time.Chronology; 021import org.joda.time.DateTime; 022import org.joda.time.DateTimeZone; 023import org.joda.time.chrono.ISOChronology; 024import org.joda.time.format.DateTimeFormatter; 025import org.joda.time.format.ISODateTimeFormat; 026 027/** 028 * Manages timestamp strings in ISO8601 format. 029 * <p> 030 * <b>Example:</b> <br> 031 * 2011-09-09T14:58:17.6+02:00 <br> 032 * 2011-09-09T14:58:17.65+02:00 <br> 033 * 2011-09-09T14:58:17.654+02:00 <br> 034 * 2011-09-09T14:58:17.654Z 035 */ 036public final class DateUtil { 037 private Chronology chrono; 038 039 /** 040 * Fetches a DateUtil that is set in the default timezone. 041 * 042 * @return DateUtil set in the default timezone 043 */ 044 public static DateUtil getDateUtil() { 045 return new DateUtil(); 046 } 047 048 /** 049 * Returns a DateUtil using a specified timezone. 050 * 051 * @param zone 052 * string representation of a timezone i.e. "UTC" or "Asia/Tokyo" 053 * @return DateUtil set with the supplied timezone 054 */ 055 public static DateUtil getDateUtil(final String zone) { 056 return new DateUtil(zone); 057 } 058 059 /** 060 * Creates a DateUtil using a specified timezone. 061 * 062 * @param zone 063 * DateTimeZone object 064 * @return DateUtil set with the supplied timezone 065 */ 066 public static DateUtil getDateUtil(final DateTimeZone zone) { 067 return new DateUtil(zone); 068 } 069 070 /** 071 * Creates a DateUtil using the default timezone and generates ISO8601 072 * timestamps. 073 */ 074 private DateUtil() { 075 this(DateTimeZone.getDefault()); 076 } 077 078 /** 079 * Creates a DateUtil using a specified timezone and generates ISO8601 080 * timestamps. 081 * 082 * @param zone 083 * string representation of a timezone. i.e. "UTC" or 084 * "Asia/Tokyo" 085 */ 086 private DateUtil(final String zone) { 087 this(DateTimeZone.forID(zone)); 088 } 089 090 /** 091 * Creates a DateUtil using a specified timezone and generates ISO8601 092 * timestamps. 093 * 094 * @param zone 095 * timezone object 096 */ 097 private DateUtil(final DateTimeZone zone) { 098 chrono = ISOChronology.getInstance(zone); 099 } 100 101 /** 102 * Generate a formatted timestamp for the current time. 103 * 104 * @return String containing a timestamp 105 */ 106 public String now() { 107 return new DateTime(chrono).toString(); 108 } 109 110 /** 111 * Get current time. 112 * @return get current time as a DateTime object 113 */ 114 public DateTime currentDateTime() { 115 return new DateTime(chrono); 116 } 117 118 /** 119 * Formats a given DateTime into a timestamp. 120 * 121 * @param date 122 * DateTime object to convert 123 * @return String containing the formatted timestamp 124 */ 125 public String formatDateTime(final DateTime date) { 126 return date.withChronology(chrono).toString(); 127 } 128 129 /** 130 * Formats a given date into a timestamp. 131 * 132 * @param date 133 * date object to convert 134 * @return String containing the formatted timestamp 135 */ 136 public String formatDateTime(final Date date) { 137 final DateTime dt = new DateTime(date, chrono); 138 return dt.toString(); 139 } 140 141 /** 142 * Formats a given timestamp into a ISO8601 timestamp. 143 * 144 * @param timestamp 145 * the timestamp to convert 146 * @return String containing the formatted timestamp 147 */ 148 public String formatDateTime(final long timestamp) { 149 final DateTime dt = new DateTime(timestamp, chrono); 150 return dt.toString(); 151 } 152 153 /** 154 * Parses an ISO8601 compliant timestamp into a DateTime object. 155 * 156 * @param timestamp 157 * timestamp to parse 158 * @return DateTime using the zone and chronology indicated by the timestamp 159 */ 160 public DateTime parseTimestamp(final String timestamp) { 161 final DateTimeFormatter parser = ISODateTimeFormat.dateTime(); 162 return parser.withOffsetParsed().parseDateTime(timestamp); 163 } 164 165 /** 166 * Parses an ISO8601 compliant timestamp into a DateTime object. 167 * 168 * Checks the length of the timestamp and returns null if the string is not 169 * ISO8601 compliant Accepted formats: 170 * 171 * <pre> 172 * yyyy-MM-ddTHH:mm:ss.SSSZ, 173 * yyyy-MM-ddTHH:mm:ss.SSS+00, 174 * yyyy-MM-ddTHH:mm:ss.SSS+00:00 175 * </pre> 176 * 177 * @param timestamp 178 * timestamp to parse 179 * @return the timestamp as a DateTime object 180 */ 181 public DateTime parseIfDate(final String timestamp) { 182 DateTime d = null; 183 if (timestamp.length() > 23 && timestamp.length() < 30) { 184 try { 185 d = parseTimestamp(timestamp); 186 } catch (IllegalArgumentException e) { 187 /* ignore */ 188 } 189 } 190 return d; 191 } 192 193 /** 194 * return the number of days between the two dates. 195 * 196 * @param start 197 * Start date 198 * @param end 199 * End date 200 * @param includeDay 201 * include both Days (increase the result with one) 202 * @return number of days 203 */ 204 public static int getDateDifferenceInDays(final Date start, final Date end, final Boolean includeDay) { 205 Integer result = null; 206 if (start != null && end != null) { 207 final Long l = 86400000L; 208 final Long r = (end.getTime() - start.getTime()) / l; 209 result = r.intValue(); 210 if (includeDay) { 211 result++; 212 } 213 } 214 return result; 215 } 216} 217