001/* 002 * The MIT License 003 * Copyright (c) 2012 Microsoft Corporation 004 * 005 * Permission is hereby granted, free of charge, to any person obtaining a copy 006 * of this software and associated documentation files (the "Software"), to deal 007 * in the Software without restriction, including without limitation the rights 008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 009 * copies of the Software, and to permit persons to whom the Software is 010 * furnished to do so, subject to the following conditions: 011 * 012 * The above copyright notice and this permission notice shall be included in 013 * all copies or substantial portions of the Software. 014 * 015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 021 * THE SOFTWARE. 022 */ 023 024package microsoft.exchange.webservices.data.util; 025 026import org.apache.commons.lang3.StringUtils; 027import org.joda.time.format.DateTimeFormat; 028import org.joda.time.format.DateTimeFormatter; 029 030import java.util.Date; 031 032public final class DateTimeUtils { 033 034 private static final DateTimeFormatter[] DATE_TIME_FORMATS = createDateTimeFormats(); 035 private static final DateTimeFormatter[] DATE_FORMATS = createDateFormats(); 036 037 038 private DateTimeUtils() { 039 throw new UnsupportedOperationException(); 040 } 041 042 043 /** 044 * Converts a date time string to local date time. 045 * 046 * Note: this method also allows dates without times, in which case the time will be 00:00:00 in the 047 * supplied timezone. UTC timezone will be assumed if no timezone is supplied. 048 * 049 * @param value The string value to parse. 050 * @return The parsed {@link Date}. 051 * 052 * @throws java.lang.IllegalArgumentException If string can not be parsed. 053 */ 054 public static Date convertDateTimeStringToDate(String value) { 055 return parseInternal(value, false); 056 } 057 058 /** 059 * Converts a date string to local date time. 060 * 061 * UTC timezone will be assumed if no timezone is supplied. 062 * 063 * @param value The string value to parse. 064 * @return The parsed {@link Date}. 065 * 066 * @throws java.lang.IllegalArgumentException If string can not be parsed. 067 */ 068 public static Date convertDateStringToDate(String value) { 069 return parseInternal(value, true); 070 } 071 072 073 private static Date parseInternal(String value, boolean dateOnly) { 074 String originalValue = value; 075 076 if (StringUtils.isEmpty(value)) { 077 return null; 078 } else { 079 if (value.endsWith("z")) { 080 // This seems to be an edge case. Let's uppercase the Z to be sure. 081 value = value.substring(0, value.length() - 1) + "Z"; 082 } 083 084 final DateTimeFormatter[] formats = dateOnly ? DATE_FORMATS : DATE_TIME_FORMATS; 085 for (final DateTimeFormatter format : formats) { 086 try { 087 return format.parseDateTime(value).toDate(); 088 } catch (IllegalArgumentException e) { 089 // Ignore and try the next pattern. 090 } 091 } 092 } 093 094 throw new IllegalArgumentException( 095 String.format("Date String %s not in valid UTC/local format", originalValue)); 096 } 097 098 private static DateTimeFormatter[] createDateTimeFormats() { 099 return new DateTimeFormatter[] { 100 DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ").withZoneUTC(), 101 DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").withZoneUTC(), 102 DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSZ").withZoneUTC(), 103 DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss").withZoneUTC(), 104 DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS").withZoneUTC(), 105 DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSS").withZoneUTC(), 106 DateTimeFormat.forPattern("yyyy-MM-ddZ").withZoneUTC(), 107 DateTimeFormat.forPattern("yyyy-MM-dd").withZoneUTC() 108 }; 109 } 110 111 private static DateTimeFormatter[] createDateFormats() { 112 return new DateTimeFormatter[] { 113 DateTimeFormat.forPattern("yyyy-MM-ddZ").withZoneUTC(), 114 DateTimeFormat.forPattern("yyyy-MM-dd").withZoneUTC() 115 }; 116 } 117 118}