package nom.tam.fits; /* * Copyright: Thomas McGlynn 1997-1998. * This code may be used for any purpose, non-commercial * or commercial so long as this copyright notice is retained * in the source code or included in or referred to in any * derived software. * * This class was contributed by D. Glowacki. */ import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; public class FitsDate { private int year = -1; private int month = -1; private int mday = -1; private int hour = -1; private int minute = -1; private int second = -1; private int millisecond = -1; private Date date = null; /** * Convert a FITS date string to a Java <CODE>Date</CODE> object. * @param dStr the FITS date * @return either <CODE>null</CODE> or a Date object * @exception FitsException if <CODE>dStr</CODE> does not * contain a valid FITS date. */ public FitsDate(String dStr) throws FitsException { // if the date string is null, we're done if (dStr == null) { return; } // if the date string is empty, we're done dStr = dStr.trim(); if (dStr.length() == 0) { return; } // if string contains at least 8 characters... int len = dStr.length(); if (len >= 8) { int first; // ... and there's a "/" in the string... first = dStr.indexOf('-'); if (first == 4 && first < len) { // ... this must be an new-style date buildNewDate(dStr, first, len); // no "/" found; maybe it's an old-style date... } else { first = dStr.indexOf('/'); if (first > 1 && first < len) { // ... this must be an old-style date buildOldDate(dStr, first, len); } } } if (year == -1) { throw new FitsException("Bad FITS date string \"" + dStr + '"'); } } private void buildOldDate(String dStr, int first, int len) { int middle = dStr.indexOf('/', first + 1); if (middle > first + 2 && middle < len) { try { year = Integer.parseInt(dStr.substring(middle+1)) + 1900; month = Integer.parseInt(dStr.substring(first+1,middle)); mday = Integer.parseInt(dStr.substring(0, first)); } catch (NumberFormatException e) { year = month = mday = -1; } } } private void parseTime(String tStr) throws FitsException { int first = tStr.indexOf(':'); if (first < 0) { throw new FitsException("Bad time"); } int len = tStr.length(); int middle = tStr.indexOf(':', first + 1); if (middle > first + 2 && middle < len) { if (middle + 3 < len && tStr.charAt(middle + 3) == '.') { double d = Double.valueOf(tStr.substring(middle+3)).doubleValue(); millisecond = (int )(d * 1000); len = middle + 3; } try { hour = Integer.parseInt(tStr.substring(0, first)); minute = Integer.parseInt(tStr.substring(first+1, middle)); second = Integer.parseInt(tStr.substring(middle+1, len)); } catch (NumberFormatException e) { hour = minute = second = millisecond = -1; } } } private void buildNewDate(String dStr, int first, int len) throws FitsException { // find the middle separator int middle = dStr.indexOf('-', first + 1); if (middle > first + 2 && middle < len) { try { // if this date string includes a time... if (middle + 3 < len && dStr.charAt(middle + 3) == 'T') { // ... try to parse the time try { parseTime(dStr.substring(middle+4)); } catch (FitsException e) { throw new FitsException("Bad time in FITS date string \"" + dStr + "\""); } // we got the time; mark the end of the date string len = middle + 3; } // parse date string year = Integer.parseInt(dStr.substring(0, first)); month = Integer.parseInt(dStr.substring(first+1, middle)); mday = Integer.parseInt(dStr.substring(middle+1, len)); } catch (NumberFormatException e) { // yikes, something failed; reset everything year = month = mday = hour = minute = second = millisecond = -1; } } } public Date toDate() { if (date == null && year != -1) { TimeZone tz = TimeZone.getTimeZone("GMT"); GregorianCalendar cal = new GregorianCalendar(tz); cal.set(Calendar.YEAR, year); cal.set(Calendar.MONTH, month - 1); cal.set(Calendar.DAY_OF_MONTH, mday); if (hour == -1) { cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); } else { cal.set(Calendar.HOUR_OF_DAY, hour); cal.set(Calendar.MINUTE, minute); cal.set(Calendar.SECOND, second); if (millisecond == -1) { cal.set(Calendar.MILLISECOND, 0); } else { cal.set(Calendar.MILLISECOND, millisecond); } } date = cal.getTime(); } return date; } public String toString() { if (year == -1) { return ""; } StringBuffer buf = new StringBuffer(23); buf.append(year); buf.append('-'); if (month < 10) { buf.append('0'); } buf.append(month); buf.append('-'); if (mday < 10) { buf.append('0'); } buf.append(mday); if (hour != -1) { buf.append('T'); if (hour < 10) { buf.append('0'); } buf.append(hour); buf.append(':'); if (minute < 10) { buf.append('0'); } buf.append(minute); buf.append(':'); if (second < 10) { buf.append('0'); } buf.append(second); if (millisecond != -1) { buf.append('.'); if (millisecond < 100) { if (millisecond < 10) { buf.append("00"); } else { buf.append('0'); } } buf.append(millisecond); } } return buf.toString(); } public static void testArgs(String args[]) { for (int i = 0; i < args.length; i++) { try { FitsDate fd = new FitsDate(args[i]); System.out.println("\"" + args[i] + "\" => " + fd + " => " + fd.toDate()); } catch (Exception e) { System.err.println("Date \"" + args[i] + "\" threw " + e.getClass().getName() + "(" + e.getMessage() + ")"); } } } public static void autotest() { String[] good = new String[6]; good[0] = "20/09/79"; good[1] = "1997-07-25"; good[2] = "1987-06-05T04:03:02.01"; good[3] = "1998-03-10T16:58:34"; good[4] = null; good[5] = " "; testArgs(good); String[] badOld = new String[4]; badOld[0] = "20/09/"; badOld[1] = "/09/79"; badOld[2] = "09//79"; badOld[3] = "20/09/79/"; testArgs(badOld); String[] badNew = new String[4]; badNew[0] = "1997-07"; badNew[1] = "-07-25"; badNew[2] = "1997--07-25"; badNew[3] = "1997-07-25-"; testArgs(badNew); String[] badMisc = new String[4]; badMisc[0] = "5-Aug-1992"; badMisc[1] = "28/02/91 16:32:00"; badMisc[2] = "18-Feb-1993"; badMisc[3] = "nn/nn/nn"; testArgs(badMisc); } public static void main(String args[]) { if (args.length == 0) { autotest(); } else { testArgs(args); } } }