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-2010, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 */ 9package com.ibm.icu.util; 10import java.util.Arrays; 11import java.util.Date; 12 13/** 14 * <code>TimeArrayTimeZoneRule</code> represents a time zone rule whose start times are 15 * defined by an array of milliseconds since the standard base time. 16 * 17 * @stable ICU 3.8 18 */ 19public class TimeArrayTimeZoneRule extends TimeZoneRule { 20 21 private static final long serialVersionUID = -1117109130077415245L; 22 23 private final long[] startTimes; 24 private final int timeType; 25 26 /** 27 * Constructs a <code>TimeArrayTimeZoneRule</code> with the name, the GMT offset of its 28 * standard time, the amount of daylight saving offset adjustment and 29 * the array of times when this rule takes effect. 30 * 31 * @param name The time zone name. 32 * @param rawOffset The UTC offset of its standard time in milliseconds. 33 * @param dstSavings The amount of daylight saving offset adjustment in 34 * milliseconds. If this ia a rule for standard time, 35 * the value of this argument is 0. 36 * @param startTimes The start times in milliseconds since the base time 37 * (January 1, 1970, 00:00:00). 38 * @param timeType The time type of the start times, which is one of 39 * <code>DataTimeRule.WALL_TIME</code>, <code>STANDARD_TIME</code> 40 * and <code>UTC_TIME</code>. 41 * 42 * @stable ICU 3.8 43 */ 44 public TimeArrayTimeZoneRule(String name, int rawOffset, int dstSavings, long[] startTimes, int timeType) { 45 super(name, rawOffset, dstSavings); 46 if (startTimes == null || startTimes.length == 0) { 47 throw new IllegalArgumentException("No start times are specified."); 48 } else { 49 this.startTimes = startTimes.clone(); 50 Arrays.sort(this.startTimes); 51 } 52 this.timeType = timeType; 53 } 54 55 /** 56 * Gets the array of start times used by this rule. 57 * 58 * @return An array of the start times in milliseconds since the base time 59 * (January 1, 1970, 00:00:00 GMT). 60 * @stable ICU 3.8 61 */ 62 public long[] getStartTimes() { 63 return startTimes.clone(); 64 } 65 66 /** 67 * Gets the time type of the start times used by this rule. The return value 68 * is either <code>DateTimeRule.WALL_TIME</code> or <code>DateTimeRule.STANDARD_TIME</code> 69 * or <code>DateTimeRule.UTC_TIME</code>. 70 * 71 * @return The time type used of the start times used by this rule. 72 * @stable ICU 3.8 73 */ 74 public int getTimeType() { 75 return timeType; 76 } 77 78 /** 79 * {@inheritDoc} 80 * @stable ICU 3.8 81 */ 82 @Override 83 public Date getFirstStart(int prevRawOffset, int prevDSTSavings) { 84 return new Date(getUTC(startTimes[0], prevRawOffset, prevDSTSavings)); 85 } 86 87 /** 88 * {@inheritDoc} 89 * @stable ICU 3.8 90 */ 91 @Override 92 public Date getFinalStart(int prevRawOffset, int prevDSTSavings) { 93 return new Date(getUTC(startTimes[startTimes.length - 1], prevRawOffset, prevDSTSavings)); 94 } 95 96 /** 97 * {@inheritDoc} 98 * @stable ICU 3.8 99 */ 100 @Override 101 public Date getNextStart(long base, int prevOffset, int prevDSTSavings, boolean inclusive) { 102 int i = startTimes.length - 1; 103 for (; i >= 0; i--) { 104 long time = getUTC(startTimes[i], prevOffset, prevDSTSavings); 105 if (time < base || (!inclusive && time == base)) { 106 break; 107 } 108 } 109 if (i == startTimes.length - 1) { 110 return null; 111 } 112 return new Date(getUTC(startTimes[i + 1], prevOffset, prevDSTSavings)); 113 } 114 115 /** 116 * {@inheritDoc} 117 * @stable ICU 3.8 118 */ 119 @Override 120 public Date getPreviousStart(long base, int prevOffset, int prevDSTSavings, boolean inclusive) { 121 int i = startTimes.length - 1; 122 for (; i >= 0; i--) { 123 long time = getUTC(startTimes[i], prevOffset, prevDSTSavings); 124 if (time < base || (inclusive && time == base)) { 125 return new Date(time); 126 } 127 } 128 return null; 129 } 130 131 /** 132 * {@inheritDoc} 133 * @stable ICU 3.8 134 */ 135 @Override 136 public boolean isEquivalentTo(TimeZoneRule other) { 137 if (!(other instanceof TimeArrayTimeZoneRule)) { 138 return false; 139 } 140 if (timeType == ((TimeArrayTimeZoneRule)other).timeType 141 && Arrays.equals(startTimes, ((TimeArrayTimeZoneRule)other).startTimes)) { 142 return super.isEquivalentTo(other); 143 } 144 return false; 145 } 146 147 /** 148 * {@inheritDoc}<br><br> 149 * Note: This method in <code>TimeArrayTimeZoneRule</code> always returns true. 150 * @stable ICU 3.8 151 */ 152 @Override 153 public boolean isTransitionRule() { 154 return true; 155 } 156 157 /* Get UTC of the time with the raw/dst offset */ 158 private long getUTC(long time, int raw, int dst) { 159 if (timeType != DateTimeRule.UTC_TIME) { 160 time -= raw; 161 } 162 if (timeType == DateTimeRule.WALL_TIME) { 163 time -= dst; 164 } 165 return time; 166 } 167 168 /** 169 * Returns a <code>String</code> representation of this <code>TimeArrayTimeZoneRule</code> object. 170 * This method is used for debugging purpose only. The string representation can be changed 171 * in future version of ICU without any notice. 172 * 173 * @stable ICU 3.8 174 */ 175 @Override 176 public String toString() { 177 StringBuilder buf = new StringBuilder(); 178 buf.append(super.toString()); 179 buf.append(", timeType="); 180 buf.append(timeType); 181 buf.append(", startTimes=["); 182 for (int i = 0; i < startTimes.length; i++) { 183 if (i != 0) { 184 buf.append(", "); 185 } 186 buf.append(Long.toString(startTimes[i])); 187 } 188 buf.append("]"); 189 return buf.toString(); 190 } 191} 192