SysTime.fromISOString

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat May 13 05:03:50 PDT 2017


On Saturday, May 13, 2017 12:31:38 Russel Winder via Digitalmars-d-learn 
wrote:
> And this seems awkward:
>
>
>   auto date = Clock.currTime();
>   auto date_buffer = date.toISOString();
>>   try {
>       date = SysTime.fromISOString(date_buffer);
>   } catch (DateTimeException dte) {
>       try {
>           date =
> SysTime(DateTime.fromISOString(date_buffer));
>       } catch (DateTimeException ddttee) {
>           date =
> SysTime(Date.fromISOString(date_buffer));
>       }
>   }
>
> Even though it works, well with 20150510 if not 2015-05-10.
>
> I suspect I am doing it wrong. :-)

Well, Clock.currTime() gives you a SysTime, not a Date. So, your date
variable is a SysTime, and date_buffer is going to be something like
"20170513T123138.12392". Calling SysTime.fromISOString will therefore work
on that without throwing, and calling either Date.fromISOString or
DateTime.fromISOString is going to throw, because Date doesn't support the
time (just the date), and DateTime doesn't support the fractional seconds or
a time zone (though you wouldn't currently get a time zone in this case,
because I still need to fix it so that LocalTime gives you a time zone for
to*String - if the time zone isn't there, then local time is assumed, so
what it's doing right now is technically correct, but it's error-prone).

std.datetime's from*String functions are designed to be fairly strict about
parsing, so you need to be fairly sure of what kind of string you're dealing
with. Certainly, you need to know whether you're dealing with the basic ISO
format or the extended ISO format, and you need to know which pieces are
going to be in the string. If it's going to be just the date (e.g.
2012-12-21), then you're going to need to use Date. If it's going to be just
the time (e.g. 04:19:22), then you're going to need to use TimeOfDay. If
it's going to be the date and the time (e.g. 2012-12-21T04:19:22), then you
can use either SysTime or DateTime, but if it's the data and the time and
includes the fractional seconds and/or a time zone (e.g.
2012-12-21T:04:19:22.0002, 2012-12-21T:04:19:22+08:00, or
2012-12-21T:04:19:22.0002+08:00), then you'll need to use SysTime, because
DateTime does not support either the fractional seconds or a time zone.

Each type is expecting a string with the pieces (date, time, fractional
seconds, and time zone) that it supports and that they'll all be there. The
only stuff that's optional is the fractional seconds and time zone when
dealing with SysTime, because the spec does not require that they be there.

If you were trying to be lax with the parsing and accept the various
combinations of what's legal, then you'd be stuck doing something like

SysTime st;
try
{
    // If it's YYYY-MM-DDTHH:MM:SS.FFFFFFFZ
    // If it's YYYY-MM-DDTHH:MM:SS.FFFFFFZ
    // If it's YYYY-MM-DDTHH:MM:SS.FFFFFZ
    // If it's YYYY-MM-DDTHH:MM:SS.FFFFZ
    // If it's YYYY-MM-DDTHH:MM:SS.FFFZ
    // If it's YYYY-MM-DDTHH:MM:SS.FFZ
    // If it's YYYY-MM-DDTHH:MM:SS.FZ
    // or      YYYY-MM-DDTHH:MM:SSZ
    // or      YYYY-MM-DDTHH:MM:SS.FFFFFFF
    // or      YYYY-MM-DDTHH:MM:SS.FFFFFF
    // or      YYYY-MM-DDTHH:MM:SS.FFFFF
    // or      YYYY-MM-DDTHH:MM:SS.FFFF
    // or      YYYY-MM-DDTHH:MM:SS.FFF
    // or      YYYY-MM-DDTHH:MM:SS.FF
    // or      YYYY-MM-DDTHH:MM:SS.F
    // or      YYYY-MM-DDTHH:MM:SS
    st = SysTime.fromISOExtString(str);
}
catch(DateTimeException)
{
    try
    {
        // If it's just YYYY-MM-DD
        st = SysTime(Date.fromISOExtString(str));
    }
    catch(DateTimeException)
    {
        // If it's just HH:MM:SS
        st = SysTime(Date.init, TimeOfDay.fromISOExtString(str));
    }
}

But that would be downright bizarre in the case where it was just HH:MM:SS,
because then you'd end up with a SysTime on January 1st, 1 A.D. And while
getting just the date is less awkward, it's still kind off to then operate
on that as a SysTime. The time would always be at midnight.

Really, just parsing an "ISO formatted string" and allowing either the date
or time to be optional doesn't make much sense to me. That implies that you
don't really know what it's for, since the meaning of something that is just
a date and the meaning of something that is just a time are completely
different.

Regardless, std.datetime was designed with the idea that you knew whether
you were dealing with a date, a time, or both a date and a time when dealing
with ISO formatted strings.

- Jonathan M Davis




More information about the Digitalmars-d-learn mailing list