1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package org.metricshub.wbem.javax.cim;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 import org.metricshub.wbem.sblim.cimclient.internal.cim.DTStringReader;
61 import org.metricshub.wbem.sblim.cimclient.internal.cim.DTStringWriter;
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 public class CIMDateTimeInterval extends CIMDateTime {
94 private static final long serialVersionUID = -7362881414085831668l;
95
96 private int iDays, iHours, iMinutes, iSeconds, iUSeconds;
97
98 private String iStr;
99
100 private boolean iTotalMicrosCalced;
101
102 private long iTotalMicros;
103
104 private int iUnsignificantUSecDigits;
105
106 private static final int MAX_DAY = 99999999, MAX_HOUR = 23, MAX_MIN = 59, MAX_SEC = 59, MAX_MILLISEC =
107 999, MAX_MICROSEC = 999999;
108
109 private static final long MAX_INTERVAL =
110 ((((long) MAX_DAY * 24 * 60 * 60) + ((long) MAX_HOUR * 60 * 60) + ((long) MAX_MIN * 60) + MAX_SEC) * 1000) +
111 MAX_MILLISEC;
112
113 private static final long MILLISEC_ACCURACY_DIV = 1000, SEC_ACCURACY_DIV =
114 1000 * MILLISEC_ACCURACY_DIV, MIN_ACCURACY_DIV = 60 * SEC_ACCURACY_DIV, HOUR_ACCURACY_DIV =
115 60 * MIN_ACCURACY_DIV, DAY_ACCURACY_DIV = 24 * HOUR_ACCURACY_DIV, NO_ACCURACY_DIV = 100000000 * DAY_ACCURACY_DIV;
116
117 private static final long[] USEC_ACCURACY_DIV_A = {
118 1,
119 10,
120 100,
121 MILLISEC_ACCURACY_DIV,
122 10000,
123 100000,
124 SEC_ACCURACY_DIV
125 };
126
127 private long iAccuracyDivisor = 1;
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148 public CIMDateTimeInterval(int pDays, int pHours, int pMinutes, int pSeconds, int pMicroseconds)
149 throws IllegalArgumentException {
150 boolean notSignificant = checkLimits("pDays", pDays, 0, MAX_DAY, false);
151 if (notSignificant) this.iAccuracyDivisor = NO_ACCURACY_DIV;
152 notSignificant = checkLimits("pHours", pHours, 0, MAX_HOUR, notSignificant);
153 if (notSignificant && this.iAccuracyDivisor == 1) this.iAccuracyDivisor = DAY_ACCURACY_DIV;
154 notSignificant = checkLimits("pMinutes", pMinutes, 0, MAX_MIN, notSignificant);
155 if (notSignificant && this.iAccuracyDivisor == 1) this.iAccuracyDivisor = HOUR_ACCURACY_DIV;
156 notSignificant = checkLimits("pSeconds", pSeconds, 0, MAX_SEC, notSignificant);
157 if (notSignificant && this.iAccuracyDivisor == 1) this.iAccuracyDivisor = MIN_ACCURACY_DIV;
158 notSignificant = checkLimits("pMicroseconds", pMicroseconds, 0, MAX_MICROSEC, notSignificant);
159 if (notSignificant) {
160 this.iUnsignificantUSecDigits = 6;
161 if (this.iAccuracyDivisor == 1) this.iAccuracyDivisor = USEC_ACCURACY_DIV_A[this.iUnsignificantUSecDigits];
162 } else {
163 this.iUnsignificantUSecDigits = 0;
164 }
165
166 this.iDays = pDays;
167 this.iHours = pHours;
168 this.iMinutes = pMinutes;
169 this.iSeconds = pSeconds;
170 this.iUSeconds = pMicroseconds;
171
172 debug(
173 "CIMDateTimeInterval(" +
174 pDays +
175 "," +
176 pHours +
177 "," +
178 pMinutes +
179 "," +
180 pSeconds +
181 "," +
182 pMicroseconds +
183 "): days=" +
184 this.iDays +
185 ", hours=" +
186 this.iHours +
187 ", mins=" +
188 this.iMinutes +
189 ", secs=" +
190 this.iSeconds +
191 ", usecs=" +
192 this.iUSeconds +
193 ", acc div=" +
194 this.iAccuracyDivisor +
195 ", unsig digits=" +
196 this.iUnsignificantUSecDigits
197 );
198 }
199
200
201
202
203
204
205
206
207 public CIMDateTimeInterval(long pMilliseconds) throws IllegalArgumentException {
208 if (pMilliseconds < 0 || pMilliseconds > MAX_INTERVAL) throw new IllegalArgumentException(
209 "pMilliseconds must be between 0 and " + MAX_INTERVAL + ". " + pMilliseconds + " is illegal!"
210 );
211 long totalUSecs = pMilliseconds * 1000;
212 long totalSecs = pMilliseconds / 1000;
213 long totalMins = totalSecs / 60;
214 long totalHours = totalMins / 60;
215 long totalDays = totalHours / 24;
216
217 this.iUSeconds = (int) (totalUSecs % 1000000);
218 this.iSeconds = (int) (totalSecs % 60);
219 this.iMinutes = (int) (totalMins % 60);
220 this.iHours = (int) (totalHours % 24);
221 this.iDays = (int) totalDays;
222
223 this.iUnsignificantUSecDigits = 3;
224 this.iAccuracyDivisor = USEC_ACCURACY_DIV_A[this.iUnsignificantUSecDigits];
225
226 this.iTotalMicrosCalced = true;
227 this.iTotalMicros = pMilliseconds * 1000;
228
229 debug(
230 "CIMDateTimeInterval(" +
231 pMilliseconds +
232 "): days=" +
233 this.iDays +
234 ", hours=" +
235 this.iHours +
236 ", mins=" +
237 this.iMinutes +
238 ", secs=" +
239 this.iSeconds +
240 ", usecs=" +
241 this.iUSeconds +
242 ", acc div=" +
243 this.iAccuracyDivisor +
244 ", unsig digits=" +
245 this.iUnsignificantUSecDigits
246 );
247 }
248
249
250
251
252
253
254
255
256
257 public CIMDateTimeInterval(String pIntervalString) throws IllegalArgumentException {
258 if (pIntervalString == null) throw new IllegalArgumentException("Null IntervalString is not allowed!");
259 if (pIntervalString.length() != LENGTH) throw new IllegalArgumentException(
260 "Length of " + pIntervalString + " must be " + LENGTH + ", " + pIntervalString.length() + " is not valid!"
261 );
262 String intervalStr = setAccuracy(pIntervalString);
263 DTStringReader dtReader = new DTStringReader(intervalStr);
264 this.iDays = dtReader.readAndCheck(8, "days", 0, MAX_DAY, true);
265 this.iHours = dtReader.readAndCheck(2, "hours", 0, MAX_HOUR, true);
266 this.iMinutes = dtReader.readAndCheck(2, "minutes", 0, MAX_MIN, true);
267 this.iSeconds = dtReader.readAndCheck(2, "seconds", 0, MAX_SEC, true);
268 dtReader.read('.');
269 this.iUSeconds = dtReader.readAndCheck(6, "microseconds", 0, MAX_MICROSEC, false);
270 if (this.iAccuracyDivisor >= SEC_ACCURACY_DIV) this.iUSeconds = -1;
271 dtReader.read(':');
272 int zeros = dtReader.read(3, "zeros", false);
273 if (zeros != 0) {
274 String msg = "In " + pIntervalString + " the last 3 characters after ':' must be zeros!";
275 throw new IllegalArgumentException(msg);
276 }
277
278 debug(
279 "CIMDateTimeInterval(\"" +
280 pIntervalString +
281 "\"): days=" +
282 this.iDays +
283 ", hours=" +
284 this.iHours +
285 ", mins=" +
286 this.iMinutes +
287 ", secs=" +
288 this.iSeconds +
289 ", usecs=" +
290 this.iUSeconds +
291 ", acc div=" +
292 this.iAccuracyDivisor +
293 ", unsig digits=" +
294 this.iUnsignificantUSecDigits
295 );
296 }
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312 public int compareTo(CIMDateTime pObj) throws IllegalArgumentException {
313 if (!(pObj instanceof CIMDateTimeInterval)) {
314 String msg =
315 "This method requires a CIMDateTimeInterval instance, while it has received a " +
316 (pObj == null ? "null!" : pObj.getClass().getName() + " instance!");
317 throw new IllegalArgumentException(msg);
318 }
319 CIMDateTimeInterval that = (CIMDateTimeInterval) pObj;
320 long accuracyDivisor = Math.max(this.iAccuracyDivisor, that.iAccuracyDivisor);
321 debug(
322 "this.acDiv=" + this.iAccuracyDivisor + ", that.acDiv=" + that.iAccuracyDivisor + ", acDiv=" + accuracyDivisor
323 );
324 Long thisMicros = Long.valueOf(calcMicros(accuracyDivisor));
325 Long thatMicros = Long.valueOf(that.calcMicros(accuracyDivisor));
326 debug("thisUs=" + thisMicros + ", thatUs=" + thatMicros);
327 return thisMicros.compareTo(thatMicros);
328 }
329
330
331
332
333
334
335
336 @Override
337 public String getDateTimeString() {
338 if (this.iStr != null) return this.iStr;
339
340 DTStringWriter dtWriter = new DTStringWriter();
341 dtWriter.write(8, this.iDays);
342 dtWriter.write(2, this.iHours);
343 dtWriter.write(2, this.iMinutes);
344 dtWriter.write(2, this.iSeconds);
345 dtWriter.write('.');
346 dtWriter.writeUSec(this.iUSeconds / (int) this.iAccuracyDivisor, this.iUnsignificantUSecDigits);
347 dtWriter.write(":000");
348 return dtWriter.toString();
349 }
350
351
352
353
354
355
356
357 public int getDays() {
358 return this.iDays;
359 }
360
361
362
363
364
365
366
367 public int getHours() {
368 return this.iHours;
369 }
370
371
372
373
374
375
376
377 public int getMicroseconds() {
378 return this.iUSeconds;
379 }
380
381
382
383
384
385
386
387 public int getMinutes() {
388 return this.iMinutes;
389 }
390
391
392
393
394
395
396
397 public int getSeconds() {
398 return this.iSeconds;
399 }
400
401
402
403
404
405
406 public long getTotalMilliseconds() {
407 return getTotalMicros() / 1000;
408 }
409
410
411
412
413
414
415
416 @Override
417 public int hashCode() {
418 return getDateTimeString().hashCode();
419 }
420
421
422
423
424
425
426
427
428
429
430 @Override
431 public String toString() {
432 return getDateTimeString();
433 }
434
435
436
437 private static final int DAY_START_IDX = 0, HOUR_START_IDX = 8, MIN_START_IDX = 10, SEC_START_IDX = 12, DOT_IDX =
438 14, USEC_START_IDX = 15, UTC_START_IDX = 21, LENGTH = 25;
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458 private boolean checkGranularity(int pIdx, String pFieldName, int pFieldStartIdx, int pNextStartIdx)
459 throws IllegalArgumentException {
460 if (pIdx > pFieldStartIdx && pIdx < pNextStartIdx) throw new IllegalArgumentException(
461 "Partial unsignificant digits are not allowed for field " + pFieldName + " in " + this.iStr + "!"
462 );
463 return pIdx == pFieldStartIdx;
464 }
465
466
467
468
469
470
471
472
473 private static int findStar(String pIvStr) {
474 for (int i = 0; i < UTC_START_IDX; i++) if (pIvStr.charAt(i) == '*') return i;
475 return -1;
476 }
477
478
479
480
481
482
483
484
485
486
487 private static void checkStars(String pIvStr, int pStartIdx) {
488 for (int i = pStartIdx; i < UTC_START_IDX; i++) {
489 char ch = pIvStr.charAt(i);
490 if (i != DOT_IDX && ch != '*') throw new IllegalArgumentException(
491 "In " +
492 pIvStr +
493 " every digit character after the first '*' character must " +
494 "be '*', '" +
495 ch +
496 "' is invalid!"
497 );
498 }
499 }
500
501
502
503
504
505
506
507
508
509
510 private String setAccuracy(String pIntervalStr) throws IllegalArgumentException {
511 this.iStr = pIntervalStr;
512
513
514
515
516
517 int startIdx = findStar(this.iStr);
518 if (startIdx < 0) return this.iStr;
519
520 checkStars(this.iStr, startIdx + 1);
521 if (checkGranularity(startIdx, "Day", DAY_START_IDX, HOUR_START_IDX)) {
522 this.iAccuracyDivisor = NO_ACCURACY_DIV;
523 } else if (checkGranularity(startIdx, "Hour", HOUR_START_IDX, MIN_START_IDX)) {
524 this.iAccuracyDivisor = DAY_ACCURACY_DIV;
525 } else if (checkGranularity(startIdx, "Minute", MIN_START_IDX, SEC_START_IDX)) {
526 this.iAccuracyDivisor = HOUR_ACCURACY_DIV;
527 } else if (checkGranularity(startIdx, "Second", SEC_START_IDX, DOT_IDX)) {
528 this.iAccuracyDivisor = MIN_ACCURACY_DIV;
529 } else {
530
531 this.iUnsignificantUSecDigits = UTC_START_IDX - startIdx;
532 this.iAccuracyDivisor = USEC_ACCURACY_DIV_A[this.iUnsignificantUSecDigits];
533 }
534
535 char[] buf = this.iStr.toCharArray();
536 if (startIdx < USEC_START_IDX) startIdx = USEC_START_IDX;
537 for (int i = startIdx; i < UTC_START_IDX; i++) {
538 if (i == DOT_IDX) continue;
539 if (this.iStr.charAt(i) != '*') throw new IllegalArgumentException(
540 "All remaining digits must be marked as unsignificant in " + this.iStr + " !"
541 );
542 buf[i] = '0';
543 }
544 return new String(buf);
545 }
546
547
548
549
550
551
552 private long getTotalMicros() {
553 if (this.iTotalMicrosCalced) return this.iTotalMicros;
554 this.iTotalMicrosCalced = true;
555
556
557 this.iTotalMicros = this.iUSeconds > 0 ? this.iUSeconds : 0;
558 if (this.iSeconds > 0) this.iTotalMicros += SEC_ACCURACY_DIV * this.iSeconds;
559 if (this.iMinutes > 0) this.iTotalMicros += MIN_ACCURACY_DIV * this.iMinutes;
560 if (this.iHours > 0) this.iTotalMicros += HOUR_ACCURACY_DIV * this.iHours;
561 if (this.iDays > 0) this.iTotalMicros += DAY_ACCURACY_DIV * this.iDays;
562 debug(
563 "days=" +
564 this.iDays +
565 " ,hours=" +
566 this.iHours +
567 " ,mins=" +
568 this.iMinutes +
569 ", secs=" +
570 this.iSeconds +
571 ", usecs=" +
572 this.iUSeconds +
573 ", totalMicros=" +
574 this.iTotalMicros
575 );
576 return this.iTotalMicros;
577 }
578
579
580
581
582
583
584
585
586
587 private long calcMicros(long pAccuracyDivisor) {
588 long remainder = getTotalMicros() % pAccuracyDivisor;
589 return getTotalMicros() - remainder;
590 }
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611 private static boolean checkLimits(String pName, int pValue, int pLow, int pHigh, boolean pNotSignificant)
612 throws IllegalArgumentException {
613 if (pValue == -1) return true;
614 if (pNotSignificant) throw new IllegalArgumentException(
615 "Not significant fields must be followed by not significant fields!"
616 );
617 if (pValue < pLow || pValue > pHigh) throw new IllegalArgumentException(
618 pName + " must be between " + pLow + " and " + pHigh + ". " + pValue + " is invalid!"
619 );
620 return false;
621 }
622
623
624
625
626
627
628
629 private static void debug(String pMsg) {
630
631 }
632 }