jdate.gms : Julian date test

**Description**

The gams function JDate(year,month,day) accepts arguments similar to to date functions in other languages. The earliest date is Jan 1, 1, and the latest date is Dec 31, 9999. Gams picked Jan 1, 1900 as day 1, as done by Excel. Unfortunately, Excel treats the year 1900 incorrectly as a leap year and the serial days starting with March 1, 1900 will be off by one day. The arguments are can be positive or negative and do not have to form a proper date. The arguments with fractional values are first converted to a signed integer by using the floor() function. Note about Excel: The Excel DATE(year,month,day) function has the following data ranges note that excel incorrectly treats the year 1900 as a leap year. DATE(1900, 1, 1) = 1 DATE(1900, 2,28) = 59 DATE(1900, 3, 1) = 61 incorrect; should be 60 DATE(9999,12,31) = 2958465 incorrected; should be 2958464 for years having a value of less than 1900, 1900 + year is assumed The wiki at http://en.wikipedia.org/wiki/Julian_day defines the Julian date (JD) as the interval of time in days and fractions of a day since January 1, 4713 BC Greenwich noon. For example JD values are: Sunday January 14, 2007 at 13:18:59.9' JD = 2454115.05486 The GAMS days start with 1/1/1900 00:00:00 which giveds an offset of 2415019.500 The following table shows different ways of entering dates:

**Reference**

- GAMS Development Corporation, Formulation and Language Example.

**Small Model of Type :** GAMS

**Category :** GAMS Model library

**Main file :** jdate.gms

```
$title Julian date test (JDATE,SEQ=292)
* The gams function JDate(year,month,day) accepts arguments similar to
* to date functions in other languages. The earliest date is Jan 1, 1, and
* the latest date is Dec 31, 9999. Gams picked Jan 1, 1900 as day 1,
* as done by Excel. Unfortunately, Excel treats the year 1900 incorrectly
* as a leap year and the serial days starting with March 1, 1900 will
* be off by one day.
*
* The arguments are can be positive or negative and do not have to form
* a proper date. The arguments with fractional values are first converted
* to a signed integer by using the floor() function.
*
* Note about Excel:
* The Excel DATE(year,month,day) function has the following data ranges
* note that excel incorrectly treats the year 1900 as a leap year.
* DATE(1900, 1, 1) = 1
* DATE(1900, 2,28) = 59
* DATE(1900, 3, 1) = 61 incorrect; should be 60
* DATE(9999,12,31) = 2958465 incorrected; should be 2958464
* for years having a value of less than 1900, 1900 + year is assumed
*
* The wiki at http://en.wikipedia.org/wiki/Julian_day defines the Julian date (JD)
* as the interval of time in days and fractions of a day since
* January 1, 4713 BC Greenwich noon. For example JD values are:
* Sunday January 14, 2007 at 13:18:59.9' JD = 2454115.05486
* The GAMS days start with 1/1/1900 00:00:00 which giveds an offset of 2415019.500
*
* The following table shows different ways of entering dates:
$eolcom //
set i / 1*22/; acronym error
table tvals(i,*) test values
year month day excel gams
1 2005 10 20 38645
2 2005.3 10.3 20.3 38645
3 2005.7 10.7 20.7 38645
4 2005 22 20 39010
5 2005 22 300 39290
6 2005 -5 300 38468
7 2005 -5 -10 38158
8 2005 -5 -10.3 38157
9 2005 -5 -10.7 38157
10 2 -9 -424 0 // excel 1900 0 1 must be wrong
11 1900 1 1 1
12 0 0 1 error
13 2004 2 30 38047
14 2004 14 30 38413
15 2004 0 0 37955
16 9999 12 31 2958465
17 9999 13 1 error
18 1900 1 2 2
19 1899 12 31 693962 // excel 3799 12 31
20 1899 12 30 693961 // excel 3799 12 30
21 1900 2 1 32
22 1 1 1 367 // excel 1901 1 1
parameter res(i) gams julian serial numbers;
display tvals;
* the following will create thre errors
res(i) = jdate(tvals(i,'year'),tvals(i,'month'),tvals(i,'day'));
abort$(execerror<> 2) 'we should have had 2 errors when using tvals'; execerror=0;
tvals(i,'gams') = res(i); display tvals;
*abort$(execerror<> 2) 'we should have had 2 errors when using res'; execerror=0;
* Now we will recover the date components
parameter back(i,*) recovered date components;
back(i,'gams') = res(i);
back(i,'year') = gyear(res(i));
back(i,'month') = gmonth(res(i));
back(i,'day') = gday(res(i));
* there will be errors
back(i,'new') = jdate(back(i,'year'),back(i,'month'),back(i,'day'));
abort$(execerror<> 3) 'we should have had 3 errors when jdate with back'; execerror=0;
display back;
* GAMS and JD days example
scalar JD 'Sunday January 14, 2007 at 13:18:59.9' / 2454115.05486 /
offset days between the JD Epoch and GAMS / 2415019.500 /
gamsjulian GAMS julian days
julian JD days adjusted to GAMS days;
scalars year,month,day,dow,hours,minutes,seconds,millisecs;
gamsjulian = jdate(2007,1,14) + jtime(13,18,59.9);
julian = JD - offset; abort$round(gamsjulian-julian,5) 'julian day problems',jd,offset,gamsjulian,julian;
year = gyear(gamsjulian); month=gmonth(gamsjulian); day=gday(gamsjulian); dow = gdow(gamsjulian);
hours = ghour(gamsjulian); minutes=gminute(gamsjulian); seconds = gsecond(gamsjulian);
millisecs=gmillisec(gamsjulian);
display julian,offset,gamsjulian,dow,month,day,year,hours,minutes,seconds,millisecs;
```