Skip to content

Commit

Permalink
Fix date parsing to correctly handle RFC3339 timezone format (#693)
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Willer authored Apr 6, 2019
1 parent a9e940f commit 391171a
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 46 deletions.
18 changes: 2 additions & 16 deletions src/main/java/com/box/sdk/BoxDateFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public final class BoxDateFormat {
private static final ThreadLocal<DateFormat> THREAD_LOCAL_DATE_FORMAT = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
return sdf;
}
Expand All @@ -28,7 +28,7 @@ private BoxDateFormat() { }
* @throws ParseException if the string cannot be parsed into a valid date.
*/
public static Date parse(String dateString) throws ParseException {
return THREAD_LOCAL_DATE_FORMAT.get().parse(fixIso8601TimeZone(dateString));
return THREAD_LOCAL_DATE_FORMAT.get().parse(dateString);
}

/**
Expand All @@ -40,18 +40,4 @@ public static String format(Date date) {
return THREAD_LOCAL_DATE_FORMAT.get().format(date);
}

/**
* Helper function to handle ISO 8601 strings of the following format:
* "2008-03-01T13:00:00+01:00". Note that the final colon (":") in the
* time zone is not supported by SimpleDateFormat's "Z" token.
*
* @param dateString a string containing the date.
* @return a date string that matches the date format.
*/
private static String fixIso8601TimeZone(String dateString) {
if (dateString.length() >= 24 && dateString.charAt(22) == ':') {
return dateString.substring(0, 22) + dateString.substring(23);
}
return dateString;
}
}
2 changes: 1 addition & 1 deletion src/test/Fixtures/BoxTask/GetAllTasksOnFile200.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"sha1": "7ea91497ad7351d80f3a8439ae3d89dcc2675d27",
"name": "Sample.pdf"
},
"due_at": null
"due_at": "2019-05-01T00:00:00Z"
}
]
}
64 changes: 64 additions & 0 deletions src/test/java/com/box/sdk/BoxDateFormatTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.box.sdk;

import java.text.ParseException;
import java.util.Date;

import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.categories.Category;

