Skip to content

Commit

Permalink
FEAT: letting MOLD/ALL on datetime value to produce ISO8601 valid result
Browse files Browse the repository at this point in the history
  • Loading branch information
Oldes committed Dec 17, 2018
1 parent 1ebbbc3 commit 542d8dd
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/core/s-mold.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
40 changes: 27 additions & 13 deletions src/core/t-date.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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) {

Expand All @@ -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));
Expand Down
13 changes: 10 additions & 3 deletions src/core/t-time.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,17 +135,24 @@

/***********************************************************************
**
*/ 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;
char *fmt;

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);
Expand Down
16 changes: 12 additions & 4 deletions src/tests/units/date-test.r3
Original file line number Diff line number Diff line change
Expand Up @@ -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"]

Expand All @@ -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===

Expand Down

0 comments on commit 542d8dd

Please sign in to comment.