Project

General

Profile

1
package eu.dnetlib.clients.index.model;
2

    
3
import java.text.DateFormat;
4
import java.text.ParseException;
5
import java.text.SimpleDateFormat;
6
import java.util.Date;
7
import java.util.TimeZone;
8
import java.util.regex.Pattern;
9

    
10
/**
11
 * helper class for formatting and parsing Values. all methods synchronize on the used local formatter object, so you
12
 * can use the shared instance. Using multiple instances may improve performance, though, because of less
13
 * synchronization.
14
 */
15
public class ValueFormatHelper {
16

    
17
	/**
18
	 * shared global helper instance.
19
	 */
20
	public static final ValueFormatHelper INSTANCE = new ValueFormatHelper();
21

    
22
	/**
23
	 * The max. length of strings to be parsed as date.
24
	 */
25
	private static final int DATE_LENGTH = 10;
26

    
27
	/**
28
	 * The length of strings to be parsed as date time for (default) pattern 1.
29
	 */
30
	private static final int DATE_TIME_LENGTH_PATTERN_DEFAULT = 28;
31

    
32
	/**
33
	 * The length of strings to be parsed as date time for pattern 2 and 3.
34
	 */
35
	private static final int DATE_TIME_LENGTH_PATTERN_2_AND_3 = 24;
36

    
37
	/**
38
	 * The length of strings to be parsed as date time for pattern 4.
39
	 */
40
	private static final int DATE_TIME_LENGTH_PATTERN_4 = 20;
41

    
42
	/**
43
	 * formatter to create and parse standard string representations of Date values: "yyyy-MM-dd".
44
	 */
45
	private final DateFormat _formatDate = new SimpleDateFormat("yyyy-MM-dd");
46

    
47
	/**
48
	 * valid Datetime value pattern with milliseconds and time zone (default for printing).
49
	 */
50
	private final DateFormat _formatDateTimePatternDefault = getDefaultDateTimeFormat();
51

    
52
	/**
53
	 * valid Datetime value pattern with time zone.
54
	 */
55
	private final DateFormat _formatDateTimePattern2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
56

    
57
	/**
58
	 * valid Datetime value pattern with milliseconds and time zone 'Z' (UTC).
59
	 */
60
	private final DateFormat _formatDateTimePattern3 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
61

    
62
	/**
63
	 * valid Datetime value pattern without milliseconds and time zone 'Z' (UTC).
64
	 */
65
	private final DateFormat _formatDateTimePattern4 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
66

    
67
	/**
68
	 * pattern for checking if the string might be a date.
69
	 */
70
	private final Pattern _formatPatternDateDefault = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
71

    
72
	/**
73
	 * pattern for checking if the string might be a date time for default pattern.
74
	 */
75
	private final Pattern _formatPatternTimeDefault = Pattern.compile("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}[+-]{1}\\d{4}");
76

    
77
	/**
78
	 * pattern for checking if the string might be a date time for pattern 2.
79
	 */
80
	private final Pattern _formatPatternTime2 = Pattern.compile("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}[+-]{1}\\d{4}");
81

    
82
	/**
83
	 * pattern for checking if the string might be a date time for pattern 3.
84
	 */
85
	private final Pattern _formatPatternTime3 = Pattern.compile("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z");
86

    
87
	/**
88
	 * pattern for checking if the string might be a date time for pattern 4.
89
	 */
90
	private final Pattern _formatPatternTime4 = Pattern.compile("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z");
91

    
92
	/**
93
	 * create local instance.
94
	 */
95
	public ValueFormatHelper() {
96
		_formatDate.setLenient(false);
97
		_formatDateTimePatternDefault.setLenient(false);
98
		_formatDateTimePattern2.setLenient(false);
99
		_formatDateTimePattern3.setLenient(false);
100
		_formatDateTimePattern3.setTimeZone(TimeZone.getTimeZone("UTC"));
101
		_formatDateTimePattern4.setLenient(false);
102
		_formatDateTimePattern4.setTimeZone(TimeZone.getTimeZone("UTC"));
103
	}
104

    
105
	/**
106
	 * @return the default format for datetime values.
107
	 */
108
	public static SimpleDateFormat getDefaultDateTimeFormat() {
109
		final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
110
		sdf.setLenient(false);
111
		return sdf;
112
	}
113

    
114
	/**
115
	 * format value as Date string.
116
	 *
117
	 * @param value a date value
118
	 * @return formatted date.
119
	 */
120
	public String formatDate(final Date value) {
121
		synchronized (_formatDate) {
122
			return _formatDate.format(value);
123
		}
124
	}
125

    
126
	/**
127
	 * format value as DateTime string.
128
	 *
129
	 * @param value a datetime value
130
	 * @return formatted datetime string
131
	 */
132
	public String formatDateTime(final Date value) {
133
		synchronized (_formatDateTimePatternDefault) {
134
			return _formatDateTimePatternDefault.format(value);
135
		}
136
	}
137

    
138
	/**
139
	 * parse a date string.
140
	 *
141
	 * @param dateString a date string
142
	 * @return parsed Date
143
	 * @throws ParseException string has wrong format
144
	 */
145
	public Date parseDate(final String dateString) throws ParseException {
146
		if (dateString.length() == DATE_LENGTH && _formatPatternDateDefault.matcher(dateString).matches()) {
147
			synchronized (_formatDate) {
148
				return _formatDate.parse(dateString);
149
			}
150
		} else {
151
			throw new ParseException("Length of date string '" + dateString + "' exceeds maximum date length of " + DATE_LENGTH, DATE_LENGTH);
152
		}
153
	}
154

    
155
	/**
156
	 * parse a date string.
157
	 *
158
	 * @param dateString a date string
159
	 * @return parsed Date if correct format, else null.
160
	 */
161
	public Date tryParseDate(final String dateString) {
162
		if (dateString.length() == DATE_LENGTH && _formatPatternDateDefault.matcher(dateString).matches()) {
163
			synchronized (_formatDate) {
164
				try {
165
					return _formatDate.parse(dateString);
166
				} catch (final ParseException ex) {
167
					; // not a date ... fine.
168
				}
169
			}
170
		}
171
		return null;
172
	}
173

    
174
	/**
175
	 * parse datetime string.
176
	 *
177
	 * @param dateTimeString a datetime string
178
	 * @return parsed Date
179
	 * @throws ParseException string has wrong format
180
	 */
181
	public Date parseDateTime(final String dateTimeString) throws ParseException {
182
		final Date result;
183
		final int dateLen = dateTimeString.length();
184
		if (dateLen == DATE_TIME_LENGTH_PATTERN_DEFAULT && _formatPatternTimeDefault.matcher(dateTimeString).matches()) {
185
			synchronized (_formatDateTimePatternDefault) {
186
				result = _formatDateTimePatternDefault.parse(dateTimeString);
187
			}
188
		} else if (dateLen == DATE_TIME_LENGTH_PATTERN_2_AND_3 && _formatPatternTime2.matcher(dateTimeString).matches()) {
189
			synchronized (_formatDateTimePattern2) {
190
				result = _formatDateTimePattern2.parse(dateTimeString);
191
			}
192
		} else if (dateLen == DATE_TIME_LENGTH_PATTERN_2_AND_3 && _formatPatternTime3.matcher(dateTimeString).matches()) {
193
			synchronized (_formatDateTimePattern3) {
194
				result = _formatDateTimePattern3.parse(dateTimeString);
195
			}
196
		} else if (dateLen == DATE_TIME_LENGTH_PATTERN_4 && _formatPatternTime4.matcher(dateTimeString).matches()) {
197
			synchronized (_formatDateTimePattern4) {
198
				result = _formatDateTimePattern4.parse(dateTimeString);
199
			}
200
		} else {
201
			throw new ParseException("Length '" + dateTimeString.length() + "' of datetime string '" + dateTimeString
202
					+ "' doesn't match expected pattern length", dateTimeString.length());
203
		}
204
		return result;
205
	}
206

    
207
	/**
208
	 * parse datetime string.
209
	 *
210
	 * @param dateTimeString a datetime string
211
	 * @return parsed Date if correct format, else null;
212
	 */
213
	public Date tryParseDateTime(final String dateTimeString) {
214
		Date result = null;
215
		try {
216
			switch (dateTimeString.length()) {
217
			case DATE_TIME_LENGTH_PATTERN_DEFAULT:
218
				if (_formatPatternTimeDefault.matcher(dateTimeString).matches()) {
219
					synchronized (_formatDateTimePatternDefault) {
220
						result = _formatDateTimePatternDefault.parse(dateTimeString);
221
					}
222
				}
223
				break;
224
			case DATE_TIME_LENGTH_PATTERN_2_AND_3:
225
				if (_formatPatternTime2.matcher(dateTimeString).matches()) {
226
					synchronized (_formatDateTimePattern2) {
227
						result = _formatDateTimePattern2.parse(dateTimeString);
228
					}
229
				} else if (_formatPatternTime3.matcher(dateTimeString).matches()) {
230
					synchronized (_formatDateTimePattern3) {
231
						result = _formatDateTimePattern3.parse(dateTimeString);
232
					}
233
				}
234
				break;
235
			case DATE_TIME_LENGTH_PATTERN_4:
236
				if (_formatPatternTime4.matcher(dateTimeString).matches()) {
237
					synchronized (_formatDateTimePattern4) {
238
						result = _formatDateTimePattern4.parse(dateTimeString);
239
					}
240
				}
241
				break;
242
			default:
243
				break;
244
			}
245
		} catch (final ParseException ex) {
246
			; // not a datetime ... fine.
247
		}
248
		return result;
249
	}
250
}
(8-8/8)