|
24 | 24 | import java.net.URL; |
25 | 25 | import java.nio.file.Path; |
26 | 26 | import java.nio.file.Paths; |
| 27 | +import java.time.LocalDate; |
| 28 | +import java.time.LocalDateTime; |
| 29 | +import java.time.LocalTime; |
| 30 | +import java.time.chrono.IsoChronology; |
| 31 | +import java.time.temporal.ChronoField; |
27 | 32 | import java.util.*; |
28 | 33 | import java.util.function.BiConsumer; |
29 | 34 | import java.util.jar.JarEntry; |
@@ -338,6 +343,123 @@ public static Optional<Long> parseLong(String s) { |
338 | 343 | } |
339 | 344 | } |
340 | 345 |
|
| 346 | + /** |
| 347 | + * 解析字符串为时间 |
| 348 | + */ |
| 349 | + public static Optional<LocalTime> parseTime(String s) { |
| 350 | + return parseTime(s, ':'); |
| 351 | + } |
| 352 | + |
| 353 | + /** |
| 354 | + * 解析字符串为时间 |
| 355 | + * @param splitter 各单位的分隔符,建议使用 <code>:</code> |
| 356 | + */ |
| 357 | + public static Optional<LocalTime> parseTime(String s, char splitter) { |
| 358 | + List<String> split = CollectionUtils.split(s, splitter, 3); |
| 359 | + if (split.size() == 2) { |
| 360 | + int hour = Util.parseInt(split.get(0)).orElse(-1); |
| 361 | + int minute = Util.parseInt(split.get(1)).orElse(-1); |
| 362 | + if (ChronoField.HOUR_OF_DAY.range().isValidValue(hour) |
| 363 | + && ChronoField.MINUTE_OF_HOUR.range().isValidValue(minute) |
| 364 | + ) { |
| 365 | + return Optional.of(LocalTime.of(hour, minute)); |
| 366 | + } |
| 367 | + } |
| 368 | + if (split.size() == 3) { |
| 369 | + int hour = Util.parseInt(split.get(0)).orElse(-1); |
| 370 | + int minute = Util.parseInt(split.get(1)).orElse(-1); |
| 371 | + int second = Util.parseInt(split.get(2)).orElse(-1); |
| 372 | + if (ChronoField.HOUR_OF_DAY.range().isValidValue(hour) |
| 373 | + && ChronoField.MINUTE_OF_HOUR.range().isValidValue(minute) |
| 374 | + && ChronoField.SECOND_OF_MINUTE.range().isValidValue(second) |
| 375 | + ) { |
| 376 | + return Optional.of(LocalTime.of(hour, minute)); |
| 377 | + } |
| 378 | + } |
| 379 | + return Optional.empty(); |
| 380 | + } |
| 381 | + |
| 382 | + /** |
| 383 | + * 解析字符串为日期 |
| 384 | + */ |
| 385 | + public static Optional<LocalDate> parseDate(String s) { |
| 386 | + return parseDate(s, '-'); |
| 387 | + } |
| 388 | + |
| 389 | + /** |
| 390 | + * 解析字符串为日期 |
| 391 | + * @param splitter 各单位的分隔符,建议使用 <code>-</code> |
| 392 | + */ |
| 393 | + public static Optional<LocalDate> parseDate(String s, char splitter) { |
| 394 | + List<String> split = CollectionUtils.split(s, splitter, 3); |
| 395 | + if (split.size() == 3) { |
| 396 | + int year = Util.parseInt(split.get(0)).orElse(-1); |
| 397 | + int month = Util.parseInt(split.get(1)).orElse(-1); |
| 398 | + int dayOfMonth = Util.parseInt(split.get(2)).orElse(-1); |
| 399 | + if (ChronoField.YEAR_OF_ERA.range().isValidValue(year) |
| 400 | + && ChronoField.MONTH_OF_YEAR.range().isValidValue(month) |
| 401 | + && ChronoField.DAY_OF_MONTH.range().isValidValue(dayOfMonth) |
| 402 | + ) { |
| 403 | + int dom; |
| 404 | + switch (month) { |
| 405 | + case 2: |
| 406 | + dom = (IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28); |
| 407 | + break; |
| 408 | + case 4: |
| 409 | + case 6: |
| 410 | + case 9: |
| 411 | + case 11: |
| 412 | + dom = 30; |
| 413 | + break; |
| 414 | + default: |
| 415 | + dom = 31; |
| 416 | + break; |
| 417 | + } |
| 418 | + if (dom <= dayOfMonth) { |
| 419 | + return Optional.of(LocalDate.of(year, month, dayOfMonth)); |
| 420 | + } |
| 421 | + } |
| 422 | + } |
| 423 | + return Optional.empty(); |
| 424 | + } |
| 425 | + |
| 426 | + /** |
| 427 | + * 解析字符串为日期与时间 |
| 428 | + */ |
| 429 | + public static Optional<LocalDateTime> parseDateTime(String s) { |
| 430 | + return parseDateTime(s, ' '); |
| 431 | + } |
| 432 | + |
| 433 | + /** |
| 434 | + * 解析字符串为日期与时间 |
| 435 | + * @param splitter 日期与时间之间的分隔符,建议使用 <code> </code> (空格) |
| 436 | + */ |
| 437 | + public static Optional<LocalDateTime> parseDateTime(String s, char splitter) { |
| 438 | + return parseDateTime(s, splitter, '-', ':'); |
| 439 | + } |
| 440 | + |
| 441 | + /** |
| 442 | + * 解析字符串为日期与时间 |
| 443 | + * @param splitter 日期与时间之间的分隔符,建议使用 <code> </code> (空格) |
| 444 | + * @param dateSplitter 日期各单位的分隔符 |
| 445 | + * @param timeSplitter 时间各单位的分隔符 |
| 446 | + * @see Util#parseDate(String, char) |
| 447 | + * @see Util#parseTime(String, char) |
| 448 | + */ |
| 449 | + public static Optional<LocalDateTime> parseDateTime(String s, char splitter, char dateSplitter, char timeSplitter) { |
| 450 | + int index = s.indexOf(splitter); |
| 451 | + if (index > 5) { |
| 452 | + String dateStr = s.substring(0, index); |
| 453 | + String timeStr = s.substring(index + 1); |
| 454 | + LocalDate date = parseDate(dateStr, dateSplitter).orElse(null); |
| 455 | + LocalTime time = parseTime(timeStr, timeSplitter).orElse(null); |
| 456 | + if (date != null && time != null) { |
| 457 | + return Optional.of(date.atTime(time)); |
| 458 | + } |
| 459 | + } |
| 460 | + return Optional.empty(); |
| 461 | + } |
| 462 | + |
341 | 463 | /** |
342 | 464 | * 通过 enum values 或者 Bukkit Registry 读取值 |
343 | 465 | * @param type 类型 |
|
0 commit comments