4 * Copyright: Thomas McGlynn 1997-1998.
5 * This code may be used for any purpose, non-commercial
6 * or commercial so long as this copyright notice is retained
7 * in the source code or included in or referred to in any
10 * This class was contributed by D. Glowacki.
12 import java.util.Calendar;
13 import java.util.Date;
14 import java.util.GregorianCalendar;
15 import java.util.TimeZone;
16 import java.text.DecimalFormat;
18 public class FitsDate {
20 private int year = -1;
21 private int month = -1;
22 private int mday = -1;
23 private int hour = -1;
24 private int minute = -1;
25 private int second = -1;
26 private int millisecond = -1;
27 private Date date = null;
30 * Convert a FITS date string to a Java <CODE>Date</CODE> object.
31 * @param dStr the FITS date
32 * @return either <CODE>null</CODE> or a Date object
33 * @exception FitsException if <CODE>dStr</CODE> does not
34 * contain a valid FITS date.
36 public FitsDate(String dStr)
37 throws FitsException {
38 // if the date string is null, we are done
43 // if the date string is empty, we are done
45 if (dStr.length() == 0) {
49 // if string contains at least 8 characters...
50 int len = dStr.length();
54 // ... and there is a "/" in the string...
55 first = dStr.indexOf('-');
56 if (first == 4 && first < len) {
58 // ... this must be an new-style date
59 buildNewDate(dStr, first, len);
61 // no "/" found; maybe it is an old-style date...
64 first = dStr.indexOf('/');
65 if (first > 1 && first < len) {
67 // ... this must be an old-style date
68 buildOldDate(dStr, first, len);
74 throw new FitsException("Bad FITS date string \"" + dStr + '"');
78 private void buildOldDate(String dStr, int first, int len) {
79 int middle = dStr.indexOf('/', first + 1);
80 if (middle > first + 2 && middle < len) {
84 year = Integer.parseInt(dStr.substring(middle + 1)) + 1900;
85 month = Integer.parseInt(dStr.substring(first + 1, middle));
86 mday = Integer.parseInt(dStr.substring(0, first));
88 } catch (NumberFormatException e) {
90 year = month = mday = -1;
95 private void parseTime(String tStr)
96 throws FitsException {
97 int first = tStr.indexOf(':');
99 throw new FitsException("Bad time");
102 int len = tStr.length();
104 int middle = tStr.indexOf(':', first + 1);
105 if (middle > first + 2 && middle < len) {
107 if (middle + 3 < len && tStr.charAt(middle + 3) == '.') {
108 double d = Double.valueOf(tStr.substring(middle + 3)).doubleValue();
109 millisecond = (int) (d * 1000);
115 hour = Integer.parseInt(tStr.substring(0, first));
116 minute = Integer.parseInt(tStr.substring(first + 1, middle));
117 second = Integer.parseInt(tStr.substring(middle + 1, len));
118 } catch (NumberFormatException e) {
119 hour = minute = second = millisecond = -1;
124 private void buildNewDate(String dStr, int first, int len)
125 throws FitsException {
126 // find the middle separator
127 int middle = dStr.indexOf('-', first + 1);
128 if (middle > first + 2 && middle < len) {
132 // if this date string includes a time...
133 if (middle + 3 < len && dStr.charAt(middle + 3) == 'T') {
135 // ... try to parse the time
137 parseTime(dStr.substring(middle + 4));
138 } catch (FitsException e) {
139 throw new FitsException("Bad time in FITS date string \""
143 // we got the time; mark the end of the date string
148 year = Integer.parseInt(dStr.substring(0, first));
149 month = Integer.parseInt(dStr.substring(first + 1, middle));
150 mday = Integer.parseInt(dStr.substring(middle + 1, len));
152 } catch (NumberFormatException e) {
154 // yikes, something failed; reset everything
155 year = month = mday = hour = minute = second = millisecond = -1;
160 /** Get a Java Date object corresponding to this
162 * @return The Java Date object.
164 public Date toDate() {
165 if (date == null && year != -1) {
166 TimeZone tz = TimeZone.getTimeZone("GMT");
167 GregorianCalendar cal = new GregorianCalendar(tz);
169 cal.set(Calendar.YEAR, year);
170 cal.set(Calendar.MONTH, month - 1);
171 cal.set(Calendar.DAY_OF_MONTH, mday);
175 cal.set(Calendar.HOUR_OF_DAY, 0);
176 cal.set(Calendar.MINUTE, 0);
177 cal.set(Calendar.SECOND, 0);
178 cal.set(Calendar.MILLISECOND, 0);
182 cal.set(Calendar.HOUR_OF_DAY, hour);
183 cal.set(Calendar.MINUTE, minute);
184 cal.set(Calendar.SECOND, second);
185 if (millisecond == -1) {
186 cal.set(Calendar.MILLISECOND, 0);
188 cal.set(Calendar.MILLISECOND, millisecond);
192 date = cal.getTime();
198 /** Return the current date in FITS date format */
199 public static String getFitsDateString() {
200 return getFitsDateString(new Date(), true);
203 /** Create FITS format date string Java Date object.
204 * @param epoch The epoch to be converted to FITS format.
206 public static String getFitsDateString(Date epoch) {
207 return getFitsDateString(epoch, true);
210 /** Create FITS format date string.
211 * Note that the date is not rounded.
212 * @param epoch The epoch to be converted to FITS format.
213 * @param timeOfDay Should time of day information be included?
215 public static String getFitsDateString(Date epoch, boolean timeOfDay) {
218 GregorianCalendar cal = new GregorianCalendar(
219 TimeZone.getTimeZone("GMT"));
224 StringBuffer fitsDate = new StringBuffer();
225 DecimalFormat df = new DecimalFormat("0000");
226 fitsDate.append(df.format(cal.get(Calendar.YEAR)));
227 fitsDate.append("-");
228 df = new DecimalFormat("00");
230 fitsDate.append(df.format(cal.get(Calendar.MONTH) + 1));
231 fitsDate.append("-");
232 fitsDate.append(df.format(cal.get(Calendar.DAY_OF_MONTH)));
235 fitsDate.append("T");
236 fitsDate.append(df.format(cal.get(Calendar.HOUR_OF_DAY)));
237 fitsDate.append(":");
238 fitsDate.append(df.format(cal.get(Calendar.MINUTE)));
239 fitsDate.append(":");
240 fitsDate.append(df.format(cal.get(Calendar.SECOND)));
241 fitsDate.append(".");
242 df = new DecimalFormat("000");
243 fitsDate.append(df.format(cal.get(Calendar.MILLISECOND)));
246 return new String(fitsDate);
248 } catch (Exception e) {
250 return new String("");
254 public String toString() {
259 StringBuffer buf = new StringBuffer(23);
294 if (millisecond != -1) {
297 if (millisecond < 100) {
298 if (millisecond < 10) {
304 buf.append(millisecond);
308 return buf.toString();
311 public static void testArgs(String args[]) {
312 for (int i = 0; i < args.length; i++) {
315 FitsDate fd = new FitsDate(args[i]);
316 System.out.println("\"" + args[i] + "\" => " + fd + " => "
318 } catch (Exception e) {
319 System.err.println("Date \"" + args[i] + "\" threw "
320 + e.getClass().getName() + "(" + e.getMessage()
326 public static void autotest() {
327 String[] good = new String[6];
328 good[0] = "20/09/79";
329 good[1] = "1997-07-25";
330 good[2] = "1987-06-05T04:03:02.01";
331 good[3] = "1998-03-10T16:58:34";
336 String[] badOld = new String[4];
337 badOld[0] = "20/09/";
338 badOld[1] = "/09/79";
339 badOld[2] = "09//79";
340 badOld[3] = "20/09/79/";
343 String[] badNew = new String[4];
344 badNew[0] = "1997-07";
345 badNew[1] = "-07-25";
346 badNew[2] = "1997--07-25";
347 badNew[3] = "1997-07-25-";
350 String[] badMisc = new String[4];
351 badMisc[0] = "5-Aug-1992";
352 badMisc[1] = "28/02/91 16:32:00";
353 badMisc[2] = "18-Feb-1993";
354 badMisc[3] = "nn/nn/nn";
358 public static void main(String args[]) {
359 if (args.length == 0) {