Skip to content

Commit

Permalink
Fix Issue 10828 - datetime toString functions should accept sink
Browse files Browse the repository at this point in the history
  • Loading branch information
JackStouffer committed Feb 16, 2018
1 parent 72bae0b commit dcdf8b4
Showing 1 changed file with 111 additions and 54 deletions.
165 changes: 111 additions & 54 deletions std/datetime/systime.d
Expand Up @@ -7791,45 +7791,67 @@ public:
enough to uniquely identify the time zone.
Time zone offsets will be in the form +HH:MM or -HH:MM.
Params:
writer = A `char` accepting
$(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
Returns:
A `string` when not using an output range; `void` otherwise.
+/
string toISOExtString() @safe const nothrow
{
import std.array : appender;
auto app = appender!string();
app.reserve(35);
try
{
immutable adjustedTime = adjTime;
long hnsecs = adjustedTime;

auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
toISOExtString(app);
catch (Exception e)
assert(0, "toISOExtString() threw.");
return app.data;
}

if (hnsecs < 0)
{
hnsecs += convert!("hours", "hnsecs")(24);
--days;
}
/// ditto
void toISOExtString(W)(ref W writer) const
if (isOutputRange!(W, char))
{
immutable adjustedTime = adjTime;
long hnsecs = adjustedTime;

auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;

auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
cast(int) minute, cast(int) second));
auto fracSecStr = fracSecsToISOString(cast(int) hnsecs);
if (hnsecs < 0)
{
hnsecs += convert!("hours", "hnsecs")(24);
--days;
}

if (_timezone is LocalTime())
return dateTime.toISOExtString() ~ fracSecStr;
immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);

if (_timezone is UTC())
return dateTime.toISOExtString() ~ fracSecStr ~ "Z";
immutable dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
cast(int) minute, cast(int) second));

immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
if (_timezone is LocalTime())
{
dateTime.toISOExtString(writer);
fracSecsToISOString(writer, cast(int) hnsecs);
return;
}

return format("%s%s%s",
dateTime.toISOExtString(),
fracSecStr,
SimpleTimeZone.toISOExtString(utcOffset));
if (_timezone is UTC())
{
dateTime.toISOExtString(writer);
fracSecsToISOString(writer, cast(int) hnsecs);
put(writer, 'Z');
return;
}
catch (Exception e)
assert(0, "format() threw.");

immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);

dateTime.toISOExtString(writer);
fracSecsToISOString(writer, cast(int) hnsecs);
SimpleTimeZone.toISOExtString(writer, utcOffset);
}

///
Expand Down Expand Up @@ -7928,45 +7950,67 @@ public:
enough to uniquely identify the time zone.
Time zone offsets will be in the form +HH:MM or -HH:MM.
Params:
writer = A `char` accepting
$(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
Returns:
A `string` when not using an output range; `void` otherwise.
+/
string toSimpleString() @safe const nothrow
{
import std.array : appender;
auto app = appender!string();
app.reserve(35);
try
{
immutable adjustedTime = adjTime;
long hnsecs = adjustedTime;

auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
toSimpleString(app);
catch (Exception e)
assert(0, "toSimpleString() threw.");
return app.data;
}

if (hnsecs < 0)
{
hnsecs += convert!("hours", "hnsecs")(24);
--days;
}
/// ditto
void toSimpleString(W)(ref W writer) const
if (isOutputRange!(W, char))
{
immutable adjustedTime = adjTime;
long hnsecs = adjustedTime;

auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;

auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
cast(int) minute, cast(int) second));
auto fracSecStr = fracSecsToISOString(cast(int) hnsecs);
if (hnsecs < 0)
{
hnsecs += convert!("hours", "hnsecs")(24);
--days;
}

if (_timezone is LocalTime())
return dateTime.toSimpleString() ~ fracSecStr;
immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);

if (_timezone is UTC())
return dateTime.toSimpleString() ~ fracSecStr ~ "Z";
immutable dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
cast(int) minute, cast(int) second));

immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
if (_timezone is LocalTime())
{
dateTime.toSimpleString(writer);
fracSecsToISOString(writer, cast(int) hnsecs);
return;
}

return format("%s%s%s",
dateTime.toSimpleString(),
fracSecStr,
SimpleTimeZone.toISOExtString(utcOffset));
if (_timezone is UTC())
{
dateTime.toSimpleString(writer);
fracSecsToISOString(writer, cast(int) hnsecs);
put(writer, 'Z');
return;
}
catch (Exception e)
assert(0, "format() threw.");

immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);

dateTime.toSimpleString(writer);
fracSecsToISOString(writer, cast(int) hnsecs);
SimpleTimeZone.toISOExtString(writer, utcOffset);
}

///
Expand Down Expand Up @@ -8071,12 +8115,25 @@ public:
`fromISOString`, `fromISOExtString`, and `fromSimpleString`.
The format returned by toString may or may not change in the future.
Params:
writer = A `char` accepting
$(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
Returns:
A `string` when not using an output range; `void` otherwise.
+/
string toString() @safe const nothrow
{
return toSimpleString();
}

/// ditto
void toString(W)(ref W writer) const
if (isOutputRange!(W, char))
{
toSimpleString(writer);
}

@safe unittest
{
import core.time;
Expand Down

0 comments on commit dcdf8b4

Please sign in to comment.