Skip to content

Commit

Permalink
FEAT: implemented query on date values
Browse files Browse the repository at this point in the history
So one can query multiple date parts with one call, for example:
```
>> query/mode now [year day month time timezone]
== [2020 8 4 12:24:54 2:00]
```
If set words are used, the result is like:
```
>> query/mode now [year: month:]
== [
    year: 2020
    month: 4
]
```
Simple `query now` would return object with all possible fields.
  • Loading branch information
Oldes committed Apr 8, 2020
1 parent ea3818e commit 5d5bf7f
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 1 deletion.
18 changes: 18 additions & 0 deletions src/boot/sysobj.r
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,24 @@ standard: context [
none
]

date-info: context [
year:
month:
day:
time:
zone:
date:
weekday:
julian:
yearday:
utc:
hour:
minute:
second:
timezone:
none
]

midi-info: context [
devices-in:
devices-out:
Expand Down
73 changes: 72 additions & 1 deletion src/core/t-date.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,22 @@
return TRUE;
}

/***********************************************************************
**
*/ static REBOOL Query_Date_Field(REBVAL *data, REBVAL *select, REBVAL *ret)
/*
** Set a value with date data according specified mode
**
***********************************************************************/
{
REBPVS pvs;
pvs.value = data;
pvs.select = select;
pvs.setval = 0;
pvs.store = ret;

return (PE_USE == PD_Date(&pvs));
}

/***********************************************************************
**
Expand All @@ -509,7 +525,7 @@

// !zone! - adjust date by zone (unless /utc given)

if (IS_WORD(arg)) {
if (IS_WORD(arg) || IS_SET_WORD(arg)) {
//!!! change this to an array!?
switch (VAL_WORD_CANON(arg)) {
case SYM_YEAR: i = 0; break;
Expand Down Expand Up @@ -718,6 +734,7 @@
REBVAL *val;
REBVAL *arg = NULL;
REBINT num;
REBVAL *spec;

val = D_ARG(1);
if (IS_DATE(val)) {
Expand Down Expand Up @@ -829,6 +846,60 @@

case A_ABSOLUTE:
goto setDate;

case A_REFLECT:
if (SYM_SPEC == VAL_WORD_SYM(D_ARG(2))) {
return R_ARG1;
}
if(!Query_Date_Field(val, D_ARG(2), D_RET)) {
Trap_Reflect(VAL_TYPE(val), D_ARG(2));
}
return R_RET;
case A_QUERY:
spec = Get_System(SYS_STANDARD, STD_DATE_INFO);
if (!IS_OBJECT(spec)) Trap_Arg(spec);
if (D_REF(2)) { // query/mode refinement
REBVAL *field = D_ARG(3);
if(IS_WORD(field)) {
if (SYM_SPEC == VAL_WORD_CANON(field)) {
return R_ARG1;
}
if (!Query_Date_Field(val, field, D_RET))
Trap_Reflect(VAL_TYPE(val), field); // better error?
}
else if (IS_BLOCK(field)) {
REBVAL *out = D_RET;
REBSER *values = Make_Block(2 * BLK_LEN(VAL_SERIES(field)));
REBVAL *word = VAL_BLK_DATA(field);
for (; NOT_END(word); word++) {
if (ANY_WORD(word)) {
if (IS_SET_WORD(word)) {
// keep the set-word in result
out = Append_Value(values);
*out = *word;
VAL_SET_LINE(out);
}
out = Append_Value(values);
if (!Query_Date_Field(val, word, out))
Trap1(RE_INVALID_ARG, word);
}
else Trap1(RE_INVALID_ARG, word);
}
Set_Series(REB_BLOCK, D_RET, values);
}
else {
Set_Block(D_RET, Get_Object_Words(spec));
}
} else {
REBSER *obj = CLONE_OBJECT(VAL_OBJ_FRAME(spec));
REBSER *words = VAL_OBJ_WORDS(spec);
REBVAL *word = BLK_HEAD(words);
for (num=0; NOT_END(word); word++,num++) {
Query_Date_Field(val, word, OFV(obj, num));
}
SET_OBJECT(D_RET, obj);
}
return R_RET;
}
}
Trap_Action(REB_DATE, action);
Expand Down
17 changes: 17 additions & 0 deletions src/tests/units/date-test.r3
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,21 @@ Rebol [

===end-group===


===start-group=== "QUERY date"
date: 8-Apr-2020/12:04:32+2:00
--test-- "query date"
--assert object? o: query date
--assert o/date = 8-Apr-2020

--test-- "query/mode date"
all-date-words: words-of system/standard/date-info
--assert all-date-words = query/mode date none
--assert date/time = query/mode date 'time
--assert [2020 4] = query/mode now [year month]
--assert [month: 4 year: 2020] = query/mode now [month: year:]
--assert [2020 4 8 12:04:32 2:00 8-Apr-2020 3 99 99 8-Apr-2020/10:04:32 12 4 32 2:00] = query/mode date all-date-words

===end-group===

~~~end-file~~~

0 comments on commit 5d5bf7f

Please sign in to comment.