001 package edu.nrao.sss.model.project.scheduling; 002 003 import java.io.Reader; 004 import java.io.StringReader; 005 import java.math.BigDecimal; 006 007 import java.util.Date; 008 009 import javax.xml.bind.annotation.XmlRootElement; 010 011 import javax.xml.bind.JAXBException; 012 import javax.xml.stream.XMLStreamException; 013 014 import org.apache.log4j.Logger; 015 016 import edu.nrao.sss.measure.TimeDuration; 017 import edu.nrao.sss.measure.TimeUnits; 018 import edu.nrao.sss.util.JaxbUtility; 019 020 //A sidereal day last from when a distant star is on the meridian at a point on Earth until 021 //it is next on the meridian. A sidereal day lasts 23 hours and 56 minutes. 022 023 //A Julian Date is used by astronomers, it has an origin of January 0,4173 BC at noon. This 024 //scale is counted in days and fractions of days rather than hours and minutes. 025 026 //The modified Julian date places the transition at midnight rather than noon. 027 /** 028 * @deprecated Use {@link edu.nrao.sss.measure.LocalSiderealTime}, 029 * {@link edu.nrao.sss.measure.JulianDate}, and the other time classes 030 * in <tt>edu.nrao.sss.measure</tt>. 031 * 032 * Represents an LST day number and hour for the purposes of scheduling. 033 * @author slovelan 034 */ 035 @Deprecated 036 @XmlRootElement 037 public class SchedTime implements Comparable<SchedTime> { 038 039 public static final float HOURS_PER_LST_DAY = 24; 040 041 //Number of milliseconds in a day. 042 private static final float MILLISECONDS_PER_DAY = 86400000; 043 private static final int MODIFIED_JULIAN_DAY_FOR_1970= 40587; 044 private static final int SECONDS_PER_HOUR = 3600; 045 private static final Logger log = Logger.getLogger( SchedTime.class ); 046 047 //Starting day number 048 private int day = 0; 049 050 //Starting hour 051 //Note units are hours although Barry's code uses half hours. 052 private double hour = 0; 053 054 /** 055 * Returns the number of days corresponding to the number of milliseconds 056 * passed in as an argument. 057 * @param millis the number of milliseconds. 058 * @return the corresponding number of days. 059 */ 060 061 private static double getDaysForMilliseconds( long millis ){ 062 double daysSince1970 = millis /MILLISECONDS_PER_DAY; 063 return daysSince1970; 064 } 065 066 067 /** 068 * Returns the modified julian day corresponding to the given 069 * number of milliseconds. 070 * @param milliseconds a time quantity. 071 * @return the modified julian day number corresponding to the given 072 * number of milliseconds. 073 */ 074 075 public static double modifiedJulianDay( long milliseconds ){ 076 077 double dayNow = getDaysForMilliseconds( milliseconds ) 078 + MODIFIED_JULIAN_DAY_FOR_1970; 079 return dayNow; 080 } 081 082 083 /** 084 * Returns the current modified julian day. 085 * @return the current modified julian day. 086 */ 087 088 public static double modifiedJulianDayNow(){ 089 long milliseconds = System.currentTimeMillis(); 090 double dayNow = modifiedJulianDay( milliseconds ); 091 return dayNow; 092 } 093 094 095 /** 096 * Returns the current LST time. 097 * @return the current LST time. 098 */ 099 100 public static double currentLSTTime(){ 101 double dayNow = modifiedJulianDayNow(); 102 double lstTime = getLSTTime( dayNow ); 103 return lstTime; 104 } 105 106 107 /** 108 * Returns the LST time corresponding to the passed in date. 109 * @param theDate a Date for which an LST time is wanted. 110 * @return the LST time corresponding to the date argument. 111 */ 112 113 public static double getLSTTime( Date theDate ){ 114 double theTime = -1; 115 if ( theDate != null ){ 116 long milliseconds = theDate.getTime(); 117 double jDay = modifiedJulianDay( milliseconds ); 118 theTime = getLSTTime( jDay ); 119 } 120 return theTime; 121 } 122 123 124 /** 125 * Returns the LST time corresponding to the indicated number of 126 * milliseconds. 127 * @param milliseconds a time represented in milliseconds. 128 * @return the LST time corresponding to the indicated number of 129 * milliseconds. 130 */ 131 132 public static double getLSTTime( long milliseconds ){ 133 double days = modifiedJulianDay( milliseconds ); 134 double lstTime = getLSTTime( days ); 135 return lstTime; 136 } 137 138 139 //LST = GST + 1.0027379093( T + T-to-Greenwich) - L / 15 140 //LST = local sidereal time 141 //GST = Greenwich sidereal time at midnight for the current date. 142 //T = the local 24 hour time 143 //T-to-Greenwich hours to convert local time to greenwich time. 144 //L west longitude of your location converted to hours ( hours=degrees/360*24) 145 /** 146 * Returns the LST time corresponding to the Julian time. 147 * @return the LST time corresponding to the Julian time. 148 */ 149 150 public static double getLSTTime( double julianDays ){ 151 152 //final double SIDEREAL_DAYS_PER_SOLAR_DAY = 1.0027379093; 153 154 //Convert the time to days and add constants to come up with 155 //the gst. 156 double lmst = julianDays + 6571; 157 158 lmst = lmst + 0.0027379094 * julianDays; 159 //lmst = (days + 6571) + 0.0027379094 * days 160 //lmst = days( 1.0027379094) +6571 161 162 //Is this something referred to as the equation of equanoxes? 163 lmst += 8.0771e-16 * julianDays * julianDays; 164 165 //Is this the longitude part? 166 lmst += 0.855951; 167 168 169 return lmst; 170 } 171 172 173 public static long convertHoursToSeconds( double hours ){ 174 long secs = (long)( hours * SECONDS_PER_HOUR ); 175 return secs; 176 } 177 178 public static double convertSecondsToHours( long seconds ){ 179 double hours = ( seconds * 1.0f ) / SECONDS_PER_HOUR; 180 int dayCount = (int)( hours / HOURS_PER_LST_DAY ); 181 double leftoverHours = hours - dayCount * HOURS_PER_LST_DAY; 182 return leftoverHours; 183 } 184 185 //------------------------------------------------------------------------- 186 // Construction 187 //------------------------------------------------------------------------- 188 189 190 /** 191 * Constructs an instance of this <code>SchedTime</code> initialized to the 192 * current time. 193 */ 194 195 public SchedTime(){ 196 double lstTimeNow = currentLSTTime(); 197 this.day = (int) lstTimeNow; 198 double hourFraction = lstTimeNow - this.day; 199 this.hour = hourFraction * HOURS_PER_LST_DAY; 200 } 201 202 203 /** 204 * Constructs an instance of this <code>SchedTime</code> initialized to the 205 * indicated LST day and hour. 206 */ 207 208 public SchedTime( double hours, int day ){ 209 if ( hours < 0 || hours > HOURS_PER_LST_DAY ){ 210 throw new IllegalArgumentException( "An hour value of: "+hours +" does not make sense!"); 211 } 212 if ( day < 0){ 213 throw new IllegalArgumentException( "A day value of: "+day+" does not make sense!"); 214 } 215 this.hour = hours; 216 this.day = day; 217 } 218 219 220 /** 221 * Constructs an instance of this <code>SchedTime</code> initialized to the 222 * same LST day and hour as the argument. 223 * @param copy a <code>SchedTime</code> representing a scheduling time to copy. 224 */ 225 //We provide a copy constructor to avoid Java's horrible clone mechanism 226 public SchedTime( SchedTime copy ){ 227 this.day = copy.getDay(); 228 this.hour = copy.getHour(); 229 } 230 231 232 //----------------------------------------------------------------------- 233 // Hour 234 //----------------------------------------------------------------------- 235 236 /** 237 * Returns the hour. 238 * @return the hour. 239 */ 240 241 public double getHour(){ 242 return hour; 243 } 244 245 /** 246 * Sets the hour 247 * @param hour the hour for this time. 248 */ 249 250 public void setHour( double hour ){ 251 if ( hour >= 0 && hour < HOURS_PER_LST_DAY ){ 252 this.hour = hour; 253 } 254 else { 255 throw new IllegalArgumentException( "An hour of "+hour+" does not make sense in a schedule."); 256 } 257 } 258 259 260 //------------------------------------------------------------ 261 // LST Day Number 262 //------------------------------------------------------------ 263 264 /** 265 * Sets the LST day number in the schedule. 266 * @param lstDayNumber the LST day number for the schedule. 267 */ 268 269 public void setDay( int lstDayNumber){ 270 if ( day >= 0 ){ 271 day = lstDayNumber; 272 } 273 else { 274 throw new IllegalArgumentException( "Setting an lst day to "+lstDayNumber+" doesn't make sense!"); 275 } 276 } 277 278 279 /** 280 * Returns the LST day number for the schedule. 281 * @return the lstDayNumber for the schedule. 282 */ 283 284 public int getDay(){ 285 return day; 286 } 287 288 289 //------------------------------------------------------------------------------------ 290 // Math Operations 291 //------------------------------------------------------------------------------------ 292 293 /** 294 * Returns a SchedTime that is the sum of the argument and this <code>SchedTime</code>. 295 * @param td a TimeDuration indicating the length of time this schedule time needs to 296 * be increased. 297 * @return the sum of this {@code SchedTime} and the argument. 298 */ 299 300 public SchedTime add( TimeDuration td ){ 301 SchedTime sum = null; 302 if ( td != null ){ 303 double hr = td.convertTo( TimeUnits.HOUR ).getValue().doubleValue(); 304 SchedTime newTime = new SchedTime( hr, 0 ); 305 sum = add( newTime ); 306 } 307 else { 308 throw new IllegalArgumentException( "SchedTime needs something to add!"); 309 } 310 return sum; 311 } 312 /** 313 * Returns a SchedTime that is the sum of the argument and this <code>SchedTime</code>. 314 * @param otherTime the <code>SchedTime</code> that should be added to this one. 315 * @return the sum of this <code>SchedTime</code> and the argument. 316 */ 317 318 public SchedTime add( SchedTime otherTime ){ 319 SchedTime sum = null; 320 if ( otherTime != null ){ 321 //Add the hours. 322 323 double thisHour = getHour(); 324 double otherHour = otherTime.getHour(); 325 double sumHour = thisHour + otherHour; 326 int sumDay = day; 327 if ( sumHour >= HOURS_PER_LST_DAY ){ 328 sumHour = sumHour - HOURS_PER_LST_DAY; 329 sumDay++; 330 } 331 //Add the days. 332 sumDay = sumDay + otherTime.getDay(); 333 sum = new SchedTime( sumHour, sumDay); 334 } 335 else { 336 sum = new SchedTime( this ); 337 } 338 return sum; 339 } 340 341 /** 342 * Returns a <code>TimeDuration</code> that represents the time difference between 343 * this <code>SchedTime</code> and the argument. 344 * @param otherTime the <code>SchedTime</code> that should be subtracted from this one. 345 * @return the difference of this <code>SchedTime</code> and the argument. 346 * @throws IllegalArgumentException if the parameter is larger than this <code>SchedTime</code>. 347 */ 348 349 350 public TimeDuration subtract( SchedTime otherTime ){ 351 TimeDuration difference = null; 352 if ( otherTime != null ){ 353 354 int diffDay = day; 355 356 //Add the hours. 357 double otherHour = otherTime.getHour(); 358 double thisHour = getHour(); 359 double diffHour = thisHour - otherHour; 360 if ( diffHour < 0 ){ 361 diffHour = diffHour + HOURS_PER_LST_DAY; 362 diffDay--; 363 } 364 365 //Subtract the days. 366 diffDay = diffDay - otherTime.getDay(); 367 double hours = diffDay * HOURS_PER_LST_DAY + diffHour; 368 difference = new TimeDuration(BigDecimal.valueOf(hours), TimeUnits.HOUR ); 369 } 370 else { 371 double hours = day * HOURS_PER_LST_DAY + getHour(); 372 difference = new TimeDuration(BigDecimal.valueOf(hours), TimeUnits.HOUR ); 373 } 374 return difference; 375 } 376 377 378 379 380 //----------------------------------------------------------------- 381 // Overriden Object Methods 382 //----------------------------------------------------------------- 383 384 public boolean equals( SchedTime other ){ 385 386 boolean result = false; 387 if ( other != null ){ 388 if ( other instanceof SchedTime ){ 389 SchedTime otherSched = (SchedTime) other; 390 if ( hour == otherSched.getHour()){ 391 if ( day == otherSched.getDay() ){ 392 result = true; 393 } 394 } 395 } 396 } 397 return result; 398 } 399 400 public int compareTo( SchedTime otherTime ){ 401 Integer thisDay = new Integer( day ); 402 Integer otherDay = new Integer( otherTime.getDay()); 403 int result = thisDay.compareTo( otherDay ); 404 if ( result == 0 ){ 405 Double thisHour = new Double( hour ); 406 Double otherHour = new Double( otherTime.getHour()); 407 result = thisHour.compareTo( otherHour ); 408 } 409 return result; 410 } 411 412 public int hashCode(){ 413 int result = 7; 414 result = 11 * result + new Integer( day ).hashCode(); 415 result = 11 * result + new Double( hour ).hashCode(); 416 return result; 417 } 418 419 420 //---------------------------------------------------------------------------- 421 // XML and String Representations 422 //---------------------------------------------------------------------------- 423 424 /** 425 * Returns a string containing the xml representation of this schedule time. 426 * @return a String containing the xml representation of this schedule time. 427 */ 428 429 public String toXml(){ 430 String xmlStr = ""; 431 432 try { 433 xmlStr = JaxbUtility.getSharedInstance().objectToXmlString(this); 434 } 435 catch( JAXBException je ){ 436 je.printStackTrace(); 437 log.error( "Could not convert schedule to xml "+je.getMessage()); 438 } 439 440 return xmlStr; 441 } 442 443 444 /** 445 * Returns the <code>SchedTime</code> constructed from a reader or null if 446 * it is not possible to determine the corresponding time. 447 * @param reader a Reader containing schedule time information. 448 * @return the corresponding SchedTime. 449 */ 450 451 public static SchedTime fromXml( Reader reader ){ 452 JaxbUtility util = JaxbUtility.getSharedInstance(); 453 SchedTime newSched = null; 454 if ( reader != null ){ 455 456 String errorStr = "Could not create viewer from string reader"; 457 try { 458 newSched = util.readObjectAsXmlFrom( reader, SchedTime.class, null ); 459 } 460 461 catch( JAXBException je ){ 462 log.error( errorStr +"(Jaxb) "+je.getMessage()+je.toString()); 463 je.printStackTrace(); 464 } 465 catch( XMLStreamException se ){ 466 log.error( errorStr + "(XML) "+se.getMessage()); 467 } 468 469 } 470 return newSched; 471 } 472 473 /** 474 * Returns a <code>SchedTime</code> from an xml representation or null if 475 * it is not possible to parse the xml. 476 * @param xmlString a String containing the xml representation of a <code>SchedTime</code> 477 * @return the <code>SchedTime</code> corresponding to the xml representation. 478 */ 479 480 public static SchedTime fromXml( String xmlString ){ 481 SchedTime newSched = null; 482 log.info( "xmlString is "+xmlString ); 483 if ( xmlString != null ){ 484 StringReader reader = new StringReader( xmlString ); 485 newSched = fromXml( reader ); 486 } 487 return newSched; 488 } 489 490 /** 491 * Returns a text representation of this schedule entry. 492 * The default form of the text is XML. However, if anything goes wrong 493 * during the conversion to XML, an alternate, and much abbreviated, form 494 * will be returned. 495 * 496 * @return a text representation of this schedule entry. 497 * 498 * @see #toSummaryString() 499 */ 500 public String toString(){ 501 try { 502 return toXml(); 503 } 504 catch (Exception ex) { 505 return toSummaryString(); 506 } 507 } 508 509 510 /** 511 * Returns a brief word description of this scheduling time. 512 * @return a brief word description of this scheduling time. 513 */ 514 515 public String toSummaryString(){ 516 double hour = getHour(); 517 //Round to one decimal 518 hour = ((int)( hour * 10 + 0.5 )) / 10.0; 519 String result = day + " at "+ hour; 520 return result; 521 } 522 523 524 /** 525 * Parses a string in the format used by Barry and returns a corresponding 526 * schedule time or null if there is no such time. 527 * @param str a String with the day and hour separated by the word "at". 528 * @return the schedule time corresponding to the string or null if there 529 * is no such time. 530 */ 531 532 public static SchedTime fromString( String str ){ 533 SchedTime newTime = null; 534 if ( str != null ){ 535 String[] parts = str.split( " "); 536 if ( parts.length == 3 ){ 537 try { 538 int day = Integer.parseInt( parts[0]); 539 double hour = Double.parseDouble( parts[2]); 540 newTime = new SchedTime( hour, day ); 541 } 542 catch( NumberFormatException nfe ){ 543 //log.error( "Could not make a sched time from string="+str ); 544 } 545 } 546 else { 547 //log.error( "Could not make a sched time from string="+str ); 548 } 549 } 550 return newTime; 551 } 552 553 }