Initializing help system before first use

Date and time data types

The module mmsystem of the standard distribution of Mosel defines the types date (calendar day: day, month, and year), time (time of the day in milliseconds), and datetime (combination of the first two) for working with date and time related data in Mosel models. We show here some examples of

  • reading and writing dates and times from/to file,
  • formatting dates and times,
  • using sets of constant dates and times for indexing arrays,
  • transformation from/to the underlying numerical representation,
  • applying operations (comparison, addition, difference, sorting),
  • enumerating dates and times.

Initializing dates and times

The following line prints out the current date and time (using the default format):

 writeln("Today: ", date(SYS_NOW), ", current local time: ", time(SYS_NOW),
         "UTC time: ", gettime(datetime(timestamp)) )

When we wish to read data from a file, the formatting of dates and times needs to be adapted to the format used in the file. For example, consider the following data file (datetime.dat)

Time1:  "4pm"
Time2:  "16h00"
Time3:  "16:00:00"

Date1:  "2-20-2002"
Date2:  "20/02/02"
Date3:  "20-Feb-2002" 

A Mosel model reading in this data file may look thus (file dates.mos).

 declarations
  t: time
  d: date
 end-declarations

 setparam("timefmt", "%h%p")             ! h: hours in 1-12, p: am/pm
 setparam("datefmt", "%m-%d-%y")         ! m: month, d: day, y: year

 initializations from "datetime.dat"
  t as "Time1"
  d as "Date1"
 end-initializations

 writeln(d, ", ", t)

 setparam("timefmt", "%Hh%0M")           ! H: hours in 0-23, M: minutes
 setparam("datefmt", "%0d/%0m/%0Y")      ! Y: year in 0-99
                                         ! 0: fill spaces with '0'

 initializations from "datetime.dat"
  t as "Time2"
  d as "Date2"
 end-initializations

 writeln(d, ", ", t)

 setparam("timefmt", "%H:%0M:%0S")       ! S: seconds
 setparam("datefmt", "%d-%N-%y")         ! N: use month names

 initializations from "datetime.dat"
  t as "Time3"
  d as "Date3"
 end-initializations

 writeln(d, ", ", t) 

For the encoding of date and time format strings please refer to the documentation of the parameters datefmt and timefmt in the 'Mosel Language Reference Manual'.

Date3 in this example uses a month name, not a number. The default 3-letter abbreviations of month names can be changed (e.g., translated) by redefining the parameter monthnames. For instance, a date written in French, such as

Date4:  "20 fevrier 2002" 

is read by the following Mosel code:

 setparam("datefmt", "%d %N %y")

 setparam("monthnames", "janvier fevrier mars avril mai juin juillet " +
          "aout septembre octobre novembre decembre")

 initializations from "datetime.dat"
  d as "Date4"
 end-initializations

 writeln(d) 

In the examples of this section we have used Mosel's standard text format for reading and writing dates and times. These data types can also be used when accessing spreadsheets or databases through Mosel's ODBC connection or the software-specific interfaces for Oracle and MS Excel. The whitepaper Using ODBC and other database interfaces with Mosel documents some examples of accessing date and time data in spreadsheets and databases.

Note: When initializing or constructing dates Mosel does not control whether they correspond to an actual calendar day (e.g., 0-valued or negative day and month counters are accepted). The validity of a date or time can be tested with the function isvalid. For example, the following code extract

 d:= date(2000,0,0)
 writeln(d, " is a valid date: ", if(isvalid(d), "true", "false")) 

results in this output:

2000-00-00 is a valid date: false 

Dates and times as constants

It is possible to use the types 'date', 'time', 'datetime' as index sets for arrays if the elements of the set are flagged as being constant. The effect of such a declaration as constant is illustrated by the following code snippet (taken from the example file dates.mos). Entities such as someday in the example below that receive a value directly in the declarations block via '=' also are constants, their value can not be changed or re-assigned.

declarations
  someday=date(2020,3,24)           ! A constant date
  SD: set of date                   ! Set of date references
  SDC: set of constant date         ! Set of constant date references
  AD: dynamic array(SDC) of real    ! Array indexed by 'date' type
end-declarations

! Operations on a set of dates
SD:= {date(2020,3,24), date(2020,3,24)+1}
writeln("Is someday in SD? ", someday in SD)             ! Output: false
writeln("Next day in SD? ", someday+1 in SD)             ! Output: false
SD+= {date(2020,3,24), date(2020,3,24)+1}
writeln("SD after addition: ", SD, " size=", SD.size)    ! Output: size=4

