1 package com.github.mygreen.cellformatter.term;
2
3 import java.util.Calendar;
4 import java.util.Date;
5 import java.util.Locale;
6 import java.util.concurrent.TimeUnit;
7
8 import org.slf4j.Logger;
9 import org.slf4j.LoggerFactory;
10
11 import com.github.mygreen.cellformatter.lang.Era;
12 import com.github.mygreen.cellformatter.lang.EraPeriod;
13 import com.github.mygreen.cellformatter.lang.EraResolver;
14 import com.github.mygreen.cellformatter.lang.ExcelDateUtils;
15 import com.github.mygreen.cellformatter.lang.MSLocale;
16 import com.github.mygreen.cellformatter.lang.MessageResolver;
17 import com.github.mygreen.cellformatter.lang.Utils;
18
19
20
21
22
23
24
25
26
27 public abstract class DateTerm implements Term<Calendar> {
28
29 protected static final Logger logger = LoggerFactory.getLogger(DateTerm.class);
30
31 protected static final MessageResolvergeResolver.html#MessageResolver">MessageResolver messageResolver = new MessageResolver("com.github.mygreen.cellformatter.label");
32
33 protected static final EraResolverng/EraResolver.html#EraResolver">EraResolver eraResolver = new EraResolver();
34
35 @Override
36 public String format(Calendar value, MSLocale formatLocale, Locale runtimeLocale) {
37
38 return format(value, formatLocale, runtimeLocale, false);
39 }
40
41
42
43
44
45
46
47
48
49 public abstract String format(Calendar value, MSLocale formatLocale, Locale runtimeLocale, boolean isStartDate1904);
50
51
52
53
54
55
56
57
58
59 private static long getElapsedZeroTime(final Date date, final boolean isStartDate1904) {
60
61 if(isStartDate1904) {
62 return ExcelDateUtils.getExcelZeroDateTime(isStartDate1904);
63 } else {
64 if(ExcelDateUtils.MILLISECONDS_19000301 <= date.getTime()) {
65
66 return ExcelDateUtils.MILLISECONDS_19000101 - TimeUnit.DAYS.toMillis(2);
67 } else {
68 return ExcelDateUtils.MILLISECONDS_19000101 - TimeUnit.DAYS.toMillis(1);
69 }
70 }
71
72 }
73
74
75
76
77 public static DateTerm elapsedHour(final String format) {
78 return new ElapsedHourTerm(format);
79 }
80
81
82
83
84
85 public static DateTerm elapsedMinute(final String format) {
86 return new ElapsedMinuteTerm(format);
87 }
88
89
90
91
92 public static DateTerm elapsedSecond(final String format) {
93 return new ElapsedSecondTerm(format);
94 }
95
96
97
98
99 public static DateTerm year(final String format) {
100 return new YearTerm(format);
101 }
102
103
104
105
106 public static DateTerm eraName(final String format) {
107 return new EraNameTerm(format);
108 }
109
110
111
112
113 public static DateTerm eraYear(final String format) {
114 return new EraYearTerm(format);
115 }
116
117
118
119
120 public static DateTerm eraNameYear(final String format) {
121 return new EraNameYearTerm(format);
122 }
123
124
125
126
127 public static DateTerm month(final String format) {
128 return new MonthTerm(format);
129 }
130
131
132
133
134 public static DateTerm day(final String format) {
135 return new DayTerm(format);
136 }
137
138
139
140
141 public static DateTerm weekName(final String format) {
142 return new WeekName(format);
143 }
144
145
146
147
148 public static DateTerm weekNameForOO(final String format) {
149 return new WeekNameForOO(format);
150 }
151
152
153
154
155 public static DateTerm weekNumber(final String format) {
156 return new WeekNumberTerm(format);
157 }
158
159
160
161
162
163
164 public static DateTerm hour(final String format, final boolean half) {
165 return new HourTerm(format, half);
166 }
167
168
169
170
171 public static DateTerm minute(final String format) {
172 return new MinuteTerm(format);
173 }
174
175
176
177
178 public static DateTerm second(final String format) {
179 return new SecondTerm(format);
180 }
181
182
183
184
185 public static DateTerm quater(final String format) {
186 return new QuaterTerm(format);
187 }
188
189
190
191
192 public static DateTerm amPm(final String format) {
193 return new AmPmTerm(format);
194 }
195
196
197
198
199 public static class ElapsedHourTerm extends DateTerm {
200
201
202 private static final long BASE = 1000*60*60;
203
204 private final String format;
205
206 public ElapsedHourTerm(final String format) {
207 this.format = format;
208 }
209
210 @Override
211 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
212
213 final long zeroTime = getElapsedZeroTime(cal.getTime(), isStartDate1904);
214 if(logger.isInfoEnabled()) {
215 logger.info("ElapsedHour:calendar={}, zeroTime={}.", ExcelDateUtils.formatDate(cal.getTime()), ExcelDateUtils.formatDate(new Date(zeroTime)));
216 }
217
218 final long time = (long) ((cal.getTime().getTime() - zeroTime) / BASE);
219 final int formatLength = format.length();
220 return Utils.supplyZero(String.valueOf(time), formatLength);
221 }
222
223 public String getFormat() {
224 return format;
225 }
226
227 }
228
229
230
231
232 public static class ElapsedMinuteTerm extends DateTerm {
233
234
235 private static final long BASE = 1000*60;
236
237 private final String format;
238
239 public ElapsedMinuteTerm(final String format) {
240 this.format = format;
241 }
242
243 @Override
244 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
245
246 final long zeroTime = getElapsedZeroTime(cal.getTime(), isStartDate1904);
247 if(logger.isInfoEnabled()) {
248 logger.info("ElapsedMinute:calendar={}, zeroTime={}.", ExcelDateUtils.formatDate(cal.getTime()), ExcelDateUtils.formatDate(new Date(zeroTime)));
249 }
250
251 final long time = (long) ((cal.getTime().getTime() - zeroTime) / BASE);
252 final int formatLength = format.length();
253 return Utils.supplyZero(String.valueOf(time), formatLength);
254 }
255
256 public String getFormat() {
257 return format;
258 }
259
260 }
261
262
263
264
265 public static class ElapsedSecondTerm extends DateTerm {
266
267
268 private static final long BASE = 1000;
269
270 private final String format;
271
272 public ElapsedSecondTerm(final String format) {
273 this.format = format;
274 }
275
276 @Override
277 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
278
279 final long zeroTime = getElapsedZeroTime(cal.getTime(), isStartDate1904);
280 if(logger.isInfoEnabled()) {
281 logger.info("ElapsedSecond:calendar={}, zeroTime={}.", ExcelDateUtils.formatDate(cal.getTime()), ExcelDateUtils.formatDate(new Date(zeroTime)));
282 }
283
284 final long time = (long) ((cal.getTime().getTime() - zeroTime) / BASE);
285 final int formatLength = format.length();
286 return Utils.supplyZero(String.valueOf(time), formatLength);
287 }
288
289 public String getFormat() {
290 return format;
291 }
292
293 }
294
295
296
297
298 public static class YearTerm extends DateTerm {
299
300 private final String format;
301
302 public YearTerm(final String format) {
303 this.format = format;
304 }
305
306 @Override
307 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
308
309 final String value = String.valueOf(cal.get(Calendar.YEAR));
310 final int formatLength = format.length();
311
312
313 if(formatLength <= 2) {
314 return Utils.supplyZero(value, 2).substring(2);
315 } else {
316 return Utils.supplyZero(value, 4);
317 }
318 }
319
320 public String getFormat() {
321 return format;
322 }
323
324 }
325
326
327
328
329 public static class EraNameTerm extends DateTerm {
330
331 private final String format;
332
333 public EraNameTerm(final String format) {
334 this.format = format;
335 }
336
337 @Override
338 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
339
340 final Date date = cal.getTime();
341
342 final Era era;
343 if(formatLocale != null) {
344 era = eraResolver.getEra(formatLocale);
345 } else {
346 era = eraResolver.getEra(runtimeLocale);
347 }
348
349 if(era.isUnkndown()) {
350 return "";
351 }
352
353 final EraPeriod period = era.getTargetPeriod(date);
354 if(period.isUnknown()) {
355 return "";
356 }
357
358 final int formatLength = format.length();
359 if(formatLength == 1) {
360 return period.getAbbrevRomanName();
361
362 } else if(formatLength == 2) {
363 return period.getAbbrevName();
364
365 } else {
366 return period.getName();
367 }
368 }
369
370 public String getFormat() {
371 return format;
372 }
373
374 }
375
376
377
378
379 public static class EraYearTerm extends DateTerm {
380
381 private final String format;
382
383 public EraYearTerm(final String format) {
384 this.format = format;
385 }
386
387 @Override
388 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
389
390 final int formatLength = format.length();
391 final Date date = cal.getTime();
392
393 final Era era;
394 if(formatLocale != null) {
395 era = eraResolver.getEra(formatLocale);
396 } else {
397 era = eraResolver.getEra(runtimeLocale);
398 }
399
400 if(era.isUnkndown()) {
401
402 String value = String.valueOf(cal.get(Calendar.YEAR));
403 return Utils.supplyZero(value, formatLength);
404 }
405
406 final EraPeriod period = era.getTargetPeriod(date);
407 if(period.isUnknown()) {
408
409 String value = String.valueOf(cal.get(Calendar.YEAR));
410 return Utils.supplyZero(value, formatLength);
411
412 }
413
414 final String value = String.valueOf(period.getEraYear(cal));
415 return Utils.supplyZero(value, formatLength);
416
417 }
418
419 public String getFormat() {
420 return format;
421 }
422
423 }
424
425
426
427
428 public static class EraNameYearTerm extends DateTerm {
429
430 private final String format;
431
432 public EraNameYearTerm(final String format) {
433 this.format = format;
434 }
435
436 @Override
437 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
438
439 final int formatLength = format.length();
440 final Date date = cal.getTime();
441
442 final Era era;
443 if(formatLocale != null) {
444 era = eraResolver.getEra(formatLocale);
445 } else {
446 era = eraResolver.getEra(runtimeLocale);
447 }
448
449 if(era.isUnkndown()) {
450
451 String value = String.valueOf(cal.get(Calendar.YEAR));
452 return Utils.supplyZero(value, formatLength);
453 }
454
455 final EraPeriod period = era.getTargetPeriod(date);
456 if(period.isUnknown()) {
457
458 String value = String.valueOf(cal.get(Calendar.YEAR));
459 return Utils.supplyZero(value, formatLength);
460
461 }
462
463 StringBuilder sb = new StringBuilder();
464
465
466 if(formatLength >= 2) {
467 sb.append(period.getName());
468 }
469
470
471 final String strYear = String.valueOf(period.getEraYear(cal));
472 sb.append(Utils.supplyZero(strYear, 2));
473
474 return sb.toString();
475 }
476
477 public String getFormat() {
478 return format;
479 }
480
481 }
482
483
484
485
486 public static class MonthTerm extends DateTerm {
487
488 private final String format;
489
490 public MonthTerm(final String format) {
491 this.format = format;
492 }
493
494 @Override
495 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
496
497 final int value = cal.get(Calendar.MONTH) + 1;
498 final int formatLength = format.length();
499
500 if(formatLength == 1) {
501 return String.valueOf(value);
502
503 } else if(formatLength == 2) {
504 return Utils.supplyZero(String.valueOf(value), 2);
505
506 } else if(formatLength == 3) {
507
508 final String key = String.format("month.%d.abbrev", value);
509 return DateTerm.messageResolver.getMessage(formatLocale, key);
510
511 } else if(formatLength == 4) {
512
513 final String key = String.format("month.%d.name", value);
514 return DateTerm.messageResolver.getMessage(formatLocale, key);
515
516 } else if(formatLength == 5) {
517
518 final String key = String.format("month.%d.leading", value);
519 return DateTerm.messageResolver.getMessage(formatLocale, key);
520
521 } else {
522 return Utils.supplyZero(String.valueOf(value), 2);
523 }
524 }
525
526 public String getFormat() {
527 return format;
528 }
529
530 }
531
532
533
534
535
536
537
538 private static int getWeekIndex(final Calendar cal) {
539 final int val = cal.get(Calendar.DAY_OF_WEEK);
540 switch(val) {
541 case Calendar.SUNDAY:
542 return 0;
543 case Calendar.MONDAY:
544 return 1;
545 case Calendar.TUESDAY:
546 return 2;
547 case Calendar.WEDNESDAY:
548 return 3;
549 case Calendar.THURSDAY:
550 return 4;
551 case Calendar.FRIDAY:
552 return 5;
553 case Calendar.SATURDAY:
554 return 6;
555 }
556
557 return 0;
558 }
559
560
561
562
563
564 public static class DayTerm extends DateTerm {
565
566 private final String format;
567
568 public DayTerm(final String format) {
569 this.format = format;
570 }
571
572 @Override
573 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
574
575 final int value = cal.get(Calendar.DAY_OF_MONTH);
576 final int formatLength = format.length();
577
578 if(formatLength == 1) {
579 return String.valueOf(value);
580
581 } else if(formatLength == 2) {
582 return Utils.supplyZero(String.valueOf(value), 2);
583
584 } else if(formatLength == 3) {
585
586 final int index = getWeekIndex(cal);
587 final String key = String.format("week.%d.abbrev", index);
588 return messageResolver.getMessage(formatLocale, key);
589
590 } else if(formatLength >= 4) {
591
592 final int index = getWeekIndex(cal);
593 final String key = String.format("week.%d.name", index);
594 return messageResolver.getMessage(formatLocale, key);
595
596 } else {
597 return Utils.supplyZero(String.valueOf(value), 2);
598 }
599
600 }
601
602 public String getFormat() {
603 return format;
604 }
605
606 }
607
608
609
610
611
612 public static class WeekName extends DateTerm {
613
614 private final String format;
615
616 public WeekName(final String format) {
617 this.format = format;
618 }
619
620 @Override
621 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
622
623 final int index = getWeekIndex(cal);
624 final int formatLength = format.length();
625
626 if(formatLength <= 3) {
627 final String key = String.format("week.%d.abbrev", index);
628 return messageResolver.getMessage(formatLocale, runtimeLocale, key);
629 } else {
630 final String key = String.format("week.%d.name", index);
631 return messageResolver.getMessage(formatLocale, runtimeLocale, key);
632 }
633 }
634
635 public String getFormat() {
636 return format;
637 }
638
639 }
640
641
642
643
644
645 public static class WeekNameForOO extends DateTerm {
646
647 private final String format;
648
649 public WeekNameForOO(final String format) {
650 this.format = format;
651 }
652
653 @Override
654 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
655
656 final int index = getWeekIndex(cal);
657 final int formatLength = format.length();
658
659 if(formatLength <= 2) {
660 final String key = String.format("week.%d.abbrev", index);
661 return messageResolver.getMessage(formatLocale, runtimeLocale, key);
662 } else {
663 final String key = String.format("week.%d.name", index);
664 return messageResolver.getMessage(formatLocale, runtimeLocale, key);
665 }
666 }
667
668 public String getFormat() {
669 return format;
670 }
671
672 }
673
674
675
676
677
678 public static class WeekNumberTerm extends DateTerm {
679
680 private final String format;
681
682 public WeekNumberTerm(final String format) {
683 this.format = format;
684 }
685
686 @Override
687 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
688
689 final int val = cal.get(Calendar.WEEK_OF_YEAR);
690 return String.valueOf(val);
691
692 }
693
694 public String getFormat() {
695 return format;
696 }
697
698 }
699
700
701
702
703 public static class HourTerm extends DateTerm {
704
705 private final String format;
706
707
708
709
710 private final boolean half;
711
712 public HourTerm(final String format, final boolean half) {
713 this.format = format;
714 this.half = half;
715 }
716
717 @Override
718 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
719
720 final String value;
721 if(isHalf()) {
722 value = String.valueOf(cal.get(Calendar.HOUR));
723 } else {
724 value = String.valueOf(cal.get(Calendar.HOUR_OF_DAY));
725 }
726
727 final int formatLength = format.length();
728 return Utils.supplyZero(value, formatLength);
729
730 }
731
732 public boolean isHalf() {
733 return half;
734 }
735
736 public String getFormat() {
737 return format;
738 }
739
740 }
741
742
743
744
745 public static class MinuteTerm extends DateTerm {
746
747 private final String format;
748
749 public MinuteTerm(final String format) {
750 this.format = format;
751 }
752
753 @Override
754 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
755
756 final String value = String.valueOf(cal.get(Calendar.MINUTE));
757 final int formatLength = format.length();
758 return Utils.supplyZero(value, formatLength);
759
760 }
761
762 public String getFormat() {
763 return format;
764 }
765
766 }
767
768
769
770
771 public static class SecondTerm extends DateTerm {
772
773 private final String format;
774
775 public SecondTerm(final String format) {
776 this.format = format;
777 }
778
779 @Override
780 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
781
782 final String value = String.valueOf(cal.get(Calendar.SECOND));
783 final int formatLength = format.length();
784 return Utils.supplyZero(value, formatLength);
785
786 }
787
788 public String getFormat() {
789 return format;
790 }
791
792 }
793
794
795
796
797 public static class AmPmTerm extends DateTerm {
798
799 private final String format;
800
801 private final String am;
802
803 private final String pm;
804
805 public AmPmTerm(final String format) {
806 this.format = format;
807
808 String[] split = format.split("/");
809 if(split.length >= 2) {
810 this.am = split[0];
811 this.pm = split[1];
812 } else {
813 this.am = "AM";
814 this.pm = "PM";
815 }
816 }
817
818 @Override
819 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
820
821 final int val = cal.get(Calendar.AM_PM);
822 if(val == Calendar.AM) {
823 return messageResolver.getMessage(formatLocale, "day.am.name", am);
824
825 } else {
826 return messageResolver.getMessage(formatLocale, "day.pm.name", pm);
827
828 }
829
830 }
831
832 public String getFormat() {
833 return format;
834 }
835
836 public String getAm() {
837 return am;
838 }
839
840 public String getPm() {
841 return pm;
842 }
843
844 }
845
846
847
848
849 public static class QuaterTerm extends DateTerm {
850
851 private final String format;
852
853 public QuaterTerm(final String format) {
854 this.format = format;
855 }
856
857 @Override
858 public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
859
860 final int index = (cal.get(Calendar.MONTH) / 3) + 1;
861
862
863 if(format.length() == 1) {
864 final String key = String.format("quaterTerm.%d.abbrev", index);
865 return messageResolver.getMessage(formatLocale, runtimeLocale, key);
866
867 } else {
868 final String key = String.format("quaterTerm.%d.name", index);
869 return messageResolver.getMessage(formatLocale, runtimeLocale, key);
870 }
871
872 }
873
874 }
875 }