package org.fluxtream.core.metadata; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TimeZone; import org.fluxtream.core.TimeInterval; import org.fluxtream.core.TimeUnit; import org.fluxtream.core.TimezoneAwareTimeInterval; import org.fluxtream.core.TimezoneMap; import org.fluxtream.core.domain.metadata.VisitedCity; import org.fluxtream.core.utils.TimeUtils; import org.joda.time.DateTimeZone; import org.joda.time.LocalDate; /** * User: candide * Date: 30/05/13 * Time: 10:39 */ public abstract class AbstractTimespanMetadata { private TimezoneMap timezoneMap; private Map<String, TimeZone> consensusTimezones; public TimeInterval timeInterval; public long start, end; // startDate and endDate are in the date storage format: yyyy-MM-dd public String startDate, endDate; public VisitedCity consensusVisitedCity; public VisitedCity nextInferredCity; public VisitedCity previousInferredCity; private List<VisitedCity> cities; private List<VisitedCity> consensusCities; public AbstractTimespanMetadata() {} // This constructor does not set the time range (start, end, startDate, and endDate) and should only be called // by subclasses which are themselves going to set those parameters before return. protected AbstractTimespanMetadata(VisitedCity consensusVisitedCity, VisitedCity previousInferredCity, VisitedCity nextInferredCity, Map<String, TimeZone> consensusTimezones, TimezoneMap timezoneMap, List<VisitedCity> cities, List<VisitedCity> consensusCities) { this.consensusVisitedCity = consensusVisitedCity; this.nextInferredCity = nextInferredCity; this.previousInferredCity = previousInferredCity; this.consensusTimezones = consensusTimezones; this.timezoneMap = timezoneMap; this.cities = cities; this.consensusCities = consensusCities; } // Returns the millisecond time of the start of the given date in the given city. // This safely dereferences the geo_timezone field, and returns the answer in UTC if // the city or the geo_timezone are not able to be successfully parsed. public static long getStartTimeForDate(final VisitedCity city, final String forDate) { DateTimeZone dateTimeZone = null; if(city!=null && city.city!=null) { // Note that there are strings in the geo_timezone column // of the cities table which cause getTimeZone to throw an exception try { dateTimeZone = DateTimeZone.forID(city.city.geo_timezone); } catch (Exception e) { System.out.println("Failed to parse timezone for " + city.city.geo_timezone + ", using UTC"); } } else { System.out.println("Invalid city, using UTC"); } if(dateTimeZone==null) { dateTimeZone = DateTimeZone.UTC; } long forDateTime = TimeUtils.dateFormatter.withZone(dateTimeZone).parseDateTime(forDate).getMillis(); return forDateTime; } protected abstract TimeUnit getTimespanTimeUnit(); public TimeInterval getTimeInterval() { if (this.timeInterval==null) this.timeInterval = new TimezoneAwareTimeInterval(start, end, getTimespanTimeUnit(), consensusTimezones, timezoneMap); return this.timeInterval; } public List<VisitedCity> getCities() { return cities; } public List<VisitedCity> getConsensusCities() { return consensusCities; } // Return a list of dates starting with startDate and ending with endDate public List<String> getDateList() { LocalDate currLocalDate = LocalDate.parse(startDate); final LocalDate endLocalDate = LocalDate.parse(endDate); List<String> dates = new ArrayList<String>(); while(!currLocalDate.isAfter(endLocalDate)) { final String date = TimeUtils.dateFormatterUTC.print(currLocalDate); dates.add(date); currLocalDate = currLocalDate.plusDays(1); } return dates; } }