1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html#License
3 /*
4 ******************************************************************************
5 * Copyright (C) 2007-2014, International Business Machines Corporation and   *
6 * others. All Rights Reserved.                                               *
7 ******************************************************************************
8 */
9 
10 package com.ibm.icu.impl.duration;
11 
12 import java.util.Date;
13 import java.util.TimeZone;
14 
15 /**
16  * Core implementation class for DurationFormatter.
17  */
18 class BasicDurationFormatter implements DurationFormatter {
19   private PeriodFormatter formatter;
20   private PeriodBuilder builder;
21   private DateFormatter fallback;
22   private long fallbackLimit;
23   private String localeName;
24   private TimeZone timeZone;
25 
26   /**
27    * Creates a basic duration formatter with the given formatter,
28    * builder, and fallback.  It's up to the caller to ensure that
29    * the locales and timezones of these are in sync.
30    */
BasicDurationFormatter(PeriodFormatter formatter, PeriodBuilder builder, DateFormatter fallback, long fallbackLimit)31   public BasicDurationFormatter(PeriodFormatter formatter,
32                                 PeriodBuilder builder,
33                                 DateFormatter fallback,
34                                 long fallbackLimit) {
35     this.formatter = formatter;
36     this.builder = builder;
37     this.fallback = fallback;
38     this.fallbackLimit = fallbackLimit < 0 ? 0 : fallbackLimit;
39   }
40 
41   protected BasicDurationFormatter(PeriodFormatter formatter,
42                                    PeriodBuilder builder,
43                                    DateFormatter fallback,
44                                    long fallbackLimit,
45                                    String localeName,
46                                    TimeZone timeZone) {
47     this.formatter = formatter;
48     this.builder = builder;
49     this.fallback = fallback;
50     this.fallbackLimit = fallbackLimit;
51     this.localeName = localeName;
52     this.timeZone = timeZone;
53   }
54 
55   @Override
56   public String formatDurationFromNowTo(Date targetDate) {
57     long now = System.currentTimeMillis();
58     long duration = targetDate.getTime() - now;
59     return formatDurationFrom(duration, now);
60   }
61 
62   @Override
63 public String formatDurationFromNow(long duration) {
64     return formatDurationFrom(duration, System.currentTimeMillis());
65   }
66 
67   @Override
68 public String formatDurationFrom(long duration, long referenceDate) {
69     String s = doFallback(duration, referenceDate);
70     if (s == null) {
71       Period p = doBuild(duration, referenceDate);
72       s = doFormat(p);
73     }
74     return s;
75   }
76 
77   @Override
78 public DurationFormatter withLocale(String locName) {
79     if (!locName.equals(localeName)) {
80       PeriodFormatter newFormatter = formatter.withLocale(locName);
81       PeriodBuilder newBuilder = builder.withLocale(locName);
82       DateFormatter newFallback = fallback == null
83           ? null
84           : fallback.withLocale(locName);
85       return new BasicDurationFormatter(newFormatter, newBuilder,
86                                         newFallback, fallbackLimit,
87                                         locName, timeZone);
88     }
89     return this;
90   }
91 
92   @Override
93 public DurationFormatter withTimeZone(TimeZone tz) {
94     if (!tz.equals(timeZone)) {
95       PeriodBuilder newBuilder = builder.withTimeZone(tz);
96       DateFormatter newFallback = fallback == null
97           ? null
98           : fallback.withTimeZone(tz);
99       return new BasicDurationFormatter(formatter, newBuilder,
100                                         newFallback, fallbackLimit,
101                                         localeName, tz);
102     }
103     return this;
104   }
105 
106   protected String doFallback(long duration, long referenceDate) {
107     if (fallback != null
108         && fallbackLimit > 0
109         && Math.abs(duration) >= fallbackLimit) {
110       return fallback.format(referenceDate + duration);
111     }
112     return null;
113   }
114 
doBuild(long duration, long referenceDate)115   protected Period doBuild(long duration, long referenceDate) {
116     return builder.createWithReferenceDate(duration, referenceDate);
117   }
118 
doFormat(Period period)119   protected String doFormat(Period period) {
120     if (!period.isSet()) {
121       throw new IllegalArgumentException("period is not set");
122     }
123     return formatter.format(period);
124   }
125 }
126