public class BoxDateFormatTest {

@Test
@Category(UnitTest.class)
public void testParseWorksWithOffsetTimezone() throws ParseException {

Date date = BoxDateFormat.parse("2019-04-06T15:57:01-07:00");
Date expectedDate = new Date(1554591421000L);
Assert.assertEquals(expectedDate, date);
}

@Test
@Category(UnitTest.class)
public void testParseWorksWithZuluTimezone() throws ParseException {

Date date = BoxDateFormat.parse("2019-04-06T22:58:49Z");
Date expectedDate = new Date(1554591529000L);
Assert.assertEquals(expectedDate, date);
}

@Test
@Category(UnitTest.class)
public void testParseWorksWithZeroOffsetTimezone() throws ParseException {

Date date = BoxDateFormat.parse("2019-04-06T22:58:49+00:00");
Date expectedDate = new Date(1554591529000L);
Assert.assertEquals(expectedDate, date);
}

@Test
@Category(UnitTest.class)
public void testParseWorksWithMinusZeroOffsetTimezone() throws ParseException {

Date date = BoxDateFormat.parse("2019-04-06T22:58:49-00:00");
Date expectedDate = new Date(1554591529000L);
Assert.assertEquals(expectedDate, date);
}

@Test
@Category(UnitTest.class)
public void testParseWorksWithRFC822ZeroOffsetTimezone() throws ParseException {

Date date = BoxDateFormat.parse("2019-04-06T22:58:49+0000");
Date expectedDate = new Date(1554591529000L);
Assert.assertEquals(expectedDate, date);
}

@Test
@Category(UnitTest.class)
public void testFormatOutputsZuluTimezone() {
Date date = new Date(1554591421000L);
String expectedString = "2019-04-06T22:57:01Z";
Assert.assertEquals(expectedString, BoxDateFormat.format(date));
}
}
24 changes: 12 additions & 12 deletions src/test/java/com/box/sdk/BoxEventTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,22 @@ public class BoxEventTest {
public void testIsEventLogUnique() throws IOException, ParseException {
String getResult = "";
final String eventURL = "/events";
String startTime = "2019-02-02T21:48:38+0000";
String endTime = "2019-02-02T23:48:40+0000";
String startTime = "2019-02-02T21:48:38Z";
String endTime = "2019-02-02T23:48:40Z";

getResult = TestConfig.getFixture("BoxEvent/GetEnterpriseEvents200");

WIRE_MOCK_CLASS_RULE.stubFor(WireMock.get(WireMock.urlPathEqualTo(eventURL))
.withQueryParam("stream_type", WireMock.equalTo("admin_logs"))
.withQueryParam("limit", WireMock.equalTo("500"))
.withQueryParam("created_after", WireMock.equalTo("2019-02-02T21:48:38+0000"))
.withQueryParam("created_before", WireMock.equalTo("2019-02-02T23:48:40+0000"))
.withQueryParam("created_after", WireMock.equalTo("2019-02-02T21:48:38Z"))
.withQueryParam("created_before", WireMock.equalTo("2019-02-02T23:48:40Z"))
.willReturn(WireMock.aResponse()
.withHeader("Content-Type", "application/json")
.withBody(getResult)));

Date startDate = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ").parse(startTime);
Date endDate = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ").parse(endTime);
Date startDate = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssX").parse(startTime);
Date endDate = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssX").parse(endTime);
EventLog eventLog = EventLog.getEnterpriseEvents(this.api, startDate, endDate);
Assert.assertTrue(eventLog.getSize() == 1);
}
Expand All @@ -55,22 +55,22 @@ public void testIsEventLogUnique() throws IOException, ParseException {
public void testEventLog() throws IOException, ParseException {
String getResult = "";
final String eventURL = "/events";
String startTime = "2019-02-02T21:48:38+0000";
String endTime = "2019-02-02T23:48:40+0000";
String startTime = "2019-02-02T21:48:38Z";
String endTime = "2019-02-02T23:48:40Z";

getResult = TestConfig.getFixture("BoxEvent/GetEnterpriseEvents200");

WIRE_MOCK_CLASS_RULE.stubFor(WireMock.get(WireMock.urlPathEqualTo(eventURL))
.withQueryParam("stream_type", WireMock.equalTo("admin_logs"))
.withQueryParam("limit", WireMock.equalTo("500"))
.withQueryParam("created_after", WireMock.equalTo("2019-02-02T21:48:38+0000"))
.withQueryParam("created_before", WireMock.equalTo("2019-02-02T23:48:40+0000"))
.withQueryParam("created_after", WireMock.equalTo("2019-02-02T21:48:38Z"))
.withQueryParam("created_before", WireMock.equalTo("2019-02-02T23:48:40Z"))
.willReturn(WireMock.aResponse()
.withHeader("Content-Type", "application/json")
.withBody(getResult)));

Date startDate = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ").parse(startTime);
Date endDate = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ").parse(endTime);
Date startDate = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssX").parse(startTime);
Date endDate = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssX").parse(endTime);
EventLog eventLog = EventLog.getEnterpriseEvents(this.api, startDate, endDate);
BoxEvent event = eventLog.iterator().next();
Assert.assertEquals("54321", event.getActionBy().getID());
Expand Down
8 changes: 4 additions & 4 deletions src/test/java/com/box/sdk/BoxFileVersionRetentionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ public void testGetRetentionsSendsCorrectRequest() throws ParseException {
final String urlString = "https://api.box.com/2.0/file_version_retentions"
+ "?file_id=0&file_version_id=1&policy_id=2"
+ "&disposition_action=permanently_delete"
+ "&disposition_before=2016-09-15T13%3A15%3A35%2B0000"
+ "&disposition_after=2014-09-15T13%3A15%3A35%2B0000"
+ "&disposition_before=2016-09-15T13%3A15%3A35Z"
+ "&disposition_after=2014-09-15T13%3A15%3A35Z"
+ "&fields=file%2Capplied_at"
+ "&limit=100";

Expand All @@ -156,8 +156,8 @@ public String getJSON() {
.addFileVersionID("1")
.addPolicyID("2")
.addDispositionAction(BoxRetentionPolicy.ACTION_PERMANENTLY_DELETE)
.addDispositionBefore(BoxDateFormat.parse("2016-09-15T13:15:35+0000"))
.addDispositionAfter(BoxDateFormat.parse("2014-09-15T13:15:35+0000"));
.addDispositionBefore(BoxDateFormat.parse("2016-09-15T13:15:35Z"))
.addDispositionAfter(BoxDateFormat.parse("2014-09-15T13:15:35Z"));

Iterator<BoxFileVersionRetention.Info> iterator
= BoxFileVersionRetention.getRetentions(api, filter, "file", "applied_at").iterator();
Expand Down
6 changes: 3 additions & 3 deletions src/test/java/com/box/sdk/BoxLegalHoldPolicyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ public void testCreateNewLegalHoldPolicyWithDateFilters() throws IOException, Pa
final String createdByName = "Test User";
final String createdByLogin = "testuser@example.com";
final String policyName = "Trial Documents";
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
final String startTimeString = "2018-04-25T23:37:05+0000";
final String endTimeString = "2020-04-25T23:37:05+0000";
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
final String startTimeString = "2018-04-25T23:37:05Z";
final String endTimeString = "2020-04-25T23:37:05Z";
final Date startTime = dateFormat.parse("2018-04-25T16:37:05-07:00");
final Date endTime = dateFormat.parse("2020-04-25T16:37:05-07:00");

Expand Down
20 changes: 10 additions & 10 deletions src/test/java/com/box/sdk/BoxSearchParametersTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,10 @@ public void shouldCorrectlySetAndGetTrashContentParam() {
@Category(UnitTest.class)
public void shouldCorrectlySetAndGetCreatedRangeParam() {
BoxSearchParameters searchParams = new BoxSearchParameters();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String createdFromDateString = "2016-01-01T00:00:00+0000";
String createdToDateString = "2016-04-01T00:00:00+0000";
String createdFromDateString = "2016-01-01T00:00:00Z";
String createdToDateString = "2016-04-01T00:00:00Z";

try {
Date createdFromDate = sdf.parse(createdFromDateString);
Expand All @@ -165,19 +165,19 @@ public void shouldCorrectlySetAndGetCreatedRangeParam() {
QueryStringBuilder queryParams = searchParams.getQueryParameters();

Assert.assertEquals(
queryParams.toString(),
"?query=query&created_at_range=2016-01-01T00%3A00%3A00%2B0000%2C2016-04-01T00%3A00%3A00%2B0000"
"?query=query&created_at_range=2016-01-01T00%3A00%3A00Z%2C2016-04-01T00%3A00%3A00Z",
queryParams.toString()
);
}

@Test
@Category(UnitTest.class)
public void shouldCorrectlySetAndGetUpdatedRangeParam() {
BoxSearchParameters searchParams = new BoxSearchParameters();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String updatedFromDateString = "2016-01-01T00:00:00+0000";
String updatedToDateString = "2016-04-01T00:00:00+0000";
String updatedFromDateString = "2016-01-01T00:00:00Z";
String updatedToDateString = "2016-04-01T00:00:00Z";

try {
Date updatedFromDate = sdf.parse(updatedFromDateString);
Expand All @@ -190,8 +190,8 @@ public void shouldCorrectlySetAndGetUpdatedRangeParam() {
QueryStringBuilder queryParams = searchParams.getQueryParameters();

Assert.assertEquals(
queryParams.toString(),
"?query=query&updated_at_range=2016-01-01T00%3A00%3A00%2B0000%2C2016-04-01T00%3A00%3A00%2B0000"
"?query=query&updated_at_range=2016-01-01T00%3A00%3A00Z%2C2016-04-01T00%3A00%3A00Z",
queryParams.toString()
);
}

Expand Down

0 comments on commit 391171a

Please sign in to comment.