// Copyright 2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.android.stardroid.util;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
/**
* Utilities for working with Dates and times.
*
* @author Kevin Serafini
* @author Brent Bryan
*/
public class TimeUtil {
private TimeUtil() {}
/**
* Calculate the number of Julian Centuries from the epoch 2000.0
* (equivalent to Julian Day 2451545.0).
*/
public static double julianCenturies(Date date) {
double jd = calculateJulianDay(date);
double delta = jd - 2451545.0;
return delta/36525.0;
}
/**
* Calculate the Julian Day for a given date using the following formula:
* JD = 367 * Y - INT(7 * (Y + INT((M + 9)/12))/4) + INT(275 * M / 9)
* + D + 1721013.5 + UT/24
*
* Note that this is only valid for the year range 1900 - 2099.
*/
public static double calculateJulianDay(Date date) {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.setTime(date);
double hour = cal.get(Calendar.HOUR_OF_DAY)
+ cal.get(Calendar.MINUTE)/60.0f
+ cal.get(Calendar.SECOND)/3600.0f;
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1;
int day = cal.get(Calendar.DAY_OF_MONTH);
double jd = 367.0 * year - Math.floor(7.0 * (year
+ Math.floor((month + 9.0) / 12.0)) / 4.0)
+ Math.floor(275.0 * month / 9.0) + day
+ 1721013.5 + hour/24.0;
return jd;
}
/**
* Convert the given Julian Day to Gregorian Date (in UT time zone).
* Based on the formula given in the Explanitory Supplement to the
* Astronomical Almanac, pg 604.
*/
public static Date calculateGregorianDate(double jd) {
int l = (int) jd + 68569;
int n = (4 * l) / 146097;
l = l - (146097 * n + 3) / 4;
int i = (4000 * (l + 1)) / 1461001;
l = l - (1461 * i) / 4 + 31;
int j =(80 * l) / 2447;
int d = l - (2447 * j) / 80;
l = j / 11;
int m = j + 2 - 12 * l;
int y = 100 * (n - 49) + i + l;
double fraction = jd - Math.floor(jd);
double dHours = fraction * 24.0;
int hours = (int) dHours;
double dMinutes = (dHours - hours) * 60.0;
int minutes = (int) dMinutes;
int seconds = (int) ((dMinutes - minutes) * 60.0);
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UT"));
cal.set(y, m - 1, d, hours + 12, minutes, seconds);
return cal.getTime();
}
/**
* Calculate local mean sidereal time in degrees. Note that longitude is
* negative for western longitude values.
*/
public static float meanSiderealTime(Date date, float longitude) {
// First, calculate number of Julian days since J2000.0.
double jd = calculateJulianDay(date);
double delta = jd - 2451545.0f;
// Calculate the global and local sidereal times
double gst = 280.461f + 360.98564737f * delta;
double lst = normalizeAngle(gst + longitude);
return (float) lst;
}
/**
* Normalize the angle to the range 0 <= value < 360.
*/
public static double normalizeAngle(double angle) {
double remainder = angle % 360;
if (remainder < 0) remainder += 360;
return remainder;
}
/**
* Normalize the time to the range 0 <= value < 24.
*/
public static double normalizeHours(double time) {
double remainder = time % 24;
if (remainder < 0) remainder += 24;
return remainder;
}
/**
* Take a universal time between 0 and 24 and return a triple
* [hours, minutes, seconds].
*
* @param ut Universal time - presumed to be between 0 and 24.
* @return [hours, minutes, seconds]
*/
public static int[] clockTimeFromHrs(double ut) {
int[] hms = new int[3];
hms[0] = (int) Math.floor(ut);
double remainderMins = 60 * (ut - hms[0]);
hms[1] = (int) Math.floor(remainderMins);
hms[2] = (int) Math.floor(remainderMins - hms[1]);
return hms;
}
}