001 package edu.nrao.sss.measure; 002 003 import java.math.BigDecimal; 004 import java.math.RoundingMode; 005 006 import static edu.nrao.sss.math.MathUtil.MC_FINAL_CALC; 007 008 import edu.nrao.sss.util.EnumerationUtility; 009 import edu.nrao.sss.util.Symbolic; 010 011 /** 012 * Units of time. 013 * <p> 014 * This class enumerates those units of time that are well defined. 015 * The unit <i>month</i>, for example, is not considered to be 016 * well-defined because sometimes it is 28 days, sometimes 29, and 017 * so on.</p> 018 * <p> 019 * <b><u>Table of Units</u></b></p> 020 * <p style="margin-left:1.5em"> 021 * <table border="1" cellspacing="0"> 022 * <tr BGCOLOR="#EEEEFF"><th>Element</th> <th>Name(s)<sup><i>1</i></sup></th> 023 * <th>Symbol(s)<sup><i>1</i></sup></th> <th>Seconds</th></tr> 024 * <tr><td>MICROSECOND</td><td>MICROSECOND</td> 025 * <td align="center">µs</td><td align="right">10<sup>-6</sup></td></tr> 026 * <tr><td>MILLISECOND</td><td>MILLISECOND</td> 027 * <td align="center">ms</td><td align="right">0.001</td></tr> 028 * <tr><td>SECOND</td><td>SECOND</td> 029 * <td align="center">s</td><td align="right">1.0</td></tr> 030 * <tr><td>MINUTE</td><td>MINUTE</td> 031 * <td align="center">m</td><td align="right">60.0</td></tr> 032 * <tr><td>HOUR</td><td>HOUR</td> 033 * <td align="center">h</td><td align="right">3,600.0</td></tr> 034 * <tr><td>DAY</td><td>DAY</td> 035 * <td align="center">d</td><td align="right">86,400.0</td></tr> 036 * <tr><td>YEAR</td><td>YEAR</td> 037 * <td align="center">y</td><td align="right">31,556,925.18748800</td></tr> 038 * </table> 039 * <sup><b>1</b></sup>The names in these columns may be sent to 040 * {@link #fromString(String)}. Note that the names are 041 * not case sensitive.<br/> 042 * </p> 043 * <p> 044 * <b><u>Table of Conversion Factors<sup>2</sup></u></b></p> 045 * <p style="margin-left:1.5em"> 046 * <table border="1" cellspacing="0"> 047 * <tr BGCOLOR="#EEEEFF"><th> </th><th>ns</th><th>µs</th><th>ms</th><th>s</th><th>m</th><th>h</th><th>d</th><th>w</th><th>ty</th><th>y</th></tr> 048 * <tr><td>NANOSECOND</td><td align="right">1</td><td align="right">0.001</td><td align="right">0.000001</td><td align="right">1E-9</td><td align="right">1.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666667E-11</td><td align="right">2.777777777777777777777777777777777777777777777777777777777777777777777777777777777777778E-13</td><td align="right">1.15740740740740740740740740740740740740740740740740740740740740740740740740740740740741E-14</td><td align="right">1.6534391534391534391534391534391534391534391534391534391534391534391534391534391534392E-15</td><td align="right">3.16887653663353660911395687389964307585456367629474904594101671868225683971378495887E-17</td></tr> 049 * <tr><td>MICROSECOND</td><td align="right">1E+3</td><td align="right">1</td><td align="right">0.001</td><td align="right">0.000001</td><td align="right">1.66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667E-8</td><td align="right">2.777777777777777777777777777777777777777777777777777777777777777777777777777777777777777778E-10</td><td align="right">1.15740740740740740740740740740740740740740740740740740740740740740740740740740740740740741E-11</td><td align="right">1.6534391534391534391534391534391534391534391534391534391534391534391534391534391534391534E-12</td><td align="right">3.16887653663353660911395687389964307585456367629474904594101671868225683971378495887162E-14</td></tr> 050 * <tr><td>MILLISECOND</td><td align="right">1E+6</td><td align="right">1E+3</td><td align="right">1</td><td align="right">0.001</td><td align="right">0.0000166666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667</td><td align="right">2.777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777778E-7</td><td align="right">1.15740740740740740740740740740740740740740740740740740740740740740740740740740740740740740741E-8</td><td align="right">1.6534391534391534391534391534391534391534391534391534391534391534391534391534391534391534392E-9</td><td align="right">3.16887653663353660911395687389964307585456367629474904594101671868225683971378495887162299E-11</td></tr> 051 * <tr><td>SECOND</td><td align="right">1E+9</td><td align="right">1E+6</td><td align="right">1E+3</td><td align="right">1</td><td align="right">0.0166666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667</td><td align="right">0.0002777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777778</td><td align="right">0.0000115740740740740740740740740740740740740740740740740740740740740740740740740740740740740740740741</td><td align="right">0.0000016534391534391534391534391534391534391534391534391534391534391534391534391534391534391534391534</td><td align="right">3.16887653663353660911395687389964307585456367629474904594101671868225683971378495887162298978E-8</td></tr> 052 * <tr><td>MINUTE</td><td align="right">6E+10</td><td align="right">6E+7</td><td align="right">6E+4</td><td align="right">6E+1</td><td align="right">1</td><td align="right">0.0166666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667</td><td align="right">0.0006944444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444</td><td align="right">0.0000992063492063492063492063492063492063492063492063492063492063492063492063492063492063492063492063</td><td align="right">0.0000019013259219801219654683741243397858455127382057768494275646100312093541038282709753229737938657</td></tr> 053 * <tr><td>HOUR</td><td align="right">3.6E+12</td><td align="right">3.6E+9</td><td align="right">3.6E+6</td><td align="right">3.6E+3</td><td align="right">6E+1</td><td align="right">1</td><td align="right">0.0416666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667</td><td align="right">0.005952380952380952380952380952380952380952380952380952380952380952380952380952380952380952380952381</td><td align="right">0.0001140795553188073179281024474603871507307642923466109656538766018725612462296962585193784276319423</td></tr> 054 * <tr><td>DAY</td><td align="right">8.64E+13</td><td align="right">8.64E+10</td><td align="right">8.64E+7</td><td align="right">8.64E+4</td><td align="right">1.44E+3</td><td align="right">24</td><td align="right">1</td><td align="right">0.1428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571429</td><td align="right">0.0027379093276513756302744587390492916175383430163186631756930384449414699095127102044650822631666143</td></tr> 055 * <tr><td>WEEK</td><td align="right">6.048E+14</td><td align="right">6.048E+11</td><td align="right">6.048E+8</td><td align="right">6.048E+5</td><td align="right">1.008E+4</td><td align="right">168</td><td align="right">7</td><td align="right">1</td><td align="right">0.0191653652935596294119212111733450413227684011142306422298512691145902893665889714312555758421662999</td></tr> 056 * <tr><td>YEAR</td><td align="right">3.15569252522016E+16</td><td align="right">31556925252201.6</td><td align="right">31556925252.2016</td><td align="right">31556925.2522016</td><td align="right">525948.75420336</td><td align="right">8765.812570056</td><td align="right">365.242190419</td><td align="right">52.1774557741428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571</td><td align="right">1</td></tr> 057 * </table> 058 * <sup><b>2</b></sup>This table was generated from the conversion logic of this class.<br/> 059 * </p> 060 * <p> 061 * <b>Version Info:</b> 062 * <table style="margin-left:2em"> 063 * <tr><td>$Revision: 1725 $</td> 064 * <tr><td>$Date: 2008-11-20 15:40:30 -0700 (Thu, 20 Nov 2008) $</td> 065 * <tr><td>$Author: switz $</td> 066 * </table></p> 067 * 068 * @author David M. Harland 069 * @since 2006-03-23 070 */ 071 public enum TimeUnits 072 implements Symbolic 073 { 074 /** @deprecated Same as {@link #YEAR}. */ 075 @Deprecated TROPICAL_YEAR("31556925.18748800", "ty"), 076 077 /** 078 * A tropical, as opposed to sidereal (or any other kind of), year. 079 * <p> 080 * The length of this year is taken as the J2000 value of 081 * 365.242 189 670 SI days. 082 * See <a href="http://en.wikipedia.org/wiki/Tropical_year"> 083 * Wikipedia</a> for more information.</p> 084 */ 085 YEAR("31556925.2522016", "y"), //TODO: See if this is the year we want 086 087 /** One week, or 7 days. */ 088 WEEK("604800.0", "w"), 089 090 /** 091 * One day, or 24 hours. 092 * <p> 093 * Note that this is one SI day, or one that does not vary with 094 * the earth's rotation and that never includes a leap second. 095 * It is exactly equal to 86,400.0 SI seconds.</p> 096 */ 097 DAY("86400.0", "d"), 098 099 /** One hour, or 60 minutes. */ 100 HOUR("3600.0", "h"), 101 102 /** One minute, or 60 seconds. */ 103 MINUTE("60.0", "m"), 104 105 /** One second. */ 106 SECOND("1.0", "s"), 107 108 /** One thousandth of a second. */ 109 MILLISECOND("0.001", "ms"), 110 111 /** One millionth of a second. */ 112 MICROSECOND("1e-6", "\u00B5s"), 113 114 /** One billionth of a second. */ 115 NANOSECOND("1e-9", "ns"); 116 117 private static final int PRECISION = MC_FINAL_CALC.getPrecision(); 118 119 private BigDecimal seconds; 120 private String symbol; 121 122 private TimeUnits(String secondsPerUnit, String symbol) 123 { 124 this.symbol = symbol; 125 this.seconds = new BigDecimal(secondsPerUnit); 126 127 //It turns out that the PRECISION constant is zero when we're 128 //in this constructor, so we make the call directly. 129 //(See http://forums.java.net/jive/thread.jspa?threadID=40585&tstart=0) 130 this.seconds = this.seconds.setScale(MC_FINAL_CALC.getPrecision(), 131 RoundingMode.HALF_UP); 132 } 133 134 /** Returns <i>false</i> -- these symbols are <i>not</i> case sensitive. */ 135 public boolean symbolsAreCaseSensitive() { return false; } 136 137 /** 138 * Returns the symbol for this unit. 139 * For example, the symbol for {@code MILLISECOND} is <i>ms</i>. 140 * 141 * @return the symbol for this unit. 142 */ 143 public String getSymbol() 144 { 145 return symbol; 146 } 147 148 /** 149 * Returns the number of seconds in one of these units. 150 * 151 * @return the number of seconds in one of these units. 152 */ 153 public BigDecimal toSeconds() 154 { 155 return seconds; 156 } 157 158 /** 159 * Returns a factor for converting from this unit to {@code otherUnits}. 160 * 161 * @param otherUnits the unit to which conversion is desired. 162 * 163 * @return a factor for converting from this unit to {@code otherUnits}. 164 */ 165 public BigDecimal toUnits(TimeUnits otherUnits) 166 { 167 return convertTo(otherUnits, BigDecimal.ONE); 168 } 169 170 /** 171 * Non-public method for use by this and other classes in pkg. 172 * Does the actual conversion; keeps answer in BigDecimal form. 173 */ 174 BigDecimal convertTo(TimeUnits otherUnits, BigDecimal value) 175 { 176 BigDecimal answer = value; 177 178 if (!otherUnits.equals(this)) 179 { 180 try //to use BigDecimal, for better accuracy, but... 181 { 182 if (value.scale() < PRECISION) 183 value = value.setScale(PRECISION); 184 185 BigDecimal dividend = this.seconds.multiply(value); 186 187 answer = dividend.divide(otherUnits.seconds, MC_FINAL_CALC); 188 } 189 catch (ArithmeticException ex) 190 { 191 //...if it fails, use java primitives 192 double ratio = this.seconds.doubleValue() / 193 otherUnits.seconds.doubleValue(); 194 195 answer = BigDecimal.valueOf(value.doubleValue() * ratio); 196 } 197 } 198 199 return answer.round(MC_FINAL_CALC); 200 } 201 202 /** 203 * Returns a default unit of time. 204 * @return a default unit of time. 205 */ 206 public static TimeUnits getDefault() 207 { 208 return HOUR; 209 } 210 211 /** 212 * Returns a text representation of this enumeration constant. 213 * @return a text representation of this enumeration constant. 214 */ 215 public String toString() 216 { 217 return EnumerationUtility.getSharedInstance().enumToString(this); 218 } 219 220 /** 221 * Returns the time units represented by {@code text}. 222 * <p> 223 * For details about the transformation, see 224 * {@link EnumerationUtility#enumFromString(Class, String)}.</p> 225 * 226 * @param text a text representation of a unit of time. 227 * 228 * @return the time units represented by {@code text}. 229 */ 230 public static TimeUnits fromString(String text) 231 { 232 return EnumerationUtility.getSharedInstance() 233 .enumFromString(TimeUnits.class, text); 234 } 235 236 //Here for testing only 237 /* 238 private static String toHtmlTable() 239 { 240 StringBuilder table = new StringBuilder(); 241 242 TimeUnits[] sortedUnits = TimeUnits.values(); 243 java.util.Arrays.sort(sortedUnits, 244 new java.util.Comparator<TimeUnits>() { 245 public int compare(TimeUnits a, TimeUnits b) { 246 return a.toSeconds().compareTo(b.toSeconds()); 247 } 248 }); 249 250 251 //Column headers 252 table.append(" * <table border=\"1\" cellspacing=\"0\">\n"); 253 table.append(" * <tr BGCOLOR=\"#EEEEFF\"><th> </th>"); 254 for (TimeUnits u : sortedUnits) 255 table.append("<th>").append(u.getSymbol()).append("</th>"); 256 table.append("</tr>\n"); 257 258 //Data rows 259 for (TimeUnits from : sortedUnits) 260 { 261 if (from == TROPICAL_YEAR) 262 continue; 263 264 table.append(" * <tr><td>").append(from.name()).append("</td>"); 265 266 for (TimeUnits to : sortedUnits) 267 { 268 if (to == TROPICAL_YEAR) 269 continue; 270 271 table.append("<td align=\"right\">").append(from.convertTo(to).stripTrailingZeros()) 272 .append("</td>"); 273 } 274 table.append("</tr>\n"); 275 } 276 277 //End table 278 table.append(" * </table>"); 279 280 return table.toString(); 281 } 282 283 public static void main(String[] args) 284 { 285 String htmlTable = TimeUnits.toHtmlTable(); 286 287 System.out.println(htmlTable); 288 } 289 */ 290 /* 291 public static void main(String[] args) 292 { 293 for (TimeUnits tu : TimeUnits.values()) 294 System.out.println(tu.name() + " " + tu.toString() + " " + tu.getSymbol() + 295 " = " + tu.toSeconds() + " seconds."); 296 } 297 */ 298 /* 299 public static void main(String[] args) 300 { 301 EnumSet<TimeUnits> miniSet = EnumSet.range(TimeUnits.DAY, TimeUnits.MILLISECOND); 302 for (TimeUnits tu : miniSet) 303 System.out.println(tu.name() + " " + tu.toString() + " " + tu.getSymbol()); 304 System.out.println(); 305 SortedSet<TimeUnits> ss = new TreeSet<TimeUnits>(miniSet); 306 for (TimeUnits tu : ss) 307 System.out.println(tu.name() + " " + tu.toString() + " " + tu.getSymbol()); 308 }*/ 309 }