Skip to content

Commit

Permalink
FEAT: enabling T as a delimiter between date and time and Z as a zero…
Browse files Browse the repository at this point in the history
… timezone, so subset of ISO8601 datetime values are loadable from Rebol.

Example:
```
>> 2013-11-08T17:01
== 8-Nov-2013/17:01
>> 2013-11-08T17:01+0100
== 8-Nov-2013/17:01+1:00
>> 2013-11-08T17:01Z
== 8-Nov-2013/17:01
```

Related issues:
metaeducation/rebol-issues#438
metaeducation/rebol-issues#2089
metaeducation/rebol-issues#2092
  • Loading branch information
Oldes committed Dec 17, 2018
1 parent 035df2a commit 1ebbbc3
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 2 deletions.
3 changes: 2 additions & 1 deletion src/core/l-scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,8 @@

return -TOKEN_INTEGER;
}
if (HAS_LEX_FLAG(flags, LEX_SPECIAL_COLON)) return TOKEN_TIME; /* 12:34 */
if (HAS_LEX_FLAG(flags, LEX_SPECIAL_COLON))
return (HAS_LEX_FLAG(flags, LEX_SPECIAL_WORD) ? TOKEN_DATE : TOKEN_TIME); /* iso8601 datetime or 12:34 */
if (HAS_LEX_FLAG(flags, LEX_SPECIAL_PERIOD)) { /* 1.2 1.2.3 1,200.3 1.200,3 1.E-2 */
if (Skip_To_Char(cp, scan_state->end, 'x')) return TOKEN_PAIR;
cp = Skip_To_Char(cp, scan_state->end, '.');
Expand Down
9 changes: 8 additions & 1 deletion src/core/l-types.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ bad_hex: Trap0(RE_INVALID_CHARS);
VAL_TIME(value) = NO_TIME;
if (cp >= end) goto end_date;

if (*cp == '/' || *cp == ' ') {
if (*cp == '/' || *cp == 'T' || *cp == ' ') { //@@ Oldes: is the check for space really needed here?
sep = *cp++;
if (cp >= end) goto end_date;
cp = Scan_Time(cp, 0, value);
Expand All @@ -535,12 +535,19 @@ bad_hex: Trap0(RE_INVALID_CHARS);

if (*cp == sep) cp++;

if (*cp == 'Z') {
// 'Z' must be last char in the ISO8601 date (if used).
if (++cp == end) goto end_date; // valid timezone 0:0
else return 0;
}
// Time zone can be 12:30 or 1230 (optional hour indicator)
if (*cp == '-' || *cp == '+') {
if (cp >= end) goto end_date;
ep = Grab_Int(cp+1, &num);
if (ep-cp == 0) return 0;
if (*ep != ':') {
// An integer is assumed to be HHMM format
// https://github.com/rebol/rebol-issues/issues/1411#issuecomment-170907151
int h, m;
if (num < -1500 || num > 1500) return 0;
h = (num / 100);
Expand Down
1 change: 1 addition & 0 deletions src/tests/run-tests.r3
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dt [ ;- delta time
wrap load %units/codecs-test.r3
wrap load %units/series-test.r3
wrap load %units/compress-test.r3
wrap load %units/date-test.r3

recycle/torture
recycle
Expand Down
37 changes: 37 additions & 0 deletions src/tests/units/date-test.r3
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Rebol [
Title: "Rebol3 date test script"
Author: "Oldes, Peter W A Wood"
File: %date-test.r3
Tabs: 4
Needs: [%../quick-test-module.r3]
]

~~~start-file~~~ "date"

===start-group=== "ISO88601 subset"
--test-- "ISO88601 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"
--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"
--assert error? try [load "2013-11-08T17:01Z0100"]
--assert error? try [load "2013/11/08T17:01Z0100"]

--test-- "Using ISO88601 datetime in a path"
;@@ https://github.com/rebol/rebol-issues/issues/2089
b: [8-Nov-2013/17:01 "foo"]
--assert "foo" = b/2013-11-08T17:01

===end-group===


===end-group===

~~~end-file~~~

0 comments on commit 1ebbbc3

Please sign in to comment.