| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 1 | package de.ids_mannheim.korap.util; |
| 2 | |||||
| 3 | import java.util.*; | ||||
| 4 | import java.util.regex.*; | ||||
| Akron | 46b63fd | 2019-02-25 14:15:07 +0100 | [diff] [blame] | 5 | import java.time.LocalDate; |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 6 | |
| 7 | /** | ||||
| Nils Diewald | c383ed0 | 2015-02-26 21:35:22 +0000 | [diff] [blame] | 8 | * KrillDate implements a helper object to stringify |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 9 | * and parse date strings optimized |
| 10 | * for integer range queries in Lucene. | ||||
| 11 | * No support for b.c. dates. | ||||
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 12 | * |
| 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 Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 18 | * <blockquote><pre> |
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 19 | * 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 Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 26 | * </pre></blockquote> |
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 27 | * |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 28 | * @author diewald |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 29 | */ |
| Nils Diewald | c383ed0 | 2015-02-26 21:35:22 +0000 | [diff] [blame] | 30 | public class KrillDate { |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 31 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 32 | /** |
| 33 | * The year of the date. | ||||
| 34 | */ | ||||
| 35 | public int year = 0; | ||||
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 36 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 37 | |
| 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 Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 51 | private static final Pattern datePattern = Pattern |
| 52 | .compile("\\s*(\\d\\d\\d\\d)" + "(?:\\s*[-/]?\\s*(\\d\\d)" | ||||
| 53 | + "(?:\\s*[-/]?\\s*(\\d\\d))?)?\\s*"); | ||||
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 54 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 55 | /** |
| 56 | * Static value representing the minimum date. | ||||
| 57 | */ | ||||
| 58 | public static final int BEGINNING = 0; | ||||
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 59 | |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 60 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 61 | /** |
| 62 | * Static value representing the maximum date. | ||||
| 63 | */ | ||||
| 64 | public static final int END = 99_999_999; | ||||
| 65 | |||||
| 66 | |||||
| 67 | /** | ||||
| Nils Diewald | c383ed0 | 2015-02-26 21:35:22 +0000 | [diff] [blame] | 68 | * Construct a new KrillDate object. |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 69 | */ |
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 70 | public KrillDate () {}; |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 71 | |
| 72 | |||||
| 73 | /** | ||||
| Nils Diewald | c383ed0 | 2015-02-26 21:35:22 +0000 | [diff] [blame] | 74 | * Construct a new KrillDate object. |
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 75 | * |
| 76 | * @param date | ||||
| 77 | * The date as a string (see synopsis). | ||||
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 78 | */ |
| Nils Diewald | c383ed0 | 2015-02-26 21:35:22 +0000 | [diff] [blame] | 79 | public KrillDate (String date) { |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 80 | 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 Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 90 | this.day = Integer.parseInt(m.group(3)); |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 91 | }; |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 92 | }; |
| 93 | |||||
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 94 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 95 | /** |
| Akron | 46b63fd | 2019-02-25 14:15:07 +0100 | [diff] [blame] | 96 | * 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 Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 112 | * Get the date as an integer with ceiled values for |
| 113 | * undefined date segments. | ||||
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 114 | * |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 115 | * <blockquote><pre> |
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 116 | * KrillDate kd = new KrillDate("2005-06"); |
| 117 | * System.err.println(kd.ceil()); | ||||
| 118 | * // 20050699 | ||||
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 119 | * </pre></blockquote> |
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 120 | * |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 121 | * @return ceiled integer value. |
| 122 | */ | ||||
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 123 | public int ceil () { |
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 124 | return (ceil((byte) 4, this.year) * 10_000) |
| 125 | + (ceil((byte) 2, this.month) * 100) | ||||
| 126 | + (ceil((byte) 2, this.day)); | ||||
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 127 | }; |
| 128 | |||||
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 129 | |
| 130 | /** | ||||
| 131 | * Get the date as an integer with floored values for | ||||
| 132 | * undefined date segments. | ||||
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 133 | * |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 134 | * <blockquote><pre> |
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 135 | * KrillDate kd = new KrillDate("2005-06"); |
| 136 | * System.err.println(kd.floor()); | ||||
| 137 | * // 20050600 | ||||
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 138 | * </pre></blockquote> |
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 139 | * |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 140 | * @return floored integer value. |
| 141 | */ | ||||
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 142 | public int floor () { |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 143 | 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 Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 158 | }; |
| 159 | |||||
| 160 | |||||
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 161 | /** |
| 162 | * Serialize date to string, appended by zeros, | ||||
| 163 | * in the form of "20050300". | ||||
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 164 | * |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 165 | * @return The date as a string. |
| 166 | */ | ||||
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 167 | public String toString () { |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 168 | StringBuilder sb = this.toStringBuilder(); |
| 169 | if (sb.length() < 4) | ||||
| 170 | return null; | ||||
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 171 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 172 | if (sb.length() < 8) { |
| 173 | sb.append("00"); | ||||
| 174 | if (sb.length() < 8) { | ||||
| 175 | sb.append("00"); | ||||
| 176 | }; | ||||
| 177 | }; | ||||
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 178 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 179 | return sb.toString(); |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 180 | }; |
| 181 | |||||
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 182 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 183 | /** |
| Akron | 4376e74 | 2019-01-16 15:02:30 +0100 | [diff] [blame] | 184 | * 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 Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 194 | * Serialize ceiled date to string. |
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 195 | * |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 196 | * @return The date as a string. |
| 197 | */ | ||||
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 198 | public String toCeilString () { |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 199 | StringBuilder sb = new StringBuilder(); |
| 200 | return sb.append(this.ceil()).toString(); | ||||
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 201 | }; |
| 202 | |||||
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 203 | |
| 204 | /** | ||||
| 205 | * Serialize floored date to string. | ||||
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 206 | * |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 207 | * @return The date as a string. |
| 208 | */ | ||||
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 209 | public String toFloorString () { |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 210 | StringBuilder sb = new StringBuilder(); |
| 211 | return sb.append(this.floor()).toString(); | ||||
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 212 | }; |
| 213 | |||||
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 214 | |
| 215 | /** | ||||
| 216 | * Serialize date to displayable string. | ||||
| 217 | * See format description in the class description. | ||||
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 218 | * |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 219 | * @return The date as a string. |
| 220 | */ | ||||
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 221 | public String toDisplay () { |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 222 | 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 Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 234 | // Format date as yyyymmdd |
| 235 | private StringBuilder toStringBuilder () { | ||||
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 236 | StringBuilder sb = new StringBuilder(); |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 237 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 238 | if (this.year != 0) { |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 239 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 240 | // Append year |
| 241 | if (this.year < 100) | ||||
| 242 | sb.append("20"); | ||||
| 243 | |||||
| 244 | sb.append(this.year); | ||||
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 245 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 246 | if (this.month != 0) { |
| Nils Diewald | bb33da2 | 2015-03-04 16:24:25 +0000 | [diff] [blame] | 247 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 248 | // Append month |
| 249 | if (this.month < 10) | ||||
| 250 | sb.append('0'); | ||||
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 251 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 252 | sb.append(this.month); |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 253 | |
| Nils Diewald | fe6a365 | 2015-02-05 20:34:27 +0000 | [diff] [blame] | 254 | 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 Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 276 | }; |
| 277 | }; | ||||