import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * Class for calculating Modified Julian Day (MJD) numbers.
 * Proposed terminology:
 * <ul>
 * <li>Modified Julian Day: the integer number.</li>
 * <li>Modified Julian Date: the number with decimal fraction.</li>
 * </ul>
 * @see <a href="http://en.wikipedia.org/wiki/Julian_day">Julian day</a>
 * @author Ronald Koster
 */
public abstract class MJD {

	public static void main(String[] args) {
		DateFormat df = new SimpleDateFormat("yyyyMMdd");
		df.setLenient(false);

		Date date = new Date();
		if (args != null && args.length > 0) {
			try {
				date = df.parse(args[0]);
			} catch (ParseException pex) {
				System.out.println("Invalid date: " + args[0]);
				System.exit(1);
			}
		}

		System.out.println("Date = " + df.format(date));
		long mjd = calculateMJD(date);
		System.out.println("Modified Julian Day = MJD = " + mjd);
		System.out.println("MJD % 7 = " + mjd % 7);
		System.out.println("(MJD_Wednesday_18581117 = 0)");
	}

	/**
	 * @return Modified Julian Day (integer number) for given date.
	 * NB. Default calendar (default time zone and locale) are used.
	 */
	public static long calculateMJD(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.set(1858, Calendar.NOVEMBER, 17, 0, 0, 0);
		cal.set(Calendar.MILLISECOND, 0);
		long utc0 = cal.getTimeInMillis();
		long dstOffset0 = cal.get(Calendar.DST_OFFSET);

		cal.setTime(date);
		long utc1 = cal.getTimeInMillis();
		long dstOffset1 = cal.get(Calendar.DST_OFFSET);

		// LT = LocalTime = UTC + TimeZoneOffset + DstOffset = UTC + TZ + D
		// Hence: LT1 - LT0 = UTC1 - UTC0 + D1 - D0  (since TZ1 = TZ0)
		long ms = utc1 - utc0 + dstOffset1 - dstOffset0;
		//System.out.println("ms: " + ms); // For debugging.
		return ms / (24L * 3600L * 1000L);
	}
}

