package edu.sc.seis.sod.tools; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.martiansoftware.jsap.FlaggedOption; import com.martiansoftware.jsap.ParseException; import com.martiansoftware.jsap.StringParser; import edu.iris.Fissures.model.ISOTime; import edu.iris.Fissures.model.MicroSecondDate; import edu.iris.Fissures.model.TimeInterval; import edu.iris.Fissures.model.UnitImpl; import edu.sc.seis.fissuresUtil.chooser.ClockUtil; import edu.sc.seis.sod.SodUtil; public class TimeParser extends StringParser { /** * @param ceiling should unspecified fields be floored or ceilinged. */ public TimeParser(boolean ceiling){ this.ceiling = ceiling; } public Object parse(String arg) throws ParseException { if(arg.equals("now")) { return "<now/>"; } else if(arg.equals(PREVIOUS_DAY_BEGIN)) { arg = PREVIOUS_DAY; }else if(arg.equals("network")){ if(ceiling){ return "<networkEndTime/>"; }else{ return "<networkStartTime/>"; } } // look for relative time, like -1d or -3m Matcher m = relativeTimePattern.matcher(arg); if (m.matches()) { String s = "<earlier><value>"+m.group(1)+"</value>"; if ("h".equals(m.group(2))) { s += "<unit>HOUR</unit>"; } else if ("d".equals(m.group(2))) { s += "<unit>DAY</unit>"; } else if ("m".equals(m.group(2))) { s += "<unit>MONTH</unit>"; } else if ("y".equals(m.group(2))) { s += "<unit>YEAR</unit>"; } else { throw new ParseException("I don't understand "+arg+", should be like -2h, -1d or -3m or -1y"); } return s+"</earlier>"; } return parseDate(arg); } public String parseDate(String arg) throws ParseException { return format(getMicroSecondDate(arg)); } public static String format(MicroSecondDate d) { DateFormat passcalFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); passcalFormat.setTimeZone(ISOTime.UTC); return passcalFormat.format(d); } public static String formatForParsing(MicroSecondDate d) { DateFormat passcalFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); passcalFormat.setTimeZone(ISOTime.UTC); return passcalFormat.format(d); } public MicroSecondDate getMicroSecondDate(String arg) throws ParseException { if (arg.equals("now")) { return ClockUtil.now(); } Matcher m = datePattern.matcher(arg); if(!m.matches()) { throw new ParseException("A time must be formatted as YYYY[[[[[-MM]-DD]-hh]-mm]-ss] like 2006-11-19, not '" + arg + "'"); } Calendar cal = SodUtil.createCalendar(Integer.parseInt(m.group(1)), extract(m, 2), extract(m, 3), extract(m, 4), extract(m, 5), extract(m, 6), ceiling); return new MicroSecondDate(cal.getTime()); } private int extract(Matcher m, int i) { if(m.group(i) == null) { return -1; } return Integer.parseInt(m.group(i)); } private Pattern datePattern = Pattern.compile("(\\-?\\d{4})-?(\\d{2})?-?(\\d{2})?-?(\\d{2})?-?(\\d{2})?-?(\\d{2})?"); private Pattern relativeTimePattern = Pattern.compile("-(\\d+)([hdmy])"); public static FlaggedOption createYesterdayParam(String name, String helpMessage, boolean ceiling) { return createParam(name, PREVIOUS_DAY_BEGIN, helpMessage, ceiling); } public static FlaggedOption createParam(String name, String defaultTime, String helpMessage, boolean ceiling) { return new FlaggedOption(name, new TimeParser(ceiling), defaultTime, false, name.charAt(0), name, helpMessage); } private boolean ceiling; public static final String FIRST_SEISMOGRAM = "1889-04-17"; private static final String PREVIOUS_DAY = new SimpleDateFormat("yyyy-MM-dd").format(ClockUtil.now() .subtract(new TimeInterval(1, UnitImpl.DAY))); private static String PREVIOUS_DAY_BEGIN = "the previous day, " + PREVIOUS_DAY; }