Vision Class: Date
Overview
Dates are objects that represent a specific day in the calendar. Any historical or future date can be represented in Vision. It is not meaningful to create new instances of the Date class.
The class DateOffset is an abstract class that supports the protocol for different date increments: BusinessDays, Days, MonthBeginnings, MonthEnds, Months, QuarterBeginnings, QuarterEnds, Quarters, YearBeginnings, YearEnds, and Years. You create instances of the DateOffset subclasses to represent increments that can be added to or subtracted from a Date.
The class DateRange represents a range of dates of a specific frequency. You create instances of this class to define specific intervals of dates for evaluation.
The Date and DateOffset classes are direct subclasses of the class Ordinal. The DateRange class is a subclass of Object:
Object | |-- DateRange | |-- Ordinal | |-- Date | |-- DateOffset |-- BusinessDays |-- Days |-- MonthBeginnings |-- MonthEnds |-- Months |-- QuarterBeginnings |-- QuarterEnds |-- Quarters |-- YearBeginnings |-- YearEnds |-- Years
Creating Dates and DateOffsets
The instances of the class Date represent a specific day in the calendar. You can create a date object by sending the asDate message to an Integer in one of the following forms:
Format | Example | Returns the String |
YYYYMMDD | 19960614 asDate | June 14, 1996 |
YYMMDD | 960614 asDate | June 14, 1996 |
YYMM | 9606 asDate | June 30, 1996 (month-end) |
YY | 96 asDate | Dec 31, 1996 (year-end) |
The magic word ^today returns the date object representing the current date. The message earliestPossibleDate has been defined at the class Object to return the Date object representing the first valid date that can be represented in Vision. This date corresponds to the first of January in the year 1.
You can add and subtract DateOffsets from a Date to create new date objects. For example:
95 asDate + 5 daysreturns the date object representing Jan 5, 1996 and:
^today - 1 monthsreturns the object representing the date one month prior to the current date.
Eleven DateOffset subclasses have been defined: Days, BusinessDays, Months, MonthBeginnings, MonthEnds, Quarters, QuarterBeginnings, QuarterEnds, Years, YearBeginnings, and YearEnds.
Valid DateOffset instances are formed by sending one of the following messages to an Integer:
Message | Example | Returns Date |
days | 95 asDate + 6 days | Jan 6, 1996 |
businessDays | 95 asDate + 6 businessDays | Jan 8, 1996 |
months | 951215 asDate - 1 months | Nov 15, 1995 |
monthBeginnings | 951215 asDate - 1 monthBeginnings | Nov 1, 1995 |
monthEnds | 951215 asDate - 1 monthEnds | Nov 30, 1995 |
quarters | 951215 asDate - 1 quarters | Sept 15, 1995 |
quarterBeginnings | 951215 asDate - 1 quarterBeginnings | July 1, 1995 |
quarterEnds | 951215 asDate - 1 quarterEnds | Sept 30, 1995 |
years | 951215 asDate - 1 years | Dec 15, 1994 |
yearBeginnings | 951215 asDate - 1 yearBeginnings | Jan 1, 1994 |
yearEnds | 951215 asDate - 1 yearEnds | Dec 31, 1994 |
When a DateOffset is added to or subtracted from a Date, another Date object is returned. Since the returned object is a Date you can add or subtract an offset from it as well. For example:
^today - 1 yearEnds + 3 daysreturns the third day of the current year.
Calculations that involve BusinessDays will only return Monday through Friday dates. Calculations that involve MonthBeginnings, QuarterBeginnings, or YearBeginnings, will only return dates that are the first day of the month, quarter, or year. Calculations that involve MonthEnds, QuarterEnds, or YearEnds, will only return dates that are the last day of the month, quarter, or year.
Calculations that involve Months, Quarters, or Years, will return dates that are on the same day in the month, as long as the date is valid. For example, the expression:
960430 asDate - 1 monthsreturns the date March 30, 1996. The expression:
960331 asDate - 1 monthsreturns the date February 29, 1996 since February 31 is not a valid date.
Date offsets that are formed by sending an increment message to the integer value 0 are used to convert a Date to a boundary relative to its current value. The following table defines these boundaries:
Example | Returns Date | Definition |
95 asDate + 0 businessDays | Dec 29, 1995 | Convert Saturday and Sunday dates to prior Friday |
95 asDate + 0 monthBeginnings | Dec 1, 1995 | First day in recipient's month |
95 asDate + 0 monthEnds | Dec 31, 1995 | Last day in recipient's month |
9511 asDate + 0 quarterBeginnings | Oct 1, 1995 | First day in recipient's quarter |
9511 asDate + 0 quarterEnds | Dec 31, 1995 | Last day in recipient's quarter |
9511 asDate + 0 yearBeginnings | Jan 1, 1995 | First day in recipient's year |
9511 asDate + 0 yearEnds | Dec 31, 1995 | Last day in recipient's year |
Basic Usage
All dates respond to the messages month, day, and year, returning integer values. For example:
960615 asDate monthreturns 6,
960615 asDate dayreturns 15, and
960615 asDate yearreturns 1996.
By default, dates print in the format month/day/year. For example:
96 asDate print ;displays:
12/31/1996The print: message prints dates in different formats, depending on the value of the supplied parameter. More information about printing dates is available.
The asInteger message can be used to convert a date to an eight-digit integer in the form YYYYMMDD. The following additional messages can be used to format date objects. They return an instance of the class String:
Message | Sample | Returns |
formatUsingMMDD | 95 asDate formatUsingMMDD | "12/31" |
formatUsingMMDDYY | 95 asDate formatUsingMMDDYY | "12/31/95" |
formatUsingMMDDYYYY | 95 asDate formatUsingMMDDYYYY | "12/31/1995" |
formatUsingShortName | 95 asDate formatUsingShortName | "31-Dec-1995" |
formatUsingLongName | 95 asDate formatUsingLongName | "December 31, 1995" |
The message getMonthDescriptor returns an instance of the class Date MonthDescriptor. This class has 12 instances, one for each month. Instances of this class respond to the messages shortName and longName. The getMonthDescriptor message returns the instance corresponding to the recipient date's month. For example:
960615 asDate getMonthDescriptor shortNamereturns the string "Jun". The MonthDescriptor class was created using the createSubclass:at: variation of the createSubclass: message so the class is only visible to Date objects.
The message getDayOfWeekDescriptor returns an instance of the class Date DayOfWeekDescriptor. This class has 7 instances, one for each day of the week. The message code returns the name of the day of the week. For example:
960615 asDate getDayOfWeekDescriptor codereturns the string "Saturday". The message dayOfWeek has been defined at the Date class to return this value as well. The DayOfWeekDescriptor class was created using the createSubclass:at: variation of the createSubclass: message so the class is only visible to Date objects.
In addition to the asDate message, the following messages can be used to convert Integer instances to Date instances:
Message | Definition | Sample |
asDateFromMMDD | Convert recipient in MMDD format to a Date object | 0315 asDateFromMMDD |
asDateFromMMDDYY | Convert recipient in MMDDYY format to a Date object | 031595 asDateFromMMDDYY |
asDateFromMMDDYYYY | Convert recipient in MMDDYYYY format to a Date object | 03151995 asDateFromMMDDYYYY |
asDateFromMMYY | Convert recipient in MMYY format to a Date object | 0395 asDateFromMMYY |
asDateFromYYYYMM | Convert recipient in YYYYMM format to a Date object | 199503 asDateFromYYYYMM |
asMonthEnd | Convert recipient month (1 - 12) to month-end Date in current year | 9 asMonthEnd |
asMonthEndInYear: | Convert recipient month (1 - 12) to month-end Date in parameter year | 9 asMonthEndInYear: 1995 |
In addition to the + offset and - offset messages, The following messages can be used to derive a Date instance from another Date:
Message | Definition | Sample |
asBDay | Convert recipient to prior Friday's date if it is a Saturday or Sunday; otherwise, return recipient | 960615 asDate asBDay |
asBDayMonday | Convert recipient to following Monday's date if it is a Saturday or Sunday; otherwise, return recipient | 960615 asDate asBDayMonday |
asCurrentYearMMDD | Convert recipient to the same month/day in current year | 920615 asDate asCurrentYearMMDD |
asMonthEnd | Convert recipient to last day of its month | 960615 asDate asMonthEnd |
asMostRecentMonthEnd | Convert recipient to last day in the month on or or before the recipient | 960615 asDate asMostRecentMonthEnd |
asQuarterEnd | Convert recipient to last day in quarter | 960615 asDate asQuarterEnd |
asYearBeginning | Convert recipient to first date in year | 960615 asDate asYearBeginning |
asYearEnd | Convert recipient to last date in year | 960615 asDate asYearEnd |
Dates and TimeSeries Data
Date objects play an important role in accessing and updating time-series data. Dates (or integer equivalents) are the parameters for the asOf: and asOf:put: messages define for the TimeSeries class. For example:
Named Currency CAD :usExchange asOf: 950315 asDatereturns the Canadian Dollar exchange rate as of March 15, 1995. The expression:
Named Currency CAD :usExchange asOf: 951315 put: 1.23 ;sets the March 15th value to 1.23.
When a message retrieves data stored in a time-varying property, it accesses the data as of a specific date. By default, this date is the current date. For example:
Named Currency CAD usExchangereturns the most recent exchange rate for the Canadian Dollar.
The evaluate: message is sent to a Date or an Integer that can be converted to a date and is used to change the default date. The parameter to this message is a block. All messages within the block that access time series properties will access the values as of this date by default. For example:
950315 evaluate: [ Named Currency CAD usExchange printNL ] ;In this case, the exchange rate is accessed as of March 15, 1995. The magic word ^date refers to the default date. For example:
950315 evaluate: [ ^date print: 15 ; Named Currency CAD usExchange printNL ; ] ;
This example displays the date 3/15/1995 followed by the exchange rate. You can change the default date within the evaluate: block. For example:
950315 evaluate: [ ^date print: 15 ; Named Currency CAD usExchange printNL ; ^date + 5 businessDays evaluate: [ ^date print: 15 ; Named Currency CAD usExchange printNL ] ; ] ;This examples displays the date 3/15/1995 followed by the exchange rate for that date. It then displays the date and exchange rate for the date 5 business days later than the original date.
Note: The evaluate: message changes the time context of the block but does not change the recipient object like the do: message. In other words, the magic word ^date is rebound by the evaluate: message but the magic word ^self is not. If you send the do: message to a Date, messages within the block will be sent to the recipient date object (i.e., ^self is rebound). The magic word ^date will not use this date. For example:960315 asDate do: [ ^date print ; #- will be ^today month print ; year printNL ; ] ; 960315 asDate evaluate: [ ^date print ; #- will be 3/15/96 ^date month print ; ^date year printNL ; ] ;
Date Arithmetic and Internal Dates
The + offset and - offset messages are used to compute a date based on another date. Several messages are also defined that allow you to perform computations between dates.
Date arithmetic is facilitated by the internal representation of the date objects. Internally, dates are stored as integers numbered consecutively from 1. This value can be accessed by sending the asIDate7 (integer form using 7-day weeks) message to a Date. For example:
95 asDate asIDate7returns the integer value 728,658. Since dates are number consecutively, internal dates can be used to compute the number of days between two dates. For example:
!date1 <- 950315 asDate; !date2 <- 950322 asDate ; (date2 asIDate7 - date1 asIDate7 ) asInteger print ;prints the value 7. The message countDaysTo: performs this same function. For example:
!date1 <- 950315 asDate; !date2 <- 950322 asDate ; date1 countDaysTo: date . asInteger print ;
Other Date Messages
The following messages perform basic comparison operations between the recipient Date and parameter Date. These messages return an instance of the Boolean class except where noted.
Message | Definition | Sample |
= | Is recipient equal to parameter? | ^today = ^date |
== | Is recipient identical to parameter? | ^today == ^date |
!= | Is recipient not equal to parameter? | ^today != ^date |
!== | Is recipient not identical to parameter? | ^today !== ^date |
< | Is recipient less than parameter? | ^today < ^date |
<= | Is recipient less than or equal to parameter? | ^today <= ^date |
> | Is recipient greater than parameter? | ^today > ^date |
>= | Is recipient greater than or equal to parameter? | ^today >= ^date |
between:and: | Is recipient value between two parameter values? | ^today between: 95 asDate and: 96 asDate . |
inRange: | Is recipient value in the range implied by the parameter, a list of two elements representing the start and end of the range inclusively? | ^today inRange: 95 asDate, 96 asDate . |
inSet: | Is recipient equal to one of the values in the parameter, a list containing one or more elements? | ^today inSet: 94 asDate, 95 asDate, 96 asDate . |
notBetween:and: | Is recipient value not between two parameter values? | ^today notBetween: 95 asDate and: 96 asDate . |
max: | Returns the larger of recipient and parameter value | ^today max: ^date . |
min: | Returns the smaller of recipient and parameter value | ^today min: ^date . |
The following messages perform basic inquiries about the recipient. These messages return an instance of the Boolean class.
Message | Definition | Sample |
isMonthEnd | Is recipient a month-end date? | ^today isMonthEnd |
isLastBusinessDayOfMonth | Is recipient the last business day of the month? | ^today isLastBusinessDayOfMonth |
isInitialDate | Is recipient the earliest possible date? | ^today isInitialDate |
Date Ranges
A DateRange is defined by specifying a starting date, and ending date, and a date offset. Starting and ending dates can be any date or an integer that can be converted to a valid date.
The general form for creating a date range is:
!dr <- date1 to: date2 by: offset ;For example:
#-- define date range of month-end dates in 1995 !dr1 <- 9501 to: 9512 by: 1 monthEnds ; #-- define weekly dates back one year !dr2 <- ^today to: ^today - 1 years by: 5 businessDays ;
DateRange objects respond to the date1, date2, and increment messages by returning the starting date, the ending date, and the date offset used to define the date range.
DateRanges respond to the evaluate: message by executing the block supplied as a parameter, once for each point in the date range. For example:
9501 to: 9512 by: 1 monthEnds . evaluate: [ ^date print: 15 ; Named Currency CAD usExchange printNL ; ] ;In this example, the US exchange rate for the Canadian currency is printed for each month-end date in 1995. The supplied block prints the evaluation date and the exchange rate. Starting with the initial date (i.e., January 31, 1995), Vision processes this block for each date in the date range, incrementing the evaluation date by the date range's offset (i.e., 1 monthEnds) until the ending date (i.e., December 31, 1995) is crossed. The magic word ^date reflects the specific evaluation date within the range as it is processing.
Date ranges can be executed in reverse order as well. When the starting date in a date range is later than the ending date, Vision will decrement the evaluation date by the offset provided. For example, if the date range in the previous example were defined using: 9512 to: 9501 by: 1 monthEnds, the exchange rates would be displayed starting with December 1995 and ending with January 1995.
Note: The evaluate: message changes the time context of the block but does not change the recipient object like the do: message. In other words, the magic word ^date is rebound by the evaluate: message but the magic word ^self is not.
The evaluate: message is defined to evaluate its block parameter for each element in the date range. Although this operation may appear to operate a date at a time, it is actually optimized internally and does not execute by sequential evaluation.
Warning!! Because date ranges are not evaluated sequentially, you do not have control over the order in which the date range is processed nor can you assume that the number of evaluations is equal to the number of elements in the range.
The iterate: message can be used instead of evaluate: when you want to evaluate the date range an element at a time. For example:
9501 to: 9512 by: 1 monthEnds . iterate: [ ^date print: 15 ; Named Currency CAD usExchange printNL ; ] ;
You can convert a DateRange into a List of Date objects using the asDateList message. For example:
!drange <- 9501 to: 9512 by: 1 monthEnds ; !dlist <- drange asDateList ; dlist count print ;The variable dlist returns a List of 12 date objects. Note that the magic word ^date will not be associated with these objects. For example:
dlist do: [ ^date print: 15 ; printNL ; ] ;In this example, the same value will print for ^date for each element in dlist. The actual value of the Date will print as the second item in the line.
The message extract:for: is used to execute a program for an object over a date range, returning a TimeSeries. For example:
9501 to: 9512 by: 1 monthEnds . extract: [ usExchange ] for: Named Currency CADreturns a time series of twelve month-end exchange rates for the Canadian currency.
Additional Information
For additional information see: