1 /*
2 * Copyright (C) 2020-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
3 */
4 package de.powerstat.validation.values;
5
6
7 import java.util.Objects;
8
9 import de.powerstat.validation.interfaces.IValueObject;
10
11
12 /**
13 * Hour.
14 *
15 * Not DSGVO relevant.
16 *
17 * TODO Listener
18 * TODO minutesWithin = 60
19 * TODO min, max
20 */
21 public final class Hour implements Comparable<Hour>, IValueObject
22 {
23 /**
24 * Overflow constant.
25 */
26 private static final String OVERFLOW = "Overflow"; //$NON-NLS-1$
27
28 /**
29 * Underflow contant.
30 */
31 private static final String UNDERFLOW = "Underflow"; //$NON-NLS-1$
32
33 /* *
34 * Cache for singletons.
35 */
36 // private static final Map<Integer, Hour> CACHE = new WeakHashMap<>();
37
38 /**
39 * Hour.
40 */
41 private final int hour;
42
43
44 /**
45 * Constructor.
46 *
47 * @param hour Hour 0-23
48 * @throws IndexOutOfBoundsException When the hour is less than 0 or greater than 23
49 */
50 private Hour(final int hour)
51 {
52 super();
53 if ((hour < 0) || (hour > 23))
54 {
55 throw new IndexOutOfBoundsException("Hour number out of range (0-23)!"); //$NON-NLS-1$
56 }
57 this.hour = hour;
58 }
59
60
61 /**
62 * Hour factory.
63 *
64 * @param hour Hour 0-23
65 * @return Hour object
66 */
67 public static Hour of(final int hour)
68 {
69 /*
70 synchronized (Hour.class)
71 {
72 Hour obj = Hour.CACHE.get(hour);
73 if (obj != null)
74 {
75 return obj;
76 }
77 obj = new Hour(hour);
78 Hour.CACHE.put(Integer.valueOf(hour), obj);
79 return obj;
80 }
81 */
82 return new Hour(hour);
83 }
84
85
86 /**
87 * Hour factory.
88 *
89 * @param value Hour 0-23 string
90 * @return Hour object
91 */
92 public static Hour of(final String value)
93 {
94 return of(Integer.parseInt(value));
95 }
96
97
98 /**
99 * Returns the value of this Hour as an int.
100 *
101 * @return The numeric value represented by this object after conversion to type int.
102 */
103 public int intValue()
104 {
105 return this.hour;
106 }
107
108
109 /**
110 * Returns the value of this Hour as a String.
111 *
112 * @return The numeric value represented by this object after conversion to type String.
113 */
114 @Override
115 public String stringValue()
116 {
117 return String.valueOf(this.hour);
118 }
119
120
121 /**
122 * Calculate hash code.
123 *
124 * @return Hash
125 * @see java.lang.Object#hashCode()
126 */
127 @Override
128 public int hashCode()
129 {
130 return Integer.hashCode(this.hour);
131 }
132
133
134 /**
135 * Is equal with another object.
136 *
137 * @param obj Object
138 * @return true when equal, false otherwise
139 * @see java.lang.Object#equals(java.lang.Object)
140 */
141 @Override
142 public boolean equals(final Object obj)
143 {
144 if (this == obj)
145 {
146 return true;
147 }
148 if (!(obj instanceof Hour))
149 {
150 return false;
151 }
152 final Hour other = (Hour)obj;
153 return this.hour == other.hour;
154 }
155
156
157 /**
158 * Returns the string representation of this Hour.
159 *
160 * The exact details of this representation are unspecified and subject to change, but the following may be regarded as typical:
161 *
162 * "Hour[hour=1]"
163 *
164 * @return String representation of this Hour
165 * @see java.lang.Object#toString()
166 */
167 @Override
168 public String toString()
169 {
170 final var builder = new StringBuilder();
171 builder.append("Hour[hour=").append(this.hour).append(']'); //$NON-NLS-1$
172 return builder.toString();
173 }
174
175
176 /**
177 * Compare with another object.
178 *
179 * @param obj Object to compare with
180 * @return 0: equal; 1: greater; -1: smaller
181 * @see java.lang.Comparable#compareTo(java.lang.Object)
182 */
183 @Override
184 public int compareTo(final Hour obj)
185 {
186 Objects.requireNonNull(obj, "obj"); //$NON-NLS-1$
187 return Integer.compare(this.hour, obj.hour);
188 }
189
190
191 /**
192 * Add hours to this hour.
193 *
194 * @param hours Hours to add to this hour
195 * @return New hour after adding the hours to this hour
196 * @throws ArithmeticException In case of an overflow
197 */
198 public Hour add(final Hours hours)
199 {
200 final int newHour = Math.toIntExact(Math.addExact(this.hour, hours.longValue()));
201 if (newHour > 23)
202 {
203 // TODO Listener
204 throw new ArithmeticException(Hour.OVERFLOW);
205 }
206 return Hour.of(newHour);
207 }
208
209
210 /**
211 * Subtract hours from this hour.
212 *
213 * @param hours Hours to subtract from this hour
214 * @return New hour after subtracting hours from this hour
215 * @throws ArithmeticException In case of an underflow
216 */
217 public Hour subtract(final Hours hours)
218 {
219 final int newHour = Math.toIntExact(Math.subtractExact(this.hour, hours.longValue()));
220 if (newHour < 0)
221 {
222 // TODO Listener
223 throw new ArithmeticException(Hour.UNDERFLOW);
224 }
225 return Hour.of(newHour);
226 }
227
228
229 /**
230 * Increment this hour.
231 *
232 * @return New hour after incrementing this hour
233 * @throws ArithmeticException In case of an overflow
234 */
235 public Hour increment()
236 {
237 final int newHour = Math.incrementExact(this.hour);
238 if (newHour == 24)
239 {
240 // TODO Listener
241 throw new ArithmeticException(Hour.OVERFLOW);
242 }
243 return Hour.of(newHour);
244 }
245
246
247 /**
248 * Decrement this hour.
249 *
250 * @return New hour after decrement this hour
251 * @throws ArithmeticException In case of an overflow
252 */
253 public Hour decrement()
254 {
255 final int newHour = Math.decrementExact(this.hour);
256 if (newHour == -1)
257 {
258 // TODO Listener
259 throw new ArithmeticException(Hour.UNDERFLOW);
260 }
261 return Hour.of(newHour);
262 }
263
264 }