/* Copyright (c) 2013-2014 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Victor Olaya (Boundless) - initial implementation
*/
package org.locationtech.geogig.api.plumbing;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import javax.xml.datatype.DatatypeConfigurationException;
import org.locationtech.geogig.api.AbstractGeoGigOp;
import org.locationtech.geogig.api.Platform;
import com.google.common.base.Preconditions;
/**
* Parses a string representing a timestamp.
*
* Supported formats are:
*
* <ul>
* <li>Standard format supported by the DateFormat class in the current locale
* <li>git-like time strings (yesterday, 2.days.ago, etc)
* <li>a {@code long} representing miliseconds since the standard UNIX epoch
* </ul>
*
*/
public class ParseTimestamp extends AbstractGeoGigOp<Long> {
private String string;
private static HashMap<String, Integer> units = new HashMap<String, Integer>();
static {
units.put("second", 1000);
units.put("minute", 1000 * 60);
units.put("hour", 1000 * 60 * 60);
units.put("day", 1000 * 60 * 60 * 24);
units.put("week", 1000 * 60 * 60 * 24 * 7);
units.put("year", 1000 * 60 * 60 * 24 * 365);
}
/**
* @param string the String to parse
* @return {@code this}
*/
public ParseTimestamp setString(String string) {
this.string = string;
return this;
}
/**
* Parses a string with a timestamp
*
* @return a Long with the timestamp represented by the specified string
*/
@Override
protected Long _call() {
Preconditions.checkState(string != null, "String has not been set.");
try { // see if it is a timestamp in milisecs
Long milis = new Long(string);
return milis;
} catch (NumberFormatException e) {
}
SimpleDateFormat formatter;
final Platform platform = platform();
if (string.equals("yesterday")) { // return the beginning of yesterday, not just 24h ago
// from current time
try {
formatter = new SimpleDateFormat("dd/MM/yyyy");
Date today = new Date(platform.currentTimeMillis());
long todayOnlyDate = formatter.parse(formatter.format(today)).getTime();
long millisecsInOneDay = 60 * 60 * 24 * 1000;
long yesterday = todayOnlyDate - millisecsInOneDay;
return yesterday;
} catch (ParseException e) {
// shouldn't reach this
}
}
if (string.equals("today")) {
try {
formatter = new SimpleDateFormat("dd/MM/yyyy");
Date today = new Date(platform.currentTimeMillis());
long todayOnlyDate = formatter.parse(formatter.format(today)).getTime();
return todayOnlyDate;
} catch (ParseException e) {
// shouldn't reach this
}
}
// parse it as a git-like time reference
String[] tokens = string.split("\\.");
if (tokens.length % 2 != 0) {
if (tokens[tokens.length - 1].toLowerCase().equals("ago")) {
long currentTime = platform.currentTimeMillis();
int i;
for (i = 0; i < tokens.length - 1; i++) {
try {
double number = Double.parseDouble(tokens[i]);
i++;
String s = tokens[i].toLowerCase();
if (s.endsWith("s")) {
s = s.substring(0, s.length() - 1);
}
if (units.containsKey(s)) {
currentTime -= units.get(s) * number;
} else {
break;
}
} catch (Exception e) {
break;
}
}
if (i == tokens.length - 1) {
return currentTime;
}
}
}
// finally, try to parse it as a Date object
try {
long time = javax.xml.datatype.DatatypeFactory.newInstance()
.newXMLGregorianCalendar(string).toGregorianCalendar().getTimeInMillis();
return time;
} catch (DatatypeConfigurationException e) {
} catch (IllegalArgumentException e) {
}
throw new IllegalArgumentException("Invalid timestamp string: " + string);
}
}