! Operations on a set of constant dates
SDC:= {date(2020,3,24),date(2020,3,24)+1}
writeln("Is someday in SDC? ", someday in SDC)           ! Output: true
writeln("Next day in SDC? ", someday+1 in SDC)           ! Output: true
SDC+= {date(SYS_NOW), date(SYS_NOW)+1}
writeln("SDC after addition: ", SDC, " size=", SDC.size) ! Output: size=2

The example shown here only mentions the type 'date', but the constant declaration is also applicable to the types 'time' and 'datetime'.

Conversion to and from numbers

In some cases it might be necessary to use the numerical representation in the place of a date or time. In the following Mosel extract we wish to define an array YEARS that is indexed by a set of dates. In this example we show how to use as index values the numerical representation that is obtained by applying getasnumber to the dates (this function returns an integer, the Julian Day number = number of days elapsed since 1/1/1970; if the argument is a time getasnumber returns the number of milliseconds since midnight). By applying date to the numerical representation it is converted back to the original date.

With this Mosel code

 declarations
  Dates: set of date
  YEAR: array(NDates: set of integer) of integer
 end-declarations

 setparam("datefmt", "")                 ! Use the default format

 initializations from "datetime.dat"
  Dates
 end-initializations

 writeln("Dates: ", Dates)
 forall(dd in Dates) YEAR(getasnumber(dd)):= getyear(dd)
 writeln("YEAR: ", YEAR)
 forall(n in NDates) writeln(date(n))    ! Mapping back to original dates

and the following data

Dates: [ "1999-1-21" "2000-2-22" "2002-3-23" "2005-4-24" "2010-5-25"] 

we obtain this output:

Dates: {1999-01-21,2000-02-22,2002-03-23,2005-04-24,2010-05-25}
YEAR: [(10612,1999),(11009,2000),(11769,2002),(12897,2005),(14754,2010)]
1999-01-21
2000-02-22
2002-03-23
2005-04-24
2010-05-25 

Similarly to what is shown here, function getasnumber can be used with 'time' and 'datetime', the backwards conversion being carried out by time or datetime respectively.

Operations and access functions

The following Mosel model extract (dates.mos) shows some operations on dates and times, including sorting lists of dates or times, difference between two dates or times, and addition of constants to obtain an enumeration of dates or times.

 declarations
  t: time
  d: date
  now1,now2: datetime
  DNAMES: array(1..7) of string
  TList: list of time
  DList: list of date
 end-declarations

! Difference between dates
 writeln("February 2004 had ", date(2004,3,1)-date(2004,2,1), " days.")

! Retrieve the weekday
 DNAMES:: (1..7)["Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
                 "Saturday", "Sunday"]
 writeln("1st January 2000 was a ", DNAMES(getweekday(date(2000,1,1))))

! Difference between times
 now1:= datetime(SYS_NOW)
 wait(1)                                 ! Delay model execution for 1 second
 now2:= datetime(SYS_NOW)
 writeln("Elapsed time: ", now2-now1, "ms")

! Enumeration / addition to 'time'
 setparam("timefmt", "%.h.%0M%p")
 t:= time(11,0)
 forall(i in 1..5) do
  writeln(t)
  t+=30*60*1000                          ! Add 30 minutes
 end-do

! Enumeration / addition to 'date'
 setparam("datefmt", "%.d/%0m/%0Y")
 d:= date(2005,12,20)
 forall(i in 1..5) do
  writeln(d)
  d+=14                                  ! Add 14 days
 end-do

! Sorting lists of dates and times
 setparam("datefmt", "")                 ! Revert to default date format
 DList:= [date(2021,1,1),date(1900,1,2),date(2020,3,24)]
 writeln("Orig.  DL=", DList)
 qsort(SYS_UP, DList)
 writeln("Sorted DL=", DList)

 setparam("timefmt", "")                 ! Revert to default time format
 TList:= [time(12,0),time(10,30),time(16,15),time(8,45)]
 writeln("Orig.  TL=", TList)
 qsort(SYS_UP, TList)
 writeln("Sorted TL=", TList)

Executing this model produces the following output.

February 2004 had 29 days.
1st January 2000 was a Saturday
Elapsed time: 1.006ms
11.00am
11.30am
12.00pm
12.30pm
 1.00pm
20/12/05
 3/01/06
17/01/06
31/01/06
14/02/06
Orig.  DL=[2021-1-1,1900-01-02,2020-03-24]
Sorted DL=[1900-01-02,2020-03-24,2021-1-1]
Orig.  TL=[12:00:00,10:30:00,16:15:00,8:45:00]
Sorted TL=[8:45:00,10:30:00,12:00:00,16:15:00]

© 2001-2020 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.