Skip to content

Commit 82b76c4

Browse files
Merge pull request #84 from ParsePlatform/richardross.datetimeformat.strict
Support any number of trailing zeroes when decoding dates.
2 parents 6c42a8d + 7cd0eab commit 82b76c4

File tree

7 files changed

+53
-9
lines changed

7 files changed

+53
-9
lines changed

Parse/Internal/FacebookAuthenticationProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public IDictionary<string, object> GetAuthData(string facebookId, string accessT
5656
return new Dictionary<string, object> {
5757
{"id", facebookId},
5858
{"access_token", accessToken},
59-
{"expiration_date", expiration.ToString(ParseClient.DateFormatString)}
59+
{"expiration_date", expiration.ToString(ParseClient.DateFormatStrings.First())}
6060
};
6161
}
6262

Parse/Internal/Installation/Controller/ParseCurrentInstallationController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ public Task SetAsync(ParseInstallation installation, CancellationToken cancellat
4141
var data = installation.ServerDataToJSONObjectForSerialization();
4242
data["objectId"] = installation.ObjectId;
4343
if (installation.CreatedAt != null) {
44-
data["createdAt"] = installation.CreatedAt.Value.ToString(ParseClient.DateFormatString);
44+
data["createdAt"] = installation.CreatedAt.Value.ToString(ParseClient.DateFormatStrings.First());
4545
}
4646
if (installation.UpdatedAt != null) {
47-
data["updatedAt"] = installation.UpdatedAt.Value.ToString(ParseClient.DateFormatString);
47+
data["updatedAt"] = installation.UpdatedAt.Value.ToString(ParseClient.DateFormatStrings.First());
4848
}
4949

5050
ParseClient.ApplicationSettings["CurrentInstallation"] = Json.Encode(data);

Parse/Internal/ParseDecoder.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,9 @@ internal static DateTime ParseDate(string input) {
9797
// TODO(hallucinogen): Figure out if we should be more flexible with the date formats
9898
// we accept.
9999
return DateTime.ParseExact(input,
100-
ParseClient.DateFormatString,
101-
CultureInfo.InvariantCulture);
100+
ParseClient.DateFormatStrings,
101+
CultureInfo.InvariantCulture,
102+
DateTimeStyles.None);
102103
}
103104
}
104105
}

Parse/Internal/ParseEncoder.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System;
44
using System.Collections.Generic;
55
using System.Globalization;
6+
using System.Linq;
67

78
namespace Parse.Internal {
89
/// <summary>
@@ -31,7 +32,7 @@ public object Encode(object value) {
3132
// encoded object. Otherwise, just return the original object.
3233
if (value is DateTime) {
3334
return new Dictionary<string, object> {
34-
{"iso", ((DateTime)value).ToString(ParseClient.DateFormatString)},
35+
{"iso", ((DateTime)value).ToString(ParseClient.DateFormatStrings.First())},
3536
{"__type", "Date"}
3637
};
3738
}

Parse/Internal/User/Controller/ParseCurrentUserController.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
using System;
44
using System.Collections.Generic;
5+
using System.Linq;
56
using System.Threading;
67
using System.Threading.Tasks;
78

@@ -34,10 +35,10 @@ public Task SetAsync(ParseUser user, CancellationToken cancellationToken) {
3435
var data = user.ServerDataToJSONObjectForSerialization();
3536
data["objectId"] = user.ObjectId;
3637
if (user.CreatedAt != null) {
37-
data["createdAt"] = user.CreatedAt.Value.ToString(ParseClient.DateFormatString);
38+
data["createdAt"] = user.CreatedAt.Value.ToString(ParseClient.DateFormatStrings.First());
3839
}
3940
if (user.UpdatedAt != null) {
40-
data["updatedAt"] = user.UpdatedAt.Value.ToString(ParseClient.DateFormatString);
41+
data["updatedAt"] = user.UpdatedAt.Value.ToString(ParseClient.DateFormatStrings.First());
4142
}
4243

4344
ParseClient.ApplicationSettings["CurrentUser"] = Json.Encode(data);

Parse/ParseClient.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,16 @@ namespace Parse {
1818
/// configuration for the Parse library.
1919
/// </summary>
2020
public static partial class ParseClient {
21-
internal const string DateFormatString = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'";
21+
internal static readonly string[] DateFormatStrings = {
22+
// Official ISO format
23+
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'",
24+
25+
// It's possible that the string converter server-side may trim trailing zeroes,
26+
// so these two formats cover ourselves from that.
27+
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ff'Z'",
28+
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'f'Z'",
29+
};
30+
2231

2332
private static readonly object mutex = new object();
2433
private static readonly string[] assemblyNames = {

ParseTest.Unit/DecoderTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,38 @@ public void TestDecodeDate() {
5656
Assert.AreEqual(0, dateTime.Millisecond);
5757
}
5858

59+
[Test]
60+
public void TestDecodeImproperDate() {
61+
IDictionary<string, object> value = new Dictionary<string, object>() {
62+
{ "__type", "Date" },
63+
{ "iso", "1990-08-30T12:03:59.0Z" }
64+
};
65+
66+
DateTime dateTime = (DateTime)ParseDecoder.Instance.Decode(value);
67+
Assert.AreEqual(1990, dateTime.Year);
68+
Assert.AreEqual(8, dateTime.Month);
69+
Assert.AreEqual(30, dateTime.Day);
70+
Assert.AreEqual(12, dateTime.Hour);
71+
Assert.AreEqual(3, dateTime.Minute);
72+
Assert.AreEqual(59, dateTime.Second);
73+
Assert.AreEqual(0, dateTime.Millisecond);
74+
75+
// Test multiple trailing zeroes
76+
value = new Dictionary<string, object>() {
77+
{ "__type", "Date" },
78+
{ "iso", "1990-08-30T12:03:59.00Z" }
79+
};
80+
81+
dateTime = (DateTime)ParseDecoder.Instance.Decode(value);
82+
Assert.AreEqual(1990, dateTime.Year);
83+
Assert.AreEqual(8, dateTime.Month);
84+
Assert.AreEqual(30, dateTime.Day);
85+
Assert.AreEqual(12, dateTime.Hour);
86+
Assert.AreEqual(3, dateTime.Minute);
87+
Assert.AreEqual(59, dateTime.Second);
88+
Assert.AreEqual(0, dateTime.Millisecond);
89+
}
90+
5991
[Test]
6092
public void TestDecodeBytes() {
6193
IDictionary<string, object> value = new Dictionary<string, object>() {

0 commit comments

Comments
 (0)