blob: 396727b077922603a41ed1eacbba7b62e63eb093 [file] [log] [blame]
Nils Diewaldf399a672013-11-18 17:55:22 +00001package de.ids_mannheim.korap.util;
2
3import java.util.*;
4import java.util.regex.*;
Akron46b63fd2019-02-25 14:15:07 +01005import java.time.LocalDate;
Nils Diewaldf399a672013-11-18 17:55:22 +00006
7/**
Nils Diewaldc383ed02015-02-26 21:35:22 +00008 * KrillDate implements a helper object to stringify
Nils Diewaldfe6a3652015-02-05 20:34:27 +00009 * and parse date strings optimized
10 * for integer range queries in Lucene.
11 * No support for b.c. dates.
Nils Diewaldbb33da22015-03-04 16:24:25 +000012 *
13 * Strings are parsed and serialized to {@link http
14 * ://tools.ietf.org/html/rfc3339 RFC3339} compatible strings with a
15 * day granularity according to {@link http
16 * ://www.w3.org/TR/NOTE-datetime W3-DateTimes}.
17 *
Nils Diewaldfe6a3652015-02-05 20:34:27 +000018 * <blockquote><pre>
Nils Diewaldbb33da22015-03-04 16:24:25 +000019 * KrillDate kd = new KrillDate("2005-06-03");
20 * System.err.println(kd.day());
21 * // 3
22 *
23 * kd = new KrillDate("2005-06");
24 * System.err.println(kd.month());
25 * // 6
Nils Diewaldfe6a3652015-02-05 20:34:27 +000026 * </pre></blockquote>
Nils Diewaldbb33da22015-03-04 16:24:25 +000027 *
Nils Diewaldfe6a3652015-02-05 20:34:27 +000028 * @author diewald
Nils Diewaldf399a672013-11-18 17:55:22 +000029 */
Nils Diewaldc383ed02015-02-26 21:35:22 +000030public class KrillDate {
Nils Diewaldf399a672013-11-18 17:55:22 +000031
Nils Diewaldfe6a3652015-02-05 20:34:27 +000032 /**
33 * The year of the date.
34 */
35 public int year = 0;
Nils Diewaldf399a672013-11-18 17:55:22 +000036
Nils Diewaldfe6a3652015-02-05 20:34:27 +000037
38 /**
39 * The month of the date.
40 */
41 public int month = 0;
42
43
44 /**
45 * The day of the date.
46 */
47 public int day = 0;
48
49
50 // Date string regex pattern
Nils Diewaldbb33da22015-03-04 16:24:25 +000051 private static final Pattern datePattern = Pattern
52 .compile("\\s*(\\d\\d\\d\\d)" + "(?:\\s*[-/]?\\s*(\\d\\d)"
53 + "(?:\\s*[-/]?\\s*(\\d\\d))?)?\\s*");
Nils Diewaldf399a672013-11-18 17:55:22 +000054
Nils Diewaldfe6a3652015-02-05 20:34:27 +000055 /**
56 * Static value representing the minimum date.
57 */
58 public static final int BEGINNING = 0;
Nils Diewaldf399a672013-11-18 17:55:22 +000059
Nils Diewaldf399a672013-11-18 17:55:22 +000060
Nils Diewaldfe6a3652015-02-05 20:34:27 +000061 /**
62 * Static value representing the maximum date.
63 */
64 public static final int END = 99_999_999;
65
66
67 /**
Nils Diewaldc383ed02015-02-26 21:35:22 +000068 * Construct a new KrillDate object.
Nils Diewaldfe6a3652015-02-05 20:34:27 +000069 */
Nils Diewaldbb33da22015-03-04 16:24:25 +000070 public KrillDate () {};
Nils Diewaldfe6a3652015-02-05 20:34:27 +000071
72
73 /**
Nils Diewaldc383ed02015-02-26 21:35:22 +000074 * Construct a new KrillDate object.
Nils Diewaldbb33da22015-03-04 16:24:25 +000075 *
76 * @param date
77 * The date as a string (see synopsis).
Nils Diewaldfe6a3652015-02-05 20:34:27 +000078 */
Nils Diewaldc383ed02015-02-26 21:35:22 +000079 public KrillDate (String date) {
Nils Diewaldfe6a3652015-02-05 20:34:27 +000080 if (date == null || date.isEmpty())
81 return;
82
83 // Use pattern to split string
84 Matcher m = datePattern.matcher(date);
85 if (m.matches()) {
86 this.year = Integer.parseInt(m.group(1));
87 if (m.group(2) != null)
88 this.month = Integer.parseInt(m.group(2));
89 if (m.group(3) != null)
Nils Diewaldbb33da22015-03-04 16:24:25 +000090 this.day = Integer.parseInt(m.group(3));
Nils Diewaldfe6a3652015-02-05 20:34:27 +000091 };
Nils Diewaldf399a672013-11-18 17:55:22 +000092 };
93
Nils Diewaldf399a672013-11-18 17:55:22 +000094
Nils Diewaldfe6a3652015-02-05 20:34:27 +000095 /**
Akron46b63fd2019-02-25 14:15:07 +010096 * Construct a new KrillDate object.
97 *
98 * @param date
99 * The date as a Date object.
100 */
101 public KrillDate (LocalDate date) {
102 if (date == null)
103 return;
104
105 this.year = date.getYear();
106 this.month = date.getMonthValue();
107 this.day = date.getDayOfMonth();
108 };
109
110
111 /**
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000112 * Get the date as an integer with ceiled values for
113 * undefined date segments.
Nils Diewaldbb33da22015-03-04 16:24:25 +0000114 *
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000115 * <blockquote><pre>
Nils Diewaldbb33da22015-03-04 16:24:25 +0000116 * KrillDate kd = new KrillDate("2005-06");
117 * System.err.println(kd.ceil());
118 * // 20050699
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000119 * </pre></blockquote>
Nils Diewaldbb33da22015-03-04 16:24:25 +0000120 *
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000121 * @return ceiled integer value.
122 */
Nils Diewaldf399a672013-11-18 17:55:22 +0000123 public int ceil () {
Nils Diewaldbb33da22015-03-04 16:24:25 +0000124 return (ceil((byte) 4, this.year) * 10_000)
125 + (ceil((byte) 2, this.month) * 100)
126 + (ceil((byte) 2, this.day));
Nils Diewaldf399a672013-11-18 17:55:22 +0000127 };
128
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000129
130 /**
131 * Get the date as an integer with floored values for
132 * undefined date segments.
Nils Diewaldbb33da22015-03-04 16:24:25 +0000133 *
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000134 * <blockquote><pre>
Nils Diewaldbb33da22015-03-04 16:24:25 +0000135 * KrillDate kd = new KrillDate("2005-06");
136 * System.err.println(kd.floor());
137 * // 20050600
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000138 * </pre></blockquote>
Nils Diewaldbb33da22015-03-04 16:24:25 +0000139 *
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000140 * @return floored integer value.
141 */
Nils Diewaldf399a672013-11-18 17:55:22 +0000142 public int floor () {
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000143 int floor = 0;
144 if (this.year == 0)
145 return 0;
146
147 floor = this.year * 10_000;
148
149 if (this.month == 0)
150 return floor;
151
152 floor += this.month * 100;
153
154 if (this.day == 0)
155 return floor;
156
157 return (floor + this.day);
Nils Diewaldf399a672013-11-18 17:55:22 +0000158 };
159
160
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000161 /**
162 * Serialize date to string, appended by zeros,
163 * in the form of &quot;20050300&quot;.
Nils Diewaldbb33da22015-03-04 16:24:25 +0000164 *
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000165 * @return The date as a string.
166 */
Nils Diewaldbb33da22015-03-04 16:24:25 +0000167 public String toString () {
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000168 StringBuilder sb = this.toStringBuilder();
169 if (sb.length() < 4)
170 return null;
Nils Diewaldf399a672013-11-18 17:55:22 +0000171
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000172 if (sb.length() < 8) {
173 sb.append("00");
174 if (sb.length() < 8) {
175 sb.append("00");
176 };
177 };
Nils Diewaldf399a672013-11-18 17:55:22 +0000178
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000179 return sb.toString();
Nils Diewaldf399a672013-11-18 17:55:22 +0000180 };
181
Nils Diewaldf399a672013-11-18 17:55:22 +0000182
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000183 /**
Akron4376e742019-01-16 15:02:30 +0100184 * Return the date as an integer
185 * based on the stringification.
186 *
187 * @return The date as an integer.
188 */
189 public int toInteger () throws NumberFormatException {
190 return Integer.parseInt(this.toString());
191 };
192
193 /**
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000194 * Serialize ceiled date to string.
Nils Diewaldbb33da22015-03-04 16:24:25 +0000195 *
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000196 * @return The date as a string.
197 */
Nils Diewaldbb33da22015-03-04 16:24:25 +0000198 public String toCeilString () {
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000199 StringBuilder sb = new StringBuilder();
200 return sb.append(this.ceil()).toString();
Nils Diewaldf399a672013-11-18 17:55:22 +0000201 };
202
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000203
204 /**
205 * Serialize floored date to string.
Nils Diewaldbb33da22015-03-04 16:24:25 +0000206 *
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000207 * @return The date as a string.
208 */
Nils Diewaldbb33da22015-03-04 16:24:25 +0000209 public String toFloorString () {
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000210 StringBuilder sb = new StringBuilder();
211 return sb.append(this.floor()).toString();
Nils Diewaldf399a672013-11-18 17:55:22 +0000212 };
213
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000214
215 /**
216 * Serialize date to displayable string.
217 * See format description in the class description.
Nils Diewaldbb33da22015-03-04 16:24:25 +0000218 *
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000219 * @return The date as a string.
220 */
Nils Diewaldbb33da22015-03-04 16:24:25 +0000221 public String toDisplay () {
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000222 StringBuilder sb = this.toStringBuilder();
223 if (sb.length() == 8)
224 sb.insert(6, '-');
225
226 if (sb.length() > 4)
227 sb.insert(4, '-');
228
229 return sb.toString();
230 };
231
232
233
Nils Diewaldf399a672013-11-18 17:55:22 +0000234 // Format date as yyyymmdd
235 private StringBuilder toStringBuilder () {
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000236 StringBuilder sb = new StringBuilder();
Nils Diewaldf399a672013-11-18 17:55:22 +0000237
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000238 if (this.year != 0) {
Nils Diewaldf399a672013-11-18 17:55:22 +0000239
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000240 // Append year
241 if (this.year < 100)
242 sb.append("20");
243
244 sb.append(this.year);
Nils Diewaldbb33da22015-03-04 16:24:25 +0000245
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000246 if (this.month != 0) {
Nils Diewaldbb33da22015-03-04 16:24:25 +0000247
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000248 // Append month
249 if (this.month < 10)
250 sb.append('0');
Nils Diewaldf399a672013-11-18 17:55:22 +0000251
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000252 sb.append(this.month);
Nils Diewaldf399a672013-11-18 17:55:22 +0000253
Nils Diewaldfe6a3652015-02-05 20:34:27 +0000254 if (this.day != 0) {
255 // Append month
256 if (this.day < 10)
257 sb.append('0');
258
259 sb.append(this.day);
260 };
261 };
262 };
263 return sb;
264 };
265
266
267 // Ceil method
268 private static int ceil (byte padding, int nr) {
269 if (nr == 0) {
270 if (padding == (byte) 4)
271 return 9999;
272 else if (padding == (byte) 2)
273 return 99;
274 };
275 return nr;
Nils Diewaldf399a672013-11-18 17:55:22 +0000276 };
277};