Skip to content

Commit 0309156

Browse files
committed
FEAT: add possibility to set date's /utc and /yearday
related to: Oldes/Rebol-issues#1385 resolves: Oldes/Rebol-wishes#18
1 parent 65ebf24 commit 0309156

File tree

2 files changed

+85
-4
lines changed

2 files changed

+85
-4
lines changed

src/core/t-date.c

+59-2
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,49 @@
205205
return date.date.day + days;
206206
}
207207

208+
/***********************************************************************
209+
**
210+
*/ REBI64 Days_Of_Date(REBINT day, REBINT month, REBINT year )
211+
/*
212+
** Return number of days from given date parts
213+
**
214+
***********************************************************************/
215+
{
216+
REBI64 m = (month + 9) % 12;
217+
REBI64 y = year - (m / 10);
218+
return (REBI64)(365 * y + (y / 4) - (y / 100) + (y / 400) + ((m * 306 + 5) / 10) + ((REBI64)day - 1));
219+
}
220+
221+
/***********************************************************************
222+
**
223+
*/ void Date_Of_Days(REBI64 days, REBDAT *date)
224+
/*
225+
** Return number of days from given date parts
226+
**
227+
***********************************************************************/
228+
{
229+
REBI64 dd, y, mi;
230+
231+
y = ((10000 * days) + 14780) / 3652425;
232+
dd = days - (365 * y + (y / 4) - (y / 100) + (y / 400));
233+
mi = (100 * dd + 52) / 3060;
234+
date->date.month = (mi + 2) % 12 + 1;
235+
date->date.year = y + ((mi + 2) / 12);
236+
date->date.day = dd - ((mi * 306 + 5) / 10) + 1;
237+
}
238+
239+
240+
/***********************************************************************
241+
**
242+
*/ static REBI64 Days_Of_Jan_1st(REBINT year)
243+
/*
244+
** Return number of days for 1st January of given year
245+
**
246+
***********************************************************************/
247+
{
248+
return Days_Of_Date(1, 1, year);
249+
}
250+
208251

209252
/***********************************************************************
210253
**
@@ -633,11 +676,11 @@
633676

634677
if (IS_INTEGER(val) || IS_DECIMAL(val)) {
635678
// allow negative time zone
636-
n = (sym == SYM_ZONE) ? Int32(val) : Int32s(val, 0);
679+
n = (sym == SYM_ZONE || sym == SYM_YEARDAY) ? Int32(val) : Int32s(val, 0);
637680
}
638681
else if (IS_NONE(val)) n = 0;
639682
else if (IS_TIME(val) && (sym == SYM_TIME || sym == SYM_ZONE));
640-
else if (IS_DATE(val) && (sym == SYM_TIME || sym == SYM_DATE));
683+
else if (IS_DATE(val) && (sym == SYM_TIME || sym == SYM_DATE || sym == SYM_UTC));
641684
else return PE_BAD_SET_TYPE;
642685

643686
if (secs == NO_TIME && ((sym >= SYM_HOUR && sym <= SYM_SECOND) || sym == SYM_TIME || sym == SYM_ZONE)) {
@@ -704,6 +747,20 @@
704747
}
705748
secs = Join_Time(&time);
706749
break;
750+
case SYM_UTC:
751+
if (!IS_DATE(val)) return PE_BAD_SET_TYPE;
752+
data = pvs->value;
753+
*data = *val;
754+
VAL_ZONE(data) = 0;
755+
return PE_USE;
756+
case SYM_YEARDAY:
757+
case SYM_JULIAN:
758+
if (!IS_INTEGER(val)) return PE_BAD_SET_TYPE;
759+
Date_Of_Days( Days_Of_Jan_1st(year) + n - 1, &date);
760+
day = date.date.day - 1;
761+
month = date.date.month - 1;
762+
year = date.date.year;
763+
break;
707764

708765
default:
709766
return PE_BAD_SET;

src/tests/units/date-test.r3

+26-2
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,33 @@ Rebol [
185185
err/id = 'invalid-path
186186
]
187187
--assert all [
188-
error? err: try [d/yearday: 1]
189-
err/id = 'bad-path-set
188+
error? err: try [d/utc: 1] ; error, because it requires date
189+
err/id = 'bad-field-set
190+
]
191+
--assert all [
192+
not error? try [d/time: 1.2] ; setting time to decimal is now implemented
193+
d = 1-Jan-2000/0:00:01.2
190194
]
195+
d/time: none
196+
--assert all [
197+
;@@ https://github.com/Oldes/Rebol-wishes/issues/18
198+
not error? try [d/yearday: 17]
199+
d = 17-1-2000
200+
60 = d/yearday: 60
201+
d = 29-Feb-2000 ; was leak year
202+
d/year: 2001 d/yearday: 60
203+
d = 1-Mar-2001 ; this one not
204+
d/yearday: 0 ; last day of previous year
205+
d = 31-Dec-2000
206+
d/yearday: -1
207+
d = 30-Dec-1999
208+
]
209+
; it's now possible to set /utc (if used date or date-time)
210+
n: 27-Nov-2020/18:15:57+1:00 ; date-time with timezone
211+
--assert probe n = (d/utc: n) ; result is passed thru
212+
probe d
213+
--assert probe d = 27-Nov-2020/17:15:57 ; but d is now adjusted
214+
191215

192216
===end-group===
193217

0 commit comments

Comments
 (0)