diff --git a/src/core/s-mold.c b/src/core/s-mold.c index 588f4a4b70..b1cae491e7 100644 --- a/src/core/s-mold.c +++ b/src/core/s-mold.c @@ -1095,7 +1095,7 @@ STOID Mold_Error(REBVAL *value, REB_MOLD *mold, REBFLG molded) case REB_TIME: //len = Emit_Time(value, buf, Punctuation[GET_MOPT(mold, MOPT_COMMA_PT) ? PUNCT_COMMA : PUNCT_DOT]); - Emit_Time(mold, value); + Emit_Time(mold, value, FALSE); break; case REB_DATE: diff --git a/src/core/t-date.c b/src/core/t-date.c index 1bbe75f1b7..abb335f099 100644 --- a/src/core/t-date.c +++ b/src/core/t-date.c @@ -95,6 +95,7 @@ REBYTE *bp = &buf[0]; REBINT tz; REBYTE dash = GET_MOPT(mold, MOPT_SLASH_DATE) ? '/' : '-'; + REBOOL iso = GET_MOPT(mold, MOPT_MOLD_ALL); REBVAL val = *value; value = &val; @@ -111,21 +112,30 @@ if (VAL_TIME(value) != NO_TIME) Adjust_Date_Zone(value, FALSE); // Punctuation[GET_MOPT(mold, MOPT_COMMA_PT) ? PUNCT_COMMA : PUNCT_DOT] - - bp = Form_Int(bp, (REBINT)VAL_DAY(value)); - *bp++ = dash; - memcpy(bp, Month_Names[VAL_MONTH(value)-1], 3); - bp += 3; - *bp++ = dash; - bp = Form_Int_Pad(bp, (REBINT)VAL_YEAR(value), 6, -4, '0'); - *bp = 0; - + if (iso) { + // use ISO8601 output + bp = Form_Int_Pad(bp, (REBINT)VAL_YEAR(value), 6, -4, '0'); + *bp = '-'; + bp = Form_Int_Pad(++bp, (REBINT)VAL_MONTH(value), 2, -2, '0'); + *bp = '-'; + bp = Form_Int_Pad(++bp, (REBINT)VAL_DAY(value), 2, -2, '0'); + *bp = 0; + } else { + // use standard Rebol output + bp = Form_Int(bp, (REBINT)VAL_DAY(value)); + *bp++ = dash; + memcpy(bp, Month_Names[VAL_MONTH(value) - 1], 3); + bp += 3; + *bp++ = dash; + bp = Form_Int_Pad(bp, (REBINT)VAL_YEAR(value), 6, -4, '0'); + *bp = 0; + } Append_Bytes(mold->series, cs_cast(buf)); if (VAL_TIME(value) != NO_TIME) { - Append_Byte(mold->series, '/'); - Emit_Time(mold, value); + Append_Byte(mold->series, iso ? 'T' : '/'); + Emit_Time(mold, value, iso); if (VAL_ZONE(value) != 0) { @@ -138,9 +148,13 @@ else *bp++ = '+'; - bp = Form_Int(bp, tz/4); + if(iso) { + bp = Form_Int_Pad(bp, tz / 4, 2, -2, '0'); + } else { + bp = Form_Int(bp, tz / 4); + } *bp++ = ':'; - bp = Form_Int_Pad(bp, (tz&3) * 15, 2, 2, '0'); + bp = Form_Int_Pad(bp, (tz & 3) * 15, 2, 2, '0'); *bp = 0; Append_Bytes(mold->series, cs_cast(buf)); diff --git a/src/core/t-time.c b/src/core/t-time.c index 73177f2486..f4744ffdb9 100644 --- a/src/core/t-time.c +++ b/src/core/t-time.c @@ -135,8 +135,11 @@ /*********************************************************************** ** -*/ void Emit_Time(REB_MOLD *mold, REBVAL *value) +*/ void Emit_Time(REB_MOLD *mold, REBVAL *value, REBOOL iso) /* +** NOTE: 'iso' arg is padding hour to two digits. +** It is used only when MOLDing datetime with /ALL refinement. +** In this datetime case hour should not be over 24. ***********************************************************************/ { REB_TIMEF tf; @@ -144,8 +147,12 @@ Split_Time(VAL_TIME(value), &tf); // loses sign - if (tf.s == 0 && tf.n == 0) fmt = "I:2"; - else fmt = "I:2:2"; + if(iso) { + fmt = "2:2:2"; + } else { + if (tf.s == 0 && tf.n == 0) fmt = "I:2"; + else fmt = "I:2:2"; + } if (VAL_TIME(value) < (REBI64)0) Append_Byte(mold->series, '-'); Emit(mold, fmt, tf.h, tf.m, tf.s, 0); diff --git a/src/tests/units/date-test.r3 b/src/tests/units/date-test.r3 index f359540d1e..d35fcc4bae 100644 --- a/src/tests/units/date-test.r3 +++ b/src/tests/units/date-test.r3 @@ -8,19 +8,19 @@ Rebol [ ~~~start-file~~~ "date" -===start-group=== "ISO88601 subset" - --test-- "ISO88601 basic load" +===start-group=== "ISO8601 subset" + --test-- "ISO8601 basic load" --assert 8-Nov-2013/17:01 = load "2013-11-08T17:01" --assert 8-Nov-2013/17:01 = load "2013-11-08T17:01Z" --assert 8-Nov-2013/17:01+1:00 = load "2013-11-08T17:01+0100" --assert 8-Nov-2013/17:01-1:00 = load "2013-11-08T17:01-0100" --assert 8-Nov-2013/17:01+1:00 = load "2013-11-08T17:01+01:00" - --test-- "basic load of not fully standard ISO88601" + --test-- "basic load of not fully standard ISO8601" --assert 8-Nov-2013/17:01 = load "2013/11/08T17:01" --assert 8-Nov-2013/17:01 = load "2013/11/08T17:01Z" --assert 8-Nov-2013/17:01+1:00 = load "2013/11/08T17:01+0100" --assert 8-Nov-2013/17:01+1:00 = load "2013/11/08T17:01+01:00" - --test-- "Invalid ISO88601 dates" + --test-- "Invalid ISO8601 dates" --assert error? try [load "2013-11-08T17:01Z0100"] --assert error? try [load "2013/11/08T17:01Z0100"] @@ -31,6 +31,14 @@ Rebol [ ===end-group=== +===start-group=== "MOLD/ALL on date" +;-- producing ISO8601 valid result (https://tools.ietf.org/html/rfc3339) + --test-- "MOLD/ALL on date" + --assert "2000-01-01T01:02:03" = mold/all 1-1-2000/1:2:3 + --assert "2000-01-01T10:20:03" = mold/all 1-1-2000/10:20:3 + --assert "0200-01-01T01:02:03" = mold/all 1-1-200/1:2:3 + --assert "0200-01-01T01:02:03+02:00" = mold/all 1-1-200/1:2:3+2:0 + --assert "0200-01-01T01:02:03+10:00" = mold/all 1-1-200/1:2:3+10:0 ===end-group===