001package fr.aumgn.bukkitutils.util; 002 003import java.util.regex.Matcher; 004import java.util.regex.Pattern; 005 006/** 007 * Time parser extracted from CommandBook 008 * Credits go to sk89q and contributors. 009 */ 010public final class TimeUtil { 011 012 protected static final Pattern TWELVE_HOUR_TIME = 013 Pattern.compile("^([0-9]+(?::[0-9]+)?)([apmAPM\\.]+)$"); 014 015 public static class UnknownTimeFormatException extends Exception { 016 private static final long serialVersionUID = -3382490815044549013L; 017 018 private final String time; 019 020 public UnknownTimeFormatException(String time) { 021 super("Unrecognized format \"" + time + "\"."); 022 this.time = time; 023 } 024 025 public String getTime() { 026 return time; 027 } 028 } 029 030 public static class UnknownTimePeriodException extends Exception { 031 private static final long serialVersionUID = -1749578413958028355L; 032 033 private final String period; 034 035 public UnknownTimePeriodException(String period) { 036 super("'am' or 'pm' expected, got '" + period + "'."); 037 this.period = period; 038 } 039 040 public String getPeriod() { 041 return period; 042 } 043 } 044 045 /** 046 * Parse a time string 047 * Accepted format are: 048 * <ul> 049 * <li>0 to 24 numbers for hour</li> 050 * <li>Numbers above 24 for ticks</li> 051 * <li>hh:mm (24h format)</li> 052 * <li>hh:mm{am,pm,a.m.,p.m.} (12h format)</li> 053 * <li> 054 * shortcuts : 055 * <ul> 056 * <li>dawn</li> 057 * <li>sunrise</li> 058 * <li>morning</li> 059 * <li>day</li> 060 * <li>midday</li> 061 * <li>noon</li> 062 * <li>afternoon</li> 063 * <li>evening</li> 064 * <li>sunset</li> 065 * <li>dusk</li> 066 * <li>night</li> 067 * <li>midnight</li> 068 * </ul> 069 * </li> 070 * </ul> 071 */ 072 public static int parseTime(String timeStr) 073 throws UnknownTimeFormatException, UnknownTimePeriodException { 074 Matcher matcher; 075 076 try { 077 int time = Integer.parseInt(timeStr); 078 079 // People tend to enter just a number of the hour 080 if (time <= 24) { 081 return ((time - 8) % 24) * 1000; 082 } 083 084 return time; 085 } catch (NumberFormatException _) { 086 // Not an integer! 087 } 088 089 // Tick time 090 if (timeStr.matches("^*[0-9]+$")) { 091 return Integer.parseInt(timeStr.substring(1)); 092 093 // Allow 24-hour time 094 } else if (timeStr.matches("^[0-9]+:[0-9]+$")) { 095 String[] parts = timeStr.split(":"); 096 int hours = Integer.parseInt(parts[0]); 097 int mins = Integer.parseInt(parts[1]); 098 return (int) (((hours - 8) % 24) * 1000 099 + Math.round((mins % 60) / 60.0 * 1000)); 100 101 // Or perhaps 12-hour time 102 } else if ((matcher = TWELVE_HOUR_TIME.matcher(timeStr)).matches()) { 103 String time = matcher.group(1); 104 String period = matcher.group(2); 105 int shift; 106 107 if (period.equalsIgnoreCase("am") 108 || period.equalsIgnoreCase("a.m.")) { 109 shift = 0; 110 } else if (period.equalsIgnoreCase("pm") 111 || period.equalsIgnoreCase("p.m.")) { 112 shift = 12; 113 } else { 114 throw new UnknownTimePeriodException(period); 115 } 116 117 String[] parts = time.split(":"); 118 int hours = Integer.parseInt(parts[0]); 119 int mins = parts.length >= 2 ? Integer.parseInt(parts[1]) : 0; 120 return (int) ((((hours % 12) + shift - 8) % 24) * 1000 121 + (mins % 60) / 60.0 * 1000); 122 123 // Or some shortcuts 124 } else if (timeStr.equalsIgnoreCase("dawn")) { 125 return (6 - 8 + 24) * 1000; 126 } else if (timeStr.equalsIgnoreCase("sunrise")) { 127 return (7 - 8 + 24) * 1000; 128 } else if (timeStr.equalsIgnoreCase("morning")) { 129 return (24) * 1000; 130 } else if (timeStr.equalsIgnoreCase("day")) { 131 return (24) * 1000; 132 } else if (timeStr.equalsIgnoreCase("midday") 133 || timeStr.equalsIgnoreCase("noon")) { 134 return (12 - 8 + 24) * 1000; 135 } else if (timeStr.equalsIgnoreCase("afternoon")) { 136 return (14 - 8 + 24) * 1000; 137 } else if (timeStr.equalsIgnoreCase("evening")) { 138 return (16 - 8 + 24) * 1000; 139 } else if (timeStr.equalsIgnoreCase("sunset")) { 140 return (21 - 8 + 24) * 1000; 141 } else if (timeStr.equalsIgnoreCase("dusk")) { 142 return (21 - 8 + 24) * 1000 + (int) (30 / 60.0 * 1000); 143 } else if (timeStr.equalsIgnoreCase("night")) { 144 return (22 - 8 + 24) * 1000; 145 } else if (timeStr.equalsIgnoreCase("midnight")) { 146 return (0 - 8 + 24) * 1000; 147 } 148 149 throw new UnknownTimeFormatException(timeStr); 150 } 151 152 private TimeUtil() { 153 } 154}