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

Fix 228: Table: DateTime serialization for milliseonds #30

Merged
merged 5 commits into from
Apr 4, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ public Date unmarshal(String arg0) throws Exception {

@Override
public String marshal(Date arg0) throws Exception {
return new ISO8601DateConverter().format(arg0);
return new ISO8601DateConverter().shortFormat(arg0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
Expand All @@ -26,38 +27,60 @@
*/
public class ISO8601DateConverter {
// Note: because of the trailing "0000000", this is not quite ISO 8601 compatible
private static final String DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z'";
private static final String DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
private static final String SHORT_DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'";
private static final String DATETIME_PATTERN_NO_S = "yyyy-MM-dd'T'HH:mm'Z'";
private static final String DATETIME_PATTERN_TO_DECIMAL = "yyyy-MM-dd'T'HH:mm:ss.";

public String format(Date date) {
return getFormat().format(date);
DateFormat iso8601Format = new SimpleDateFormat(DATETIME_PATTERN, Locale.US);
iso8601Format.setTimeZone(TimeZone.getTimeZone("GMT"));
return iso8601Format.format(date);
}

public String shortFormat(Date date) {
return getShortFormat().format(date);
DateFormat iso8601Format = new SimpleDateFormat(SHORT_DATETIME_PATTERN, Locale.US);
iso8601Format.setTimeZone(TimeZone.getTimeZone("GMT"));
return iso8601Format.format(date);
}

public Date parse(String date) throws ParseException {
if (date == null)
return null;

// Sometimes, the date comes back without the ".SSSSSSS" part (presumably when the decimal value
// of the date is "0". Use the short format in that case.
if (date.indexOf('.') < 0)
return getShortFormat().parse(date);
else
return getFormat().parse(date);
}
int length = date.length();
if (length == 17) {
// [2012-01-04T23:21Z] length = 17
return parseDateFromString(date, DATETIME_PATTERN_NO_S);
}
else if (length == 20) {
// [2012-01-04T23:21:59Z] length = 20
return parseDateFromString(date, SHORT_DATETIME_PATTERN);
}
else if (length >= 22 && length <= 28) {
// [2012-01-04T23:21:59.1Z] length = 22
// [2012-01-04T23:21:59.1234567Z] length = 28
// Need to handle the milliseconds gently.

private DateFormat getFormat() {
DateFormat iso8601Format = new SimpleDateFormat(DATETIME_PATTERN, Locale.US);
iso8601Format.setTimeZone(TimeZone.getTimeZone("GMT"));
return iso8601Format;
Date allExceptMilliseconds = parseDateFromString(date, DATETIME_PATTERN_TO_DECIMAL);
long timeWithSecondGranularity = allExceptMilliseconds.getTime();
// Decimal point is at 19
String secondDecimalString = date.substring(19, date.indexOf('Z'));
Float secondDecimal = Float.parseFloat(secondDecimalString);
int milliseconds = Math.round(secondDecimal * 1000);
long timeInMS = timeWithSecondGranularity + milliseconds;
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeInMS);
return calendar.getTime();
}
else {
throw new IllegalArgumentException(String.format("Invalid Date String: %s", date));
}
}

private DateFormat getShortFormat() {
DateFormat iso8601Format = new SimpleDateFormat(SHORT_DATETIME_PATTERN, Locale.US);
private static Date parseDateFromString(final String value, final String pattern) throws ParseException {
DateFormat iso8601Format = new SimpleDateFormat(pattern, Locale.US);
iso8601Format.setTimeZone(TimeZone.getTimeZone("GMT"));
return iso8601Format;
return iso8601Format.parse(value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ private InputStream generateEntry(PropertiesWriter propertiesWriter) {
writer.writeEndElement(); // title

writer.writeStartElement("updated");
writer.writeCharacters(iso8601DateConverter.shortFormat(dateFactory.getDate()));
writer.writeCharacters(iso8601DateConverter.format(dateFactory.getDate()));
writer.writeEndElement(); // updated

writer.writeStartElement("author");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public String serialize(String edmType, Object value) {

String serializedValue;
if (value instanceof Date) {
serializedValue = iso8601DateConverter.shortFormat((Date) value);
serializedValue = iso8601DateConverter.format((Date) value);
}
else if (value instanceof byte[]) {
serializedValue = new String(Base64.encode((byte[]) value));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

import static org.junit.Assert.*;

import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import org.junit.Test;

Expand All @@ -29,9 +31,23 @@ public void shortFormatWorks() throws Exception {

// Act
Date result = converter.parse(value);
String value2 = converter.format(result);

// Assert
assertNotNull(result);

Calendar calendar = Calendar.getInstance();
calendar.setTime(result);
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
assertEquals("Year", 2012, calendar.get(Calendar.YEAR));
assertEquals("Month", 1, calendar.get(Calendar.MONTH) + 1);
assertEquals("Day", 12, calendar.get(Calendar.DAY_OF_MONTH));
assertEquals("Hour", 0, calendar.get(Calendar.HOUR));
assertEquals("Minute", 35, calendar.get(Calendar.MINUTE));
assertEquals("Second", 58, calendar.get(Calendar.SECOND));
assertEquals("Millisecond", 0, calendar.get(Calendar.MILLISECOND));

assertEquals("2012-01-12T00:35:58.000Z", value2);
}

@Test
Expand All @@ -42,9 +58,50 @@ public void longFormatWorks() throws Exception {

// Act
Date result = converter.parse(value);
String value2 = converter.format(result);

// Assert
assertNotNull(result);

Calendar calendar = Calendar.getInstance();
calendar.setTime(result);
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
assertEquals("Year", 2012, calendar.get(Calendar.YEAR));
assertEquals("Month", 1, calendar.get(Calendar.MONTH) + 1);
assertEquals("Day", 12, calendar.get(Calendar.DAY_OF_MONTH));
assertEquals("Hour", 0, calendar.get(Calendar.HOUR));
assertEquals("Minute", 35, calendar.get(Calendar.MINUTE));
assertEquals("Second", 58, calendar.get(Calendar.SECOND));
assertEquals("Millisecond", 123, calendar.get(Calendar.MILLISECOND));

assertEquals("2012-01-12T00:35:58.123Z", value2);
}

@Test
public void mixedFormatWorks() throws Exception {
// Arrange
ISO8601DateConverter converter = new ISO8601DateConverter();
String value = "2012-01-12T00:35:58.12Z";

// Act
Date result = converter.parse(value);
String value2 = converter.format(result);

// Assert
assertNotNull(result);

Calendar calendar = Calendar.getInstance();
calendar.setTime(result);
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
assertEquals("Year", 2012, calendar.get(Calendar.YEAR));
assertEquals("Month", 1, calendar.get(Calendar.MONTH) + 1);
assertEquals("Day", 12, calendar.get(Calendar.DAY_OF_MONTH));
assertEquals("Hour", 0, calendar.get(Calendar.HOUR));
assertEquals("Minute", 35, calendar.get(Calendar.MINUTE));
assertEquals("Second", 58, calendar.get(Calendar.SECOND));
assertEquals("Millisecond", 120, calendar.get(Calendar.MILLISECOND));

assertEquals("2012-01-12T00:35:58.120Z", value2);
}

@Test
Expand All @@ -56,9 +113,11 @@ public void shortFormatRoundTrips() throws Exception {
// Act
Date result = converter.parse(value);
String value2 = converter.shortFormat(result);
String value3 = converter.format(result);

// Assert
assertNotNull(result);
assertEquals(value, value2);
assertEquals("2012-01-12T00:35:58.000Z", value3);
}
}