001 /****************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one *
003 * or more contributor license agreements. See the NOTICE file *
004 * distributed with this work for additional information *
005 * regarding copyright ownership. The ASF licenses this file *
006 * to you under the Apache License, Version 2.0 (the *
007 * "License"); you may not use this file except in compliance *
008 * with the License. You may obtain a copy of the License at *
009 * *
010 * http://www.apache.org/licenses/LICENSE-2.0 *
011 * *
012 * Unless required by applicable law or agreed to in writing, *
013 * software distributed under the License is distributed on an *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015 * KIND, either express or implied. See the License for the *
016 * specific language governing permissions and limitations *
017 * under the License. *
018 ****************************************************************/
019
020
021 package org.apache.mailet.base;
022
023 import java.text.ParseException;
024 import java.util.Date;
025 import java.util.Locale;
026 import java.util.TimeZone;
027
028 /**
029 * A thread-safe date formatting class to produce dates formatted in accord with the
030 * specifications of RFC 977.
031 *
032 */
033 public class RFC977DateFormat implements SimplifiedDateFormat {
034
035 /**
036 * Internal date formatter for long date formats
037 */
038 private final SynchronizedDateFormat internalLongDateFormat;
039
040 /**
041 * Internal date formatter for short date formats
042 */
043 private final SynchronizedDateFormat internalShortDateFormat;
044
045 /**
046 * Constructor for RFC977DateFormat
047 */
048 public RFC977DateFormat() {
049 internalLongDateFormat = new SynchronizedDateFormat("yyyyMMdd HHmmss", Locale.ENGLISH);
050 internalShortDateFormat = new SynchronizedDateFormat("yyMMdd HHmmss", Locale.ENGLISH);
051 }
052
053 /**
054 * This method returns the long form of the RFC977 Date
055 *
056 * @return java.lang.String
057 * @param d Date
058 */
059 public String format(Date d) {
060 return internalLongDateFormat.format(d);
061 }
062
063 /**
064 * Parses text from the beginning of the given string to produce a date.
065 * The method may not use the entire text of the given string.
066 * <p>
067 * This method is designed to be thread safe, so we wrap our delegated
068 * parse method in an appropriate synchronized block.
069 *
070 * @param source A <code>String</code> whose beginning should be parsed.
071 * @return A <code>Date</code> parsed from the string.
072 * @throws ParseException if the beginning of the specified string
073 * cannot be parsed.
074 */
075 public Date parse(String source) throws ParseException {
076 source = source.trim();
077 if (source.indexOf(' ') == 6) {
078 return internalShortDateFormat.parse(source);
079 } else {
080 return internalLongDateFormat.parse(source);
081 }
082 }
083
084 /**
085 * Sets the time zone of this SynchronizedDateFormat object.
086 * @param zone the given new time zone.
087 */
088 public void setTimeZone(TimeZone zone) {
089 synchronized(this) {
090 internalShortDateFormat.setTimeZone(zone);
091 internalLongDateFormat.setTimeZone(zone);
092 }
093 }
094
095 /**
096 * Gets the time zone.
097 * @return the time zone associated with this SynchronizedDateFormat.
098 */
099 public TimeZone getTimeZone() {
100 synchronized(this) {
101 return internalShortDateFormat.getTimeZone();
102 }
103 }
104
105 /**
106 * Specify whether or not date/time parsing is to be lenient. With
107 * lenient parsing, the parser may use heuristics to interpret inputs that
108 * do not precisely match this object's format. With strict parsing,
109 * inputs must match this object's format.
110 * @param lenient when true, parsing is lenient
111 * @see java.util.Calendar#setLenient
112 */
113 public void setLenient(boolean lenient)
114 {
115 synchronized(this) {
116 internalShortDateFormat.setLenient(lenient);
117 internalLongDateFormat.setLenient(lenient);
118 }
119 }
120
121 /**
122 * Tell whether date/time parsing is to be lenient.
123 * @return whether this SynchronizedDateFormat is lenient.
124 */
125 public boolean isLenient()
126 {
127 synchronized(this) {
128 return internalShortDateFormat.isLenient();
129 }
130 }
131
132
133 /**
134 * Overrides equals
135 */
136 public boolean equals(Object obj) {
137 if (this == obj) {
138 return true;
139 }
140 if (!(obj instanceof RFC977DateFormat)) {
141 return false;
142 }
143 RFC977DateFormat theOtherRFC977DateFormat = (RFC977DateFormat)obj;
144 synchronized (this) {
145 return ((internalShortDateFormat.equals(theOtherRFC977DateFormat.internalShortDateFormat)) &&
146 (internalLongDateFormat.equals(theOtherRFC977DateFormat.internalLongDateFormat)));
147 }
148 }
149
150 /**
151 * Overrides hashCode
152 */
153 public int hashCode() {
154 return internalLongDateFormat.hashCode() & internalShortDateFormat.hashCode();
155 }
156
157 }