Skip to content

Commit 4212720

Browse files
Time: Add support for variable number of millisecond digits in ISO8601 format
1 parent ea37e71 commit 4212720

File tree

1 file changed

+64
-8
lines changed

1 file changed

+64
-8
lines changed

modules/juce_core/time/juce_Time.cpp

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -435,19 +435,27 @@ String Time::toISO8601 (bool includeDividerCharacters) const
435435
+ getUTCOffsetString (includeDividerCharacters);
436436
}
437437

438-
static int parseFixedSizeIntAndSkip (String::CharPointerType& t, int numChars, char charToSkip) noexcept
438+
static int parseVariableSizeIntAndSkip (String::CharPointerType& t,
439+
int minNumChars,
440+
int targetNumChars,
441+
char charToSkip) noexcept
439442
{
440443
int n = 0;
441444

442-
for (int i = numChars; --i >= 0;)
445+
for (int i = 0; i < targetNumChars; ++i)
443446
{
444-
auto digit = (int) (*t - '0');
447+
n *= 10;
448+
const auto digit = (int) (*t - '0');
445449

446-
if (! isPositiveAndBelow (digit, 10))
450+
if (isPositiveAndBelow (digit, 10))
451+
{
452+
n += digit;
453+
++t;
454+
}
455+
else if (i < minNumChars)
456+
{
447457
return -1;
448-
449-
++t;
450-
n = n * 10 + digit;
458+
}
451459
}
452460

453461
if (charToSkip != 0 && *t == (juce_wchar) charToSkip)
@@ -456,6 +464,11 @@ static int parseFixedSizeIntAndSkip (String::CharPointerType& t, int numChars, c
456464
return n;
457465
}
458466

467+
static int parseFixedSizeIntAndSkip (String::CharPointerType& t, int numChars, char charToSkip) noexcept
468+
{
469+
return parseVariableSizeIntAndSkip (t, numChars, numChars, charToSkip);
470+
}
471+
459472
Time Time::fromISO8601 (StringRef iso)
460473
{
461474
auto t = iso.text;
@@ -515,13 +528,16 @@ Time Time::fromISO8601 (StringRef iso)
515528
if (*t == '.' || *t == ',')
516529
{
517530
++t;
518-
milliseconds = parseFixedSizeIntAndSkip (t, 3, 0);
531+
milliseconds = parseVariableSizeIntAndSkip (t, 1, 3, 0);
519532

520533
if (milliseconds < 0)
521534
{
522535
jassertfalse;
523536
return {};
524537
}
538+
539+
// skip to the next non-digit character
540+
while (t.isDigit()) { ++t; }
525541
}
526542

527543
milliseconds += 1000 * seconds;
@@ -701,6 +717,46 @@ class TimeTests final : public UnitTest
701717
expect (Time::fromISO8601 ("20160216T150357.999-0230") == Time (2016, 1, 16, 17, 33, 57, 999, false));
702718
expect (Time::fromISO8601 ("20160216T150357,999-0230") == Time (2016, 1, 16, 17, 33, 57, 999, false));
703719

720+
expect (Time::fromISO8601 ("2016-02-16T15:03:57.9+00:00") == Time (2016, 1, 16, 15, 3, 57, 900, false));
721+
expect (Time::fromISO8601 ("20160216T150357.9+0000") == Time (2016, 1, 16, 15, 3, 57, 900, false));
722+
expect (Time::fromISO8601 ("2016-02-16T15:03:57.9Z") == Time (2016, 1, 16, 15, 3, 57, 900, false));
723+
expect (Time::fromISO8601 ("2016-02-16T15:03:57,9Z") == Time (2016, 1, 16, 15, 3, 57, 900, false));
724+
expect (Time::fromISO8601 ("20160216T150357.9Z") == Time (2016, 1, 16, 15, 3, 57, 900, false));
725+
expect (Time::fromISO8601 ("20160216T150357,9Z") == Time (2016, 1, 16, 15, 3, 57, 900, false));
726+
727+
expect (Time::fromISO8601 ("2016-02-16T15:03:57.9-02:30") == Time (2016, 1, 16, 17, 33, 57, 900, false));
728+
expect (Time::fromISO8601 ("2016-02-16T15:03:57,9-02:30") == Time (2016, 1, 16, 17, 33, 57, 900, false));
729+
expect (Time::fromISO8601 ("20160216T150357.9-0230") == Time (2016, 1, 16, 17, 33, 57, 900, false));
730+
expect (Time::fromISO8601 ("20160216T150357,9-0230") == Time (2016, 1, 16, 17, 33, 57, 900, false));
731+
732+
expect (Time::fromISO8601 ("2016-02-16T15:03:57.99+00:00") == Time (2016, 1, 16, 15, 3, 57, 990, false));
733+
expect (Time::fromISO8601 ("20160216T150357.99+0000") == Time (2016, 1, 16, 15, 3, 57, 990, false));
734+
expect (Time::fromISO8601 ("2016-02-16T15:03:57.99Z") == Time (2016, 1, 16, 15, 3, 57, 990, false));
735+
expect (Time::fromISO8601 ("2016-02-16T15:03:57,99Z") == Time (2016, 1, 16, 15, 3, 57, 990, false));
736+
expect (Time::fromISO8601 ("20160216T150357.99Z") == Time (2016, 1, 16, 15, 3, 57, 990, false));
737+
expect (Time::fromISO8601 ("20160216T150357,99Z") == Time (2016, 1, 16, 15, 3, 57, 990, false));
738+
739+
expect (Time::fromISO8601 ("2016-02-16T15:03:57.99-02:30") == Time (2016, 1, 16, 17, 33, 57, 990, false));
740+
expect (Time::fromISO8601 ("2016-02-16T15:03:57,99-02:30") == Time (2016, 1, 16, 17, 33, 57, 990, false));
741+
expect (Time::fromISO8601 ("20160216T150357.99-0230") == Time (2016, 1, 16, 17, 33, 57, 990, false));
742+
expect (Time::fromISO8601 ("20160216T150357,99-0230") == Time (2016, 1, 16, 17, 33, 57, 990, false));
743+
744+
// The 8601 standard appears to support any number of fractional digits.
745+
// The fractional part should either be rounded or truncated.
746+
// The Time class stores time with millisecond precision.
747+
// Most implementations appear to truncate so that's what we test for too.
748+
expect (Time::fromISO8601 ("2016-02-16T15:03:57.9999+00:00") == Time (2016, 1, 16, 15, 3, 57, 999, false));
749+
expect (Time::fromISO8601 ("20160216T150357.999999999+0000") == Time (2016, 1, 16, 15, 3, 57, 999, false));
750+
expect (Time::fromISO8601 ("2016-02-16T15:03:57.999999999Z") == Time (2016, 1, 16, 15, 3, 57, 999, false));
751+
expect (Time::fromISO8601 ("2016-02-16T15:03:57,999999999Z") == Time (2016, 1, 16, 15, 3, 57, 999, false));
752+
expect (Time::fromISO8601 ("20160216T150357.9999999999999Z") == Time (2016, 1, 16, 15, 3, 57, 999, false));
753+
expect (Time::fromISO8601 ("20160216T150357,9999999999999Z") == Time (2016, 1, 16, 15, 3, 57, 999, false));
754+
755+
expect (Time::fromISO8601 ("2016-02-16T15:03:57.9999-02:30") == Time (2016, 1, 16, 17, 33, 57, 999, false));
756+
expect (Time::fromISO8601 ("2016-02-16T15:03:57,9999-02:30") == Time (2016, 1, 16, 17, 33, 57, 999, false));
757+
expect (Time::fromISO8601 ("20160216T150357.999999999-0230") == Time (2016, 1, 16, 17, 33, 57, 999, false));
758+
expect (Time::fromISO8601 ("20160216T150357,999999999-0230") == Time (2016, 1, 16, 17, 33, 57, 999, false));
759+
704760
expect (Time (1970, 0, 1, 0, 0, 0, 0, false) == Time (0));
705761
expect (Time (2106, 1, 7, 6, 28, 15, 0, false) == Time (4294967295000));
706762
expect (Time (2007, 10, 7, 1, 7, 20, 0, false) == Time (1194397640000));

0 commit comments

Comments
 (0)