Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added location info for timezones #263

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@
<argument>etcetera</argument>
<argument>backward</argument>
<argument>systemv</argument>
<argument>iso3166.tab</argument>
<argument>zone.tab</argument>
<argument>zone1970.tab</argument>
</arguments>
</configuration>
</plugin>
Expand Down
36 changes: 34 additions & 2 deletions src/main/java/org/joda/time/DateTimeZone.java
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ private static String printOffset(int offset) {
//--------------------------------------------------------------------

private final String iID;

private TimeZoneLocationInfo iLocationInfo;
/**
* Constructor.
*
Expand All @@ -671,8 +671,23 @@ protected DateTimeZone(String id) {
throw new IllegalArgumentException("Id must not be null");
}
iID = id;
iLocationInfo = null;
}

/**
* Constructor.
*
* @param id the id to use
* @param locationInfo the location info for this timezone
* @throws IllegalArgumentException if the id is null
*/
protected DateTimeZone(String id, TimeZoneLocationInfo locationInfo) {
if (id == null) {
throw new IllegalArgumentException("Id must not be null");
}
iID = id;
iLocationInfo = locationInfo;
}
// Principal methods
//--------------------------------------------------------------------

Expand All @@ -685,7 +700,24 @@ protected DateTimeZone(String id) {
public final String getID() {
return iID;
}


/**
* Gets the location-info of this datetime zone.
*
* @return the location-info of this datetime zone
*/
public TimeZoneLocationInfo getLocationInfo() {
return iLocationInfo;
}

/**
* Sets the location-info of this datetime zone.
*/
public void setLocationInfo(TimeZoneLocationInfo locationInfo) {
this.iLocationInfo = locationInfo;
}

/**
* Returns a non-localized name that is unique to this time zone. It can be
* combined with id to form a unique key for fetching localized names.
Expand Down Expand Up @@ -1267,7 +1299,7 @@ protected Object writeReplace() throws ObjectStreamException {
return new Stub(iID);
}

/**
/**
* Used to serialize DateTimeZones by id.
*/
private static final class Stub implements Serializable {
Expand Down
74 changes: 74 additions & 0 deletions src/main/java/org/joda/time/TimeZoneLocationInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.joda.time;

import java.util.HashMap;

public class TimeZoneLocationInfo {
public String getLatitude() {
return latitude;
}

public void setLatitude(String latitude) {
this.latitude = latitude;
}

public String getLongitude() {
return longitude;
}

@Override
public String toString() {
return "LocationInfo [latitude=" + latitude + ", longitude="
+ longitude + ", comments=" + comments + ", countries="
+ countries + "]";
}

public void setLongitude(String longitude) {
this.longitude = longitude;
}

public String getComments() {
return comments;
}

public void setComments(String comments) {
this.comments = comments;
}

public HashMap<String, String> getCountries() {
return countries;
}

public void setCountries(HashMap<String, String> countries) {
this.countries = countries;
}

private String latitude;
private String longitude;
private String comments;
private HashMap<String, String> countries;

public TimeZoneLocationInfo(String lat, String lon, String com, HashMap<String, String> countries) {
latitude = lat;
longitude = lon;
comments = com;
this.countries = countries;
}

public TimeZoneLocationInfo(String lat, String lon, String com, String countries) {
countries = countries.substring(1, countries.length()-1);
HashMap<String, String> countriesMap = new HashMap<String, String>();
String[] pairs = countries.split(",");

for(int index=0; index<pairs.length; index++) {
String pair = pairs[index];
String[] values = pair.split("=");
if(values.length==2) {
countriesMap.put(values[0].trim(), values[1].trim());
}
}
latitude = lat;
longitude = lon;
comments = com;
this.countries = countriesMap;
}
}
2 changes: 1 addition & 1 deletion src/main/java/org/joda/time/tz/CachedDateTimeZone.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public static CachedDateTimeZone forZone(DateTimeZone zone) {
private final transient Info[] iInfoCache = new Info[cInfoCacheMask + 1];

private CachedDateTimeZone(DateTimeZone zone) {
super(zone.getID());
super(zone.getID(), zone.getLocationInfo());
iZone = zone;
}

Expand Down
110 changes: 93 additions & 17 deletions src/main/java/org/joda/time/tz/DateTimeZoneBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,16 @@
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.joda.time.Chronology;
import org.joda.time.DateTime;
import org.joda.time.DateTimeUtils;
import org.joda.time.DateTimeZone;
import org.joda.time.Period;
import org.joda.time.PeriodType;
import org.joda.time.TimeZoneLocationInfo;
import org.joda.time.chrono.ISOChronology;

/**
Expand Down Expand Up @@ -110,7 +113,7 @@ public static DateTimeZone readFrom(DataInput in, String id) throws IOException
switch (in.readUnsignedByte()) {
case 'F':
DateTimeZone fixed = new FixedDateTimeZone
(id, in.readUTF(), (int)readMillis(in), (int)readMillis(in));
(id, in.readUTF(), (int)readMillis(in), (int)readMillis(in), parseTimeZoneLocationInfo(in.readLine()));
if (fixed.equals(DateTimeZone.UTC)) {
fixed = DateTimeZone.UTC;
}
Expand All @@ -123,6 +126,32 @@ public static DateTimeZone readFrom(DataInput in, String id) throws IOException
throw new IOException("Invalid encoding");
}
}

/**
* Parses the location-info string read from file and creates a
* {@link TimeZoneLocationInfo} object.
*
* @param locationInfo String to be parsed
* @return {@link TimeZoneLocationInfo} object if string is parsed successfully, null otherwise
*/
public static TimeZoneLocationInfo parseTimeZoneLocationInfo(String locationInfo) {
if(locationInfo == null) {
return null;
}
TimeZoneLocationInfo locInfo = null;
try {
String pattern = ".*latitude=(.*), longitude=(.*), comments=(.*), countries=(.*)].*";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(locationInfo);
m.matches();
locInfo = new TimeZoneLocationInfo(m.group(1), m.group(2), m.group(3), m.group(4));
} catch (Exception e) {
System.out.println("Failed to parse location-info string");
e.printStackTrace();
}

return locInfo;
}

/**
* Millisecond encoding formats:
Expand Down Expand Up @@ -328,8 +357,19 @@ private RuleSet getLastRuleSet() {
*
* @param id time zone id to assign
* @param outputID true if the zone id should be output
*/
*/
public DateTimeZone toDateTimeZone(String id, boolean outputID) {
return toDateTimeZone(id, outputID, null);
}

/**
* Processes all the rules and builds a DateTimeZone along with location-info
*
* @param id time zone id to assign
* @param outputID true if the zone id should be output
* @param locationInfo {@link TimeZoneLocationInfo} object for this timezone
*/
public DateTimeZone toDateTimeZone(String id, boolean outputID, TimeZoneLocationInfo locationInfo) {
if (id == null) {
throw new IllegalArgumentException();
}
Expand Down Expand Up @@ -393,7 +433,7 @@ public DateTimeZone toDateTimeZone(String id, boolean outputID) {
tr.getWallOffset(), tr.getStandardOffset());
}

PrecalculatedZone zone = PrecalculatedZone.create(id, outputID, transitions, tailZone);
PrecalculatedZone zone = PrecalculatedZone.create(id, outputID, transitions, tailZone, locationInfo);
if (zone.isCachable()) {
return CachedDateTimeZone.forZone(zone);
}
Expand Down Expand Up @@ -433,30 +473,43 @@ private boolean addTransition(ArrayList<Transition> transitions, Transition tr)
}

/**
* Encodes a built DateTimeZone to the given stream. Call readFrom to
* decode the data into a DateTimeZone object.
* Encodes a built DateTimeZone along with the location-info to the given stream.
* Call readFrom to decode the data into a DateTimeZone object.
*
* @param out the output stream to receive the encoded DateTimeZone
* @param locationInfo location-info of the timezone
* @param out the output stream to receive the encoded DateTimeZone
* @since 1.5 (parameter added)
*/
public void writeTo(String zoneID, OutputStream out) throws IOException {
public void writeTo(String zoneID, OutputStream out, TimeZoneLocationInfo locationInfo) throws IOException {
if (out instanceof DataOutput) {
writeTo(zoneID, (DataOutput)out);
writeTo(zoneID, (DataOutput)out, locationInfo);
} else {
writeTo(zoneID, (DataOutput)new DataOutputStream(out));
writeTo(zoneID, (DataOutput)new DataOutputStream(out), locationInfo);
}
}

/**
* Encodes a built DateTimeZone to the given stream. Call readFrom to
* decode the data into a DateTimeZone object.
*
* @param out the output stream to receive the encoded DateTimeZone
* @since 1.5 (parameter added)
*/
public void writeTo(String zoneID, DataOutput out) throws IOException {
public void writeTo(String zoneID, OutputStream out) throws IOException {
writeTo(zoneID, out, null);
}

/**
* Encodes a built DateTimeZone along with the location-info to the given stream.
* Call readFrom to decode the data into a DateTimeZone object.
*
* @param locationInfo location-info of the timezone
* @param out the output stream to receive the encoded DateTimeZone
* @since 1.5 (parameter added)
*/
public void writeTo(String zoneID, DataOutput out, TimeZoneLocationInfo locationInfo) throws IOException {
// pass false so zone id is not written out
DateTimeZone zone = toDateTimeZone(zoneID, false);
DateTimeZone zone = toDateTimeZone(zoneID, false, locationInfo);

if (zone instanceof FixedDateTimeZone) {
out.writeByte('F'); // 'F' for fixed
Expand All @@ -472,6 +525,10 @@ public void writeTo(String zoneID, DataOutput out) throws IOException {
}
((PrecalculatedZone)zone).writeTo(out);
}
//Write the location-info if present
if(locationInfo != null) {
out.writeBytes(locationInfo.toString());
}
}

/**
Expand Down Expand Up @@ -1374,10 +1431,14 @@ static PrecalculatedZone readFrom(DataInput in, String id) throws IOException {
if (in.readBoolean()) {
tailZone = DSTZone.readFrom(in, id);
}


//Try to read the location-info from the file
String locationInfoString = in.readLine();
TimeZoneLocationInfo locationInfo = DateTimeZoneBuilder.parseTimeZoneLocationInfo(locationInfoString);
return new PrecalculatedZone
(id, transitions, wallOffsets, standardOffsets, nameKeys, tailZone);
(id, transitions, wallOffsets, standardOffsets, nameKeys, tailZone, locationInfo);
}


/**
* Factory to create instance from builder.
Expand All @@ -1386,9 +1447,10 @@ static PrecalculatedZone readFrom(DataInput in, String id) throws IOException {
* @param outputID true if the zone id should be output
* @param transitions the list of Transition objects
* @param tailZone optional zone for getting info beyond precalculated tables
* @param locationInfo the location-info for this timezone
*/
static PrecalculatedZone create(String id, boolean outputID, ArrayList<Transition> transitions,
DSTZone tailZone) {
DSTZone tailZone, TimeZoneLocationInfo locationInfo) {
int size = transitions.size();
if (size == 0) {
throw new IllegalArgumentException();
Expand Down Expand Up @@ -1481,7 +1543,7 @@ static PrecalculatedZone create(String id, boolean outputID, ArrayList<Transitio
}

return new PrecalculatedZone
((outputID ? id : ""), trans, wallOffsets, standardOffsets, nameKeys, tailZone);
((outputID ? id : ""), trans, wallOffsets, standardOffsets, nameKeys, tailZone, locationInfo);
}

// All array fields have the same length.
Expand All @@ -1500,14 +1562,28 @@ static PrecalculatedZone create(String id, boolean outputID, ArrayList<Transitio
private PrecalculatedZone(String id, long[] transitions, int[] wallOffsets,
int[] standardOffsets, String[] nameKeys, DSTZone tailZone)
{
super(id);
super(id, null);
iTransitions = transitions;
iWallOffsets = wallOffsets;
iStandardOffsets = standardOffsets;
iNameKeys = nameKeys;
iTailZone = tailZone;
}

/**
* Constructor with location-info
*/
private PrecalculatedZone(String id, long[] transitions, int[] wallOffsets,
int[] standardOffsets, String[] nameKeys, DSTZone tailZone, TimeZoneLocationInfo locationInfo)
{
super(id, locationInfo);
iTransitions = transitions;
iWallOffsets = wallOffsets;
iStandardOffsets = standardOffsets;
iNameKeys = nameKeys;
iTailZone = tailZone;
}

public String getNameKey(long instant) {
long[] transitions = iTransitions;
int i = Arrays.binarySearch(transitions, instant);
Expand Down