diff --git a/graphsdk/src/androidTest/java/com/microsoft/graph/serializer/DateOnlyTests.java b/graphsdk/src/androidTest/java/com/microsoft/graph/serializer/DateOnlyTests.java
new file mode 100644
index 00000000..1d79cbd6
--- /dev/null
+++ b/graphsdk/src/androidTest/java/com/microsoft/graph/serializer/DateOnlyTests.java
@@ -0,0 +1,32 @@
+package com.microsoft.graph.serializer;
+
+import android.test.AndroidTestCase;
+
+import com.microsoft.graph.model.DateOnly;
+
+public class DateOnlyTests extends AndroidTestCase {
+
+ public void testDateSerializer() throws Exception {
+ String strDate = DateOnly.parse("2016-04-27").toString();
+ assertEquals("2016-04-27", strDate);
+ }
+
+ public void testDateSerializerIndefinite() throws Exception {
+ String strDate = DateOnly.parse("0001-01-01").toString();
+ assertEquals("0001-01-01", strDate);
+ }
+
+ public void testDateDeserializer() throws Exception {
+ DateOnly date = DateOnly.parse("2016-04-27");
+ assertEquals(2016, date.getYear());
+ assertEquals(4, date.getMonth());
+ assertEquals(27, date.getDay());
+ }
+
+ public void testDateDeserializerIndefinite() throws Exception{
+ DateOnly date = DateOnly.parse("0001-01-01");
+ assertEquals(1, date.getYear());
+ assertEquals(1, date.getMonth());
+ assertEquals(1, date.getDay());
+ }
+}
diff --git a/graphsdk/src/androidTest/java/com/microsoft/graph/serializer/DefaultSerializerTests.java b/graphsdk/src/androidTest/java/com/microsoft/graph/serializer/DefaultSerializerTests.java
index a1119b29..4202d356 100644
--- a/graphsdk/src/androidTest/java/com/microsoft/graph/serializer/DefaultSerializerTests.java
+++ b/graphsdk/src/androidTest/java/com/microsoft/graph/serializer/DefaultSerializerTests.java
@@ -22,18 +22,22 @@
package com.microsoft.graph.serializer;
+import android.test.AndroidTestCase;
+
import com.microsoft.graph.extensions.Drive;
+import com.microsoft.graph.extensions.RecurrenceRangeType;
+import com.microsoft.graph.generated.BaseRecurrenceRange;
import com.microsoft.graph.logger.DefaultLogger;
-
-import android.test.AndroidTestCase;
+import com.microsoft.graph.model.DateOnly;
/**
* Test cases for the {@see DefaultSerializer}
*/
-public class DefaultSerializerTests extends AndroidTestCase {
+public class DefaultSerializerTests extends AndroidTestCase {
/**
* Make sure that deserializing a Drive also returns members from BaseDrive
+ *
* @throws Exception If there is an exception during the test
*/
public void testDriveDeserialization() throws Exception {
@@ -46,4 +50,36 @@ public void testDriveDeserialization() throws Exception {
assertEquals("8bf6ae90006c4a4c", result.id);
}
+
+ public void testRecurrenceRangeDeserialization() throws Exception {
+ final DefaultSerializer serializer = new DefaultSerializer(new DefaultLogger());
+ String source = "{\n" +
+ " \"type\": \"noEnd\",\n" +
+ " \"startDate\": \"2016-04-27\",\n" +
+ " \"endDate\": \"0001-01-01\",\n" +
+ " \"recurrenceTimeZone\": \"China Standard Time\",\n" +
+ " \"numberOfOccurrences\": 0\n" +
+ "}";
+ BaseRecurrenceRange baseRecurrenceRange = serializer.deserializeObject(source, BaseRecurrenceRange.class);
+ assertNotNull(source);
+ assertEquals(baseRecurrenceRange.type, RecurrenceRangeType.noEnd);
+ assertEquals("2016-04-27", baseRecurrenceRange.startDate.toString());
+ assertEquals("0001-01-01", baseRecurrenceRange.endDate.toString());
+ assertEquals("China Standard Time", baseRecurrenceRange.recurrenceTimeZone);
+ assertEquals(Integer.valueOf(0), baseRecurrenceRange.numberOfOccurrences);
+ }
+
+ public void testRecurrenceRangeSerialization() throws Exception {
+ final String expected = "{\"endDate\":\"2016-05-25\",\"numberOfOccurrences\":4,\"@odata.type\":\"microsoft.graph.recurrenceRange\",\"recurrenceTimeZone\":\"PST\",\"startDate\":\"2016-04-25\",\"type\":\"endDate\"}";
+ final DefaultSerializer serializer = new DefaultSerializer(new DefaultLogger());
+ BaseRecurrenceRange brr = new BaseRecurrenceRange();
+ brr.type = RecurrenceRangeType.endDate;
+ brr.startDate = new DateOnly(2016, 4, 25);
+ brr.endDate = new DateOnly(2016, 5, 25);
+ brr.recurrenceTimeZone = "PST";
+ brr.numberOfOccurrences = 4;
+ String jsonOut = serializer.serializeObject(brr);
+ assertNotNull(jsonOut);
+ assertEquals(jsonOut, expected);
+ }
}
diff --git a/graphsdk/src/main/java/com/microsoft/graph/generated/BaseRecurrenceRange.java b/graphsdk/src/main/java/com/microsoft/graph/generated/BaseRecurrenceRange.java
index d05f9301..8af39aaa 100644
--- a/graphsdk/src/main/java/com/microsoft/graph/generated/BaseRecurrenceRange.java
+++ b/graphsdk/src/main/java/com/microsoft/graph/generated/BaseRecurrenceRange.java
@@ -42,13 +42,13 @@ public BaseRecurrenceRange(){
* The Start Date.
*/
@SerializedName("startDate")
- public java.util.Calendar startDate;
+ public com.microsoft.graph.model.DateOnly startDate;
/**
* The End Date.
*/
@SerializedName("endDate")
- public java.util.Calendar endDate;
+ public com.microsoft.graph.model.DateOnly endDate;
/**
* The Recurrence Time Zone.
diff --git a/graphsdk/src/main/java/com/microsoft/graph/model/DateOnly.java b/graphsdk/src/main/java/com/microsoft/graph/model/DateOnly.java
new file mode 100644
index 00000000..b2facbe8
--- /dev/null
+++ b/graphsdk/src/main/java/com/microsoft/graph/model/DateOnly.java
@@ -0,0 +1,106 @@
+package com.microsoft.graph.model;
+
+
+import java.text.ParseException;
+import java.util.Locale;
+
+/**
+ * A timezone-nonspecific date
+ */
+public class DateOnly {
+
+ /**
+ * The year
+ */
+ private final int mYear;
+
+ /**
+ * The month
+ */
+ private final int mMonth;
+
+ /**
+ * The day
+ */
+ private final int mDay;
+
+ /**
+ * Constructs a timezone-nonspecific DateOnly
+ *
+ * @param dateStr date string of the form yyyy-mm-dd
+ * @return the parsed DateOnly instance
+ * @exception ParseException If there was a failure parsing the dateStr
+ */
+ public static DateOnly parse(final String dateStr) throws ParseException {
+ // break the date up into its constituent parts
+ String[] dateInfo = dateStr.split("-");
+
+ // validate the split date string
+ final int expectedLength = 3;
+ if (dateInfo.length != expectedLength) {
+ throw new ParseException(
+ "Expected datestring format 'yyyy-mm-dd' but found: " + dateStr, 0
+ );
+ }
+
+ // array indices for date parsing
+ final int indYear = 0;
+ final int indMonth = 1;
+ final int indDay = 2;
+
+ // unpack this array
+ int year = Integer.parseInt(dateInfo[indYear]);
+ int month = Integer.parseInt(dateInfo[indMonth]);
+ int day = Integer.parseInt(dateInfo[indDay]);
+
+ return new DateOnly(year, month, day);
+ }
+
+ /**
+ * Constructs a timezone-nonspecific DateOnly
+ *
+ * @param year the year
+ * @param month 1-indexed month value (Jan == 1)
+ * @param day day of the month
+ */
+ public DateOnly(final int year, final int month, final int day) {
+ mYear = year;
+ mMonth = month;
+ mDay = day;
+ }
+
+ /**
+ * Gets the year
+ *
+ * @return the year
+ */
+ public int getYear() {
+ return mYear;
+ }
+
+ /**
+ * Gets the month
+ *
+ * @return the month
+ */
+ public int getMonth() {
+ return mMonth;
+ }
+
+ /**
+ * Gets the day
+ *
+ * @return the day
+ */
+ public int getDay() {
+ return mDay;
+ }
+
+ @Override
+ public String toString() {
+ return String.format(
+ Locale.ROOT,
+ "%04d-%02d-%02d", mYear, mMonth, mDay
+ );
+ }
+}
diff --git a/graphsdk/src/main/java/com/microsoft/graph/serializer/GsonFactory.java b/graphsdk/src/main/java/com/microsoft/graph/serializer/GsonFactory.java
index fbc5446c..eeb80b93 100644
--- a/graphsdk/src/main/java/com/microsoft/graph/serializer/GsonFactory.java
+++ b/graphsdk/src/main/java/com/microsoft/graph/serializer/GsonFactory.java
@@ -1,16 +1,16 @@
// ------------------------------------------------------------------------------
// Copyright (c) 2015 Microsoft Corporation
-//
+//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
-//
+//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
-//
+//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -31,8 +31,8 @@
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
-
import com.microsoft.graph.logger.ILogger;
+import com.microsoft.graph.model.DateOnly;
import java.lang.reflect.Type;
import java.text.ParseException;
@@ -52,12 +52,13 @@ private GsonFactory() {
/**
* Creates an instance of Gson.
+ *
* @param logger The logger.
* @return The new instance.
*/
public static Gson getGsonInstance(final ILogger logger) {
- final JsonSerializer dateJsonSerializer = new JsonSerializer() {
+ final JsonSerializer calendarJsonSerializer = new JsonSerializer() {
@Override
public JsonElement serialize(final Calendar src,
final Type typeOfSrc,
@@ -74,7 +75,7 @@ public JsonElement serialize(final Calendar src,
}
};
- final JsonDeserializer dateJsonDeserializer = new JsonDeserializer() {
+ final JsonDeserializer calendarJsonDeserializer = new JsonDeserializer() {
@Override
public Calendar deserialize(final JsonElement json,
final Type typeOfT,
@@ -111,13 +112,43 @@ public JsonElement serialize(final byte[] src,
final JsonDeserializer byteArrayJsonDeserializer = new JsonDeserializer() {
@Override
public byte[] deserialize(final JsonElement json,
+ final Type typeOfT,
+ final JsonDeserializationContext context) throws JsonParseException {
+ if (json == null) {
+ return null;
+ }
+ try {
+ return ByteArraySerializer.deserialize(json.getAsString());
+ } catch (final ParseException e) {
+ logger.logError("Parsing issue on " + json.getAsString(), e);
+ return null;
+ }
+ }
+ };
+
+ final JsonSerializer dateJsonSerializer = new JsonSerializer() {
+ @Override
+ public JsonElement serialize(final DateOnly src,
+ final Type typeOfSrc,
+ final JsonSerializationContext context) {
+ if (src == null) {
+ return null;
+ }
+ return new JsonPrimitive(src.toString());
+ }
+ };
+
+ final JsonDeserializer dateJsonDeserializer = new JsonDeserializer() {
+ @Override
+ public DateOnly deserialize(final JsonElement json,
final Type typeOfT,
final JsonDeserializationContext context) throws JsonParseException {
if (json == null) {
return null;
}
+
try {
- return ByteArraySerializer.deserialize(json.getAsString());
+ return DateOnly.parse(json.getAsString());
} catch (final ParseException e) {
logger.logError("Parsing issue on " + json.getAsString(), e);
return null;
@@ -126,12 +157,14 @@ public byte[] deserialize(final JsonElement json,
};
return new GsonBuilder()
- .registerTypeAdapter(Calendar.class, dateJsonSerializer)
- .registerTypeAdapter(Calendar.class, dateJsonDeserializer)
- .registerTypeAdapter(GregorianCalendar.class, dateJsonSerializer)
- .registerTypeAdapter(GregorianCalendar.class, dateJsonDeserializer)
+ .registerTypeAdapter(Calendar.class, calendarJsonSerializer)
+ .registerTypeAdapter(Calendar.class, calendarJsonDeserializer)
+ .registerTypeAdapter(GregorianCalendar.class, calendarJsonSerializer)
+ .registerTypeAdapter(GregorianCalendar.class, calendarJsonDeserializer)
.registerTypeAdapter(byte[].class, byteArrayJsonDeserializer)
.registerTypeAdapter(byte[].class, byteArrayJsonSerializer)
+ .registerTypeAdapter(DateOnly.class, dateJsonSerializer)
+ .registerTypeAdapter(DateOnly.class, dateJsonDeserializer)
.registerTypeAdapterFactory(new FallBackEnumTypeAdapter())
.create();
}