OLINGO-864: Refining the Edm.Date and Edm.Time behavior not to assume GMT but use default timezone of the JVM
This commit is contained in:
commit
7b26cc6ee7
|
@ -25,8 +25,12 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.olingo.commons.api.format.ContentType;
|
||||
import org.apache.olingo.server.tecsvc.data.DataProvider;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
|
@ -63,4 +67,14 @@ public abstract class AbstractParamTecSvcITCase extends AbstractTecSvcITCase {
|
|||
assertTrue(n instanceof Number);
|
||||
assertEquals(value, ((Number) n).intValue());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
|
||||
}
|
||||
|
||||
@After
|
||||
public void teardown() {
|
||||
TimeZone.setDefault(TimeZone.getDefault());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
package org.apache.olingo.commons.core.edm.primitivetype;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -48,7 +47,7 @@ public final class EdmDate extends SingletonPrimitiveType {
|
|||
final Boolean isNullable, final Integer maxLength, final Integer precision,
|
||||
final Integer scale, final Boolean isUnicode, final Class<T> returnType) throws EdmPrimitiveTypeException {
|
||||
|
||||
final Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
||||
final Calendar dateTimeValue = Calendar.getInstance();
|
||||
dateTimeValue.clear();
|
||||
|
||||
final Matcher matcher = PATTERN.matcher(value);
|
||||
|
@ -75,7 +74,7 @@ public final class EdmDate extends SingletonPrimitiveType {
|
|||
final Boolean isNullable, final Integer maxLength, final Integer precision,
|
||||
final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
|
||||
|
||||
final Calendar dateTimeValue = EdmDateTimeOffset.createDateTime(value);
|
||||
final Calendar dateTimeValue = EdmDateTimeOffset.createDateTime(value, true);
|
||||
|
||||
final StringBuilder result = new StringBuilder(10); // Ten characters are enough for "normal" dates.
|
||||
final int year = dateTimeValue.get(Calendar.YEAR);
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.apache.olingo.commons.core.edm.primitivetype;
|
||||
|
||||
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
|
||||
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Calendar;
|
||||
|
@ -26,7 +28,6 @@ import java.util.TimeZone;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
|
||||
|
||||
/**
|
||||
* Implementation of the EDM primitive type DateTimeOffset.
|
||||
|
@ -61,7 +62,8 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
|
|||
|
||||
final String timeZoneOffset = matcher.group(9) == null || matcher.group(10) == null
|
||||
|| matcher.group(10).matches("[-+]0+:0+") ? null : matcher.group(10);
|
||||
final Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT" + timeZoneOffset));
|
||||
final TimeZone tz = TimeZone.getTimeZone("GMT" + ((timeZoneOffset == null) ? "" : timeZoneOffset));
|
||||
final Calendar dateTimeValue = Calendar.getInstance(tz);
|
||||
if (dateTimeValue.get(Calendar.ZONE_OFFSET) == 0 && timeZoneOffset != null) {
|
||||
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
|
||||
}
|
||||
|
@ -109,6 +111,7 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
|
|||
|
||||
/**
|
||||
* Converts a {@link Calendar} value into the requested return type if possible.
|
||||
* <br>It is expected that the {@link Calendar} value will already be in the desired time zone.
|
||||
*
|
||||
* @param dateTimeValue the value
|
||||
* @param nanoSeconds nanoseconds part of the value; only used for the {@link Timestamp} return type
|
||||
|
@ -141,8 +144,20 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
|
|||
Timestamp timestamp = new Timestamp(dateTimeValue.getTimeInMillis());
|
||||
timestamp.setNanos(nanoSeconds);
|
||||
return returnType.cast(timestamp);
|
||||
} else if(returnType.isAssignableFrom(Time.class)) {
|
||||
return returnType.cast(new Time(dateTimeValue.getTimeInMillis()));
|
||||
} else if (returnType.isAssignableFrom(Time.class)) {
|
||||
//normalize the value
|
||||
dateTimeValue.set(Calendar.YEAR, 1970);
|
||||
dateTimeValue.set(Calendar.MONTH, Calendar.JANUARY);
|
||||
dateTimeValue.set(Calendar.DAY_OF_MONTH, 1);
|
||||
dateTimeValue.set(Calendar.MILLISECOND, 0);
|
||||
return returnType.cast(new Time(dateTimeValue.getTimeInMillis())); // may throw IllegalArgumentException
|
||||
} else if (returnType.isAssignableFrom(java.sql.Date.class)) {
|
||||
//normalize the value
|
||||
dateTimeValue.set(Calendar.HOUR_OF_DAY, 0);
|
||||
dateTimeValue.set(Calendar.MINUTE, 0);
|
||||
dateTimeValue.set(Calendar.SECOND, 0);
|
||||
dateTimeValue.set(Calendar.MILLISECOND, 0);
|
||||
return returnType.cast(new java.sql.Date(dateTimeValue.getTimeInMillis())); // may throw IllegalArgumentException
|
||||
} else {
|
||||
throw new ClassCastException("unsupported return type " + returnType.getSimpleName());
|
||||
}
|
||||
|
@ -153,16 +168,9 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
|
|||
final Boolean isNullable, final Integer maxLength, final Integer precision,
|
||||
final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
|
||||
|
||||
Calendar dateTimeValue;
|
||||
if (value instanceof Timestamp) {
|
||||
final Calendar tmp = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
||||
tmp.setTimeInMillis(((Timestamp) value).getTime());
|
||||
dateTimeValue = createDateTime(tmp);
|
||||
} else {
|
||||
dateTimeValue = createDateTime(value);
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
final Calendar dateTimeValue = createDateTime(value, false);
|
||||
|
||||
final StringBuilder result = new StringBuilder();
|
||||
final int year = dateTimeValue.get(Calendar.YEAR);
|
||||
appendTwoDigits(result, year / 100);
|
||||
appendTwoDigits(result, year % 100);
|
||||
|
@ -203,21 +211,27 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
|
|||
* @return the value as {@link Calendar}
|
||||
* @throws EdmPrimitiveTypeException if the type of the value is not supported
|
||||
*/
|
||||
protected static <T> Calendar createDateTime(final T value) throws EdmPrimitiveTypeException {
|
||||
protected static <T> Calendar createDateTime(final T value, boolean isLocal) throws EdmPrimitiveTypeException {
|
||||
Calendar dateTimeValue;
|
||||
if(value instanceof Time) {
|
||||
dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
||||
dateTimeValue.setTimeInMillis(((Time) value).getTime());
|
||||
} else if (value instanceof Date) {
|
||||
// Although java.util.Date, as stated in its documentation,
|
||||
// "is intended to reflect coordinated universal time (UTC)",
|
||||
// its getName() method uses the default time zone. And so do we.
|
||||
dateTimeValue = Calendar.getInstance();
|
||||
if (value instanceof Date) {
|
||||
TimeZone tz;
|
||||
if (isLocal) {
|
||||
tz = TimeZone.getDefault();
|
||||
} else {
|
||||
tz = TimeZone.getTimeZone("GMT");
|
||||
}
|
||||
dateTimeValue = Calendar.getInstance(tz);
|
||||
dateTimeValue.setTime((Date) value);
|
||||
} else if (value instanceof Calendar) {
|
||||
dateTimeValue = (Calendar) ((Calendar) value).clone();
|
||||
} else if (value instanceof Long) {
|
||||
dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
||||
TimeZone tz;
|
||||
if (isLocal) {
|
||||
tz = TimeZone.getDefault();
|
||||
} else {
|
||||
tz = TimeZone.getTimeZone("GMT");
|
||||
}
|
||||
dateTimeValue = Calendar.getInstance(tz);
|
||||
dateTimeValue.setTimeInMillis((Long) value);
|
||||
} else {
|
||||
throw new EdmPrimitiveTypeException("The value type " + value.getClass() + " is not supported.");
|
||||
|
|
|
@ -20,7 +20,6 @@ package org.apache.olingo.commons.core.edm.primitivetype;
|
|||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -52,7 +51,7 @@ public final class EdmTimeOfDay extends SingletonPrimitiveType {
|
|||
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
|
||||
}
|
||||
|
||||
final Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
||||
final Calendar dateTimeValue = Calendar.getInstance();
|
||||
dateTimeValue.clear();
|
||||
dateTimeValue.set(Calendar.HOUR_OF_DAY, Byte.parseByte(matcher.group(1)));
|
||||
dateTimeValue.set(Calendar.MINUTE, Byte.parseByte(matcher.group(2)));
|
||||
|
@ -92,18 +91,8 @@ public final class EdmTimeOfDay extends SingletonPrimitiveType {
|
|||
final Boolean isNullable, final Integer maxLength, final Integer precision,
|
||||
final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
|
||||
|
||||
final Calendar dateTimeValue;
|
||||
final int fractionalSecs;
|
||||
if (value instanceof Timestamp) {
|
||||
final Calendar tmp = Calendar.getInstance();
|
||||
tmp.setTimeInMillis(((Timestamp) value).getTime());
|
||||
dateTimeValue = EdmDateTimeOffset.createDateTime(tmp);
|
||||
fractionalSecs = ((Timestamp) value).getNanos();
|
||||
} else {
|
||||
dateTimeValue = EdmDateTimeOffset.createDateTime(value);
|
||||
fractionalSecs = dateTimeValue.get(Calendar.MILLISECOND);
|
||||
}
|
||||
|
||||
final Calendar dateTimeValue = EdmDateTimeOffset.createDateTime(value, true);
|
||||
|
||||
final StringBuilder result = new StringBuilder();
|
||||
EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.HOUR_OF_DAY));
|
||||
result.append(':');
|
||||
|
@ -112,7 +101,8 @@ public final class EdmTimeOfDay extends SingletonPrimitiveType {
|
|||
EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.SECOND));
|
||||
|
||||
try {
|
||||
EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, value instanceof Timestamp, precision);
|
||||
EdmDateTimeOffset.appendFractionalSeconds(result,
|
||||
dateTimeValue.get(Calendar.MILLISECOND), value instanceof Timestamp, precision);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
throw new EdmPrimitiveTypeException("The value '" + value + "' does not match the facets' constraints.", e);
|
||||
}
|
||||
|
|
|
@ -67,7 +67,6 @@ public class EdmDateTest extends PrimitiveTypeBaseTest {
|
|||
public void valueOfString() throws Exception {
|
||||
Calendar dateTime = Calendar.getInstance();
|
||||
dateTime.clear();
|
||||
dateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
dateTime.set(2012, 1, 29);
|
||||
assertEquals(dateTime, instance.valueOfString("2012-02-29", null, null, null, null, null, Calendar.class));
|
||||
assertEquals(Long.valueOf(dateTime.getTimeInMillis()), instance.valueOfString("2012-02-29", null, null, null, null,
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
package org.apache.olingo.commons.core.edm.primitivetype;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
|
@ -82,8 +81,7 @@ public class EdmDateTimeOffsetTest extends PrimitiveTypeBaseTest {
|
|||
assertEquals("1969-12-31T23:59:59.98Z", instance.valueToString(new Time(-20L), null, null, 2, null, null));
|
||||
|
||||
final Date date = new Date(millis);
|
||||
final String time = date.toString().substring(11, 19);
|
||||
assertTrue(instance.valueToString(date, null, null, 3, null, null).contains(time));
|
||||
assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(date, null, null, 3, null, null));
|
||||
|
||||
Timestamp timestamp = new Timestamp(0);
|
||||
timestamp.setNanos(120);
|
||||
|
@ -136,9 +134,10 @@ public class EdmDateTimeOffsetTest extends PrimitiveTypeBaseTest {
|
|||
|
||||
assertEquals(new Time(120000L), instance.valueOfString("1970-01-01T00:02", null, null, null, null, null,
|
||||
Time.class));
|
||||
assertEquals(new Time(12L), instance.valueOfString("1970-01-01T00:00:00.012", null, null, 3, null, null,
|
||||
// 0L because java.sql.Time does not keep track of fraction of milliseconds
|
||||
assertEquals(new Time(0L), instance.valueOfString("1970-01-01T00:00:00.012", null, null, 3, null, null,
|
||||
Time.class));
|
||||
assertEquals(new Time(120L), instance.valueOfString("1970-01-01T00:00:00.12", null, null, 2, null, null,
|
||||
assertEquals(new Time(0L), instance.valueOfString("1970-01-01T00:00:00.12", null, null, 2, null, null,
|
||||
Time.class));
|
||||
|
||||
expectFacetsErrorInValueOfString(instance, "2012-02-29T23:32:02.9Z", null, null, null, null, null);
|
||||
|
|
|
@ -62,11 +62,27 @@ public class EdmTimeOfDayTest extends PrimitiveTypeBaseTest {
|
|||
expectTypeErrorInValueToString(instance, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueToStringWithGMT() throws Exception {
|
||||
Calendar dateTime = Calendar.getInstance();
|
||||
dateTime.clear();
|
||||
dateTime.setTimeZone(TimeZone.getTimeZone("GMT+11:30"));
|
||||
dateTime.set(1, 2, 3, 4, 5, 6);
|
||||
assertEquals("04:05:06", instance.valueToString(dateTime, null, null, null, null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoundTripTime() throws Exception {
|
||||
java.sql.Time time = instance.valueOfString("04:05:06.002", true,
|
||||
4000, 3, 0, true, java.sql.Time.class);
|
||||
String val = instance.valueToString(time, true, 4000, 3, 0, true);
|
||||
assertEquals("04:05:06", val);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toTimeObject() throws Exception {
|
||||
Calendar dateTime = Calendar.getInstance();
|
||||
dateTime.clear();
|
||||
dateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
dateTime.set(Calendar.HOUR, 12);
|
||||
|
||||
Time timeValue = instance.valueOfString("12:00:00", null, null, null, null, null, Time.class);
|
||||
|
@ -75,7 +91,7 @@ public class EdmTimeOfDayTest extends PrimitiveTypeBaseTest {
|
|||
|
||||
@Test
|
||||
public void fromTimeObject() throws Exception {
|
||||
Calendar dateTime = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
||||
Calendar dateTime = Calendar.getInstance();
|
||||
dateTime.clear();
|
||||
dateTime.set(Calendar.HOUR, 5);
|
||||
dateTime.set(Calendar.MINUTE, 59);
|
||||
|
@ -84,12 +100,11 @@ public class EdmTimeOfDayTest extends PrimitiveTypeBaseTest {
|
|||
Time time = new Time(dateTime.getTimeInMillis());
|
||||
assertEquals("05:59:23", instance.valueToString(time, null, null, null, null, null));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void valueOfString() throws Exception {
|
||||
Calendar dateTime = Calendar.getInstance();
|
||||
dateTime.clear();
|
||||
dateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
|
||||
assertEquals(dateTime, instance.valueOfString("00:00", null, null, null, null, null, Calendar.class));
|
||||
assertEquals(dateTime, instance.valueOfString("00:00:00", null, null, null, null, null, Calendar.class));
|
||||
|
|
|
@ -28,7 +28,6 @@ import java.util.Calendar;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.olingo.commons.api.Constants;
|
||||
|
@ -1187,9 +1186,10 @@ public class DataCreator {
|
|||
|
||||
protected static Calendar getDateTime(final int year, final int month, final int day,
|
||||
final int hour, final int minute, final int second) {
|
||||
Calendar dateTime = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
||||
Calendar dateTime = Calendar.getInstance();
|
||||
dateTime.clear();
|
||||
dateTime.set(year, month - 1, day, hour, minute, second);
|
||||
dateTime.set(Calendar.MILLISECOND, 0);
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
|
@ -1201,8 +1201,12 @@ public class DataCreator {
|
|||
}
|
||||
|
||||
protected static Calendar getTime(final int hour, final int minute, final int second) {
|
||||
Calendar time = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
||||
Calendar time = Calendar.getInstance();
|
||||
time.clear();
|
||||
time.set(Calendar.YEAR, 1970);
|
||||
time.set(Calendar.MONTH, Calendar.JANUARY);
|
||||
time.set(Calendar.DAY_OF_MONTH, 1);
|
||||
time.set(Calendar.MILLISECOND, 0);
|
||||
time.set(Calendar.HOUR_OF_DAY, hour);
|
||||
time.set(Calendar.MINUTE, minute);
|
||||
time.set(Calendar.SECOND, second);
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.apache.olingo.server.tecsvc.data;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.olingo.commons.api.data.ComplexValue;
|
||||
import org.apache.olingo.commons.api.data.Entity;
|
||||
|
@ -33,7 +34,9 @@ import org.apache.olingo.server.api.OData;
|
|||
import org.apache.olingo.server.api.edmx.EdmxReference;
|
||||
import org.apache.olingo.server.api.uri.UriParameter;
|
||||
import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
|
@ -52,6 +55,16 @@ public class DataProviderTest {
|
|||
private final EdmEntitySet esMixPrimCollComp = entityContainer.getEntitySet("ESMixPrimCollComp");
|
||||
private final EdmEntitySet esMedia = entityContainer.getEntitySet("ESMedia");
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
|
||||
}
|
||||
|
||||
@After
|
||||
public void teardown() {
|
||||
TimeZone.setDefault(TimeZone.getDefault());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void esAllPrimEntity() throws Exception {
|
||||
final DataProvider dataProvider = new DataProvider(oData, edm);
|
||||
|
@ -82,6 +95,7 @@ public class DataProviderTest {
|
|||
mockParameter("PropertySByte", "127"),
|
||||
mockParameter("PropertyString", "'First'"),
|
||||
mockParameter("PropertyTimeOfDay", "02:48:21"))));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.io.InputStream;
|
|||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.olingo.commons.api.data.ComplexValue;
|
||||
|
@ -62,7 +63,9 @@ import org.apache.olingo.server.tecsvc.MetadataETagSupport;
|
|||
import org.apache.olingo.server.tecsvc.data.DataProvider;
|
||||
import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
|
@ -78,6 +81,16 @@ public class ODataJsonSerializerTest {
|
|||
new ODataJsonSerializer(ContentType.create(ContentType.JSON, ContentType.PARAMETER_IEEE754_COMPATIBLE, "true"));
|
||||
private final UriHelper helper = odata.createUriHelper();
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
|
||||
}
|
||||
|
||||
@After
|
||||
public void teardown() {
|
||||
TimeZone.setDefault(TimeZone.getDefault());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void entitySimple() throws Exception {
|
||||
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
|
||||
|
|
Loading…
Reference in New Issue