Skip to content

Commit

Permalink
Add exact parsing for datetime RFC3339
Browse files Browse the repository at this point in the history
  • Loading branch information
xoofx committed Feb 10, 2019
1 parent ff05e5a commit d190334
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/SharpToml.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Copyright (c) $CURRENT_YEAR$ - Alexandre Mutel. All rights reserved.&#xD;
Licensed under the BSD-Clause 2 license. &#xD;
See license.txt file in the project root for full license information.</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RFC/@EntryIndexedValue">RFC</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Toml/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
89 changes: 89 additions & 0 deletions src/SharpToml/Helpers/DateTimeRFC3339.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (c) 2019 - Alexandre Mutel. All rights reserved.
// Licensed under the BSD-Clause 2 license.
// See license.txt file in the project root for full license information.

using System;
using System.Globalization;

namespace SharpToml.Helpers
{
internal static class DateTimeRFC3339
{
// https://www.ietf.org/rfc/rfc3339.txt

//date-fullyear = 4DIGIT
//date-month = 2DIGIT ; 01-12
//date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on
// ; month/year
//time-hour = 2DIGIT ; 00-23
//time-minute = 2DIGIT ; 00-59
//time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second
// ; rules
//time-secfrac = "." 1*DIGIT
//time-numoffset = ("+" / "-") time-hour ":" time-minute
//time-offset = "Z" / time-numoffset

//partial-time = time-hour ":" time-minute ":" time-second
// [time-secfrac]
//full-date = date-fullyear "-" date-month "-" date-mday
//full-time = partial-time time-offset

//date-time = full-date "T" full-time

private static readonly string[] Formats = new[]
{
"yyyy-MM-ddTHH:mm:ssZ", // With Z postfix
"yyyy-MM-ddTHH:mm:ss.fZ",
"yyyy-MM-ddTHH:mm:ss.ffZ",
"yyyy-MM-ddTHH:mm:ss.fffZ",
"yyyy-MM-ddTHH:mm:ss.ffffZ",
"yyyy-MM-ddTHH:mm:ss.fffffZ",
"yyyy-MM-ddTHH:mm:ss.ffffffZ",
"yyyy-MM-ddTHH:mm:ss.fffffffZ",
"yyyy-MM-ddTHH:mm:sszzz", // With time-numoffset
"yyyy-MM-ddTHH:mm:ss.fzzz",
"yyyy-MM-ddTHH:mm:ss.ffzzz",
"yyyy-MM-ddTHH:mm:ss.fffzzz",
"yyyy-MM-ddTHH:mm:ss.ffffzzz",
"yyyy-MM-ddTHH:mm:ss.fffffzzz",
"yyyy-MM-ddTHH:mm:ss.ffffffzzz",
"yyyy-MM-ddTHH:mm:ss.fffffffzzz",

// Specs says that T might be omitted
"yyyy-MM-dd HH:mm:ssZ", // With Z postfix
"yyyy-MM-dd HH:mm:ss.fZ",
"yyyy-MM-dd HH:mm:ss.ffZ",
"yyyy-MM-dd HH:mm:ss.fffZ",
"yyyy-MM-dd HH:mm:ss.ffffZ",
"yyyy-MM-dd HH:mm:ss.fffffZ",
"yyyy-MM-dd HH:mm:ss.ffffffZ",
"yyyy-MM-dd HH:mm:ss.fffffffZ",
"yyyy-MM-dd HH:mm:sszzz", // With time-numoffset
"yyyy-MM-dd HH:mm:ss.fzzz",
"yyyy-MM-dd HH:mm:ss.ffzzz",
"yyyy-MM-dd HH:mm:ss.fffzzz",
"yyyy-MM-dd HH:mm:ss.ffffzzz",
"yyyy-MM-dd HH:mm:ss.fffffzzz",
"yyyy-MM-dd HH:mm:ss.ffffffzzz",
"yyyy-MM-dd HH:mm:ss.fffffffzzz",

// Local Date
"yyyy-MM-dd",

// Local Time
"HH:mm:ss",
"HH:mm:ss.f",
"HH:mm:ss.ff",
"HH:mm:ss.fff",
"HH:mm:ss.ffff",
"HH:mm:ss.fffff",
"HH:mm:ss.ffffff",
"HH:mm:ss.fffffff",
};

public static bool TryParse(string str, out DateTime time)
{
return DateTime.TryParseExact(str, Formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out time);
}
}
}
3 changes: 2 additions & 1 deletion src/SharpToml/Parsing/Lexer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using SharpToml.Helpers;
using SharpToml.Syntax;
using SharpToml.Text;

Expand Down Expand Up @@ -558,7 +559,7 @@ private void ReadNumberOrDate(char32? signPrefix = null, TextPosition? signPrefi
}

DateTime dateTime;
if (!DateTime.TryParse(dateTimeAsString, CultureInfo.InvariantCulture, DateTimeStyles.AllowInnerWhite, out dateTime))
if (!DateTimeRFC3339.TryParse(dateTimeAsString, out dateTime))
{
AddError($"Unable to parse the date time/offset `{dateTimeAsString}`", start, end);
}
Expand Down

0 comments on commit d190334

Please sign in to comment.