>Review of Date Objects
by
Shawn M. Gordon
President
S.M.Gordon & Associates

Introduction

Are you worried about the year 2000 yet? Can your programs handle it? How about dates in general, can you get the number of days between two dates easily? What about figure out what day of the week it is? I know I have written routines to handle some of these scenarios, but I am always amazed at the type of date computations that my clients want me to do. This brings me to this month’s review of Date Objects from Programmers Tool Shed. Date Objects is a collection of 32 routines that can do just about anything with dates from the year 1 to the year 9999, which should handle most of your programming needs. The flyer that came with Date Objects has an interesting bit of trivia about dates and leap years, it reads “In the new calendar the year was defined as 365 days, but as it takes the earth about 365 and 1/4 days to go around the sun, to keep the calendar in sync with the seasons, February has an extra day every 4 years. Unfortunately it’s not quite 365.25 so the century years are not leap years. More unfortunately, that doesn’t quite work either, so century years that are divisible by 400 ARE leap years. While this is all rather complex, it does work rather well. By the year 9999 we will only be slightly more than 2 days out of sync with the sun.”

I was glad to find out that the year 2000 is a leap year since I had already planned for it. I was distressed to find out that 1900 wasn’t, that means I have some birthday calculations floating around that aren’t quite right.

I tried the software on an HP 3000 series 37 with 2 meg of memory and 150 meg of disk running Platform 1P of MPE. The language that I tested with was COBOL 85, but the routines are callable from virtually any 3 or 4 GL, their sample code was in COBOL 74.

Features

The best way to go through this product is to tell you about each of the functions that are available and how they work. I will give you the name of the function, the short description of what it does, the parameters it takes, and an extended description or explanation of what you could use it for if necessary. A standard way to call the functions in COBOL would be like this;


WORKING-STORAGE SECTION.
01 AMERICAN-DATE   PIC 9(8)    VALUE 10211993.
01 JAPANESE-DATE     PIC 9(8)    VALUE ZEROES.

PROCEDURE DIVISION.
     CALL "PSAM2JP"  USING AMERICAN-DATE, JAPANESE-DATE.
     DISPLAY JAPANESE-DATE.

So the above routine would convert an American format date to a Japanese format date using the Date Object 'PSAM2JP'.  Dates variables should always be specified as numeric.  Now on to our examples.

PSAM2EU - Convert American date to European date.  
                    Input Parmeters:
                            American Date: MMDDYYYY 
                    Return Parameters:
                           European Date: DDMMYYYY 

PSAM2JP - Convert American date to Japanese date.  
                   Input Parameters:
                            American Date: MMDDYYYY 
                   Returned Parameters:
                            Japanese Date: YYYYMMDD 

This is an important call if you store your dates in YMD format like I do.

PSAMFMT - Format American date with custom seperators.
                     Input Parameters:
                             American Date: MMDDYYYY
                            Custom Separator Character: any single ascii character (i.e. "/")
                     Returned Parameters:
                            American Date separated by the Customer Separator: MM/DD/YYYY

This is very handy in reporting.  I know it's always tedious for me to have to format dates out.

PSA2J - Convert American date to Julian date
              Input Parameters:
                      American Date: MMDDYY
              Returned Parameters:
                      Julian Date: YYYYDDD

The nice thing here is the inclusion of the century in the Julian date that is returned.  A Julian date is the number of days since the beginning of the year.

PSCOMP - Compare Input Dates
                  Input Parameters:
                          American Date #1: MMDDYYYY
                          American Date #2: MMDDYYYY
                  Returned Parameters:
                          Date Status
                                  "B"   First date is before second date
                                  "A"   First date is after second date
                                  "S"    The dates are the same

I really like this one, I used to convert dates to century dates and then do comparisons to see which was greater.

PSDADIF - Calculate number of days between dates
                   Input Parameters:
                           American Date #1: MMDDYYYY
                           American Date #2: MMDDYYYY
                  Returned Parameters:
                         Signed Number of days difference

This one is really handy because it also takes into account the century, so your calculation will always be correct.

PSDATE - Calculate date from Serial Number
                  Input Parameters:
                           Serial Number: #######
                  Returned Parameters:
                           American Date: MMDDYYYY
                           Date Status
                                SPACE = Everything is OKAY
                               "0"         = Passed day is zero
                               "Z"        = Passed day is greater than 12/31/9999 equivalent

This Date Object is a little confusing at first.  It is used to convert the value returned by the PSDAYS date object back into a readable date.  Refer to my explanation of PSDAYS to find out what Serial Number is.

PSDAYNM - Name of Week Day
                      Input Parameters:
                              American Date: MMDDYYYY
                      Returned Parameters:
                             Name of Day (Sunday, Monday.....Saturday)

You actually get the English name for the day of the week for the specified date, great for report formatting.

PSDAYS - Calculate Serial Number from American Date
                  Input Parameters:
                           American Date: MMDDYYYY
                  Returned Parameters:
                           Serial Number: #######

The serial number is the number of days displacement from 01/01/0001.  This allows you to do any type of date calculations that you want.  You can then use the PSDATE Date Object to convert the value back to an American Date format.

PSDFRM - Days from Date
                  Input Parameters:
                          American Date: MMDDYYYY
                         +/- Number of days difference DDDDDDD
                  Returned Parameters:
                         Returned Date: MMDDYYYY  << will be zero if input date is invalid >>

By specifying a negative number you will get a date that is prior to the input date, a positive value will be a date in the future.  This is very nice for getting dates from a date and an offset value.

PSDOW - Calculate the day of the week
                 Input Parameters:
                         American Date: MMDDYYYY
                 Return Parameters:
                         Day of the week: # in the range 1:7 << 1=Sunday, 2=Monday,...7=Saturday >>

PSERR - Explanation of Error Codes
                Input Parameters:
                         DATESTATUS    Character
                Returned Parameters:
                         MESSAGE in readable form

Most of the Date Objects will return an error code if something is invalid.  This object will return an error message for the error code.

PSEU2AM - Convert European date to American date format
                     Input Parameters:
                             European Date: DDMMYYYY
                     Returned Parameters:
                            American Date: MMDDYYYY

PSEUFMT - Format European date with custom separators
                    Input Parameters:
                             European Date: DDMMYYYY
                             Custom Separator Character: any single ascii character (i.e. "-")
                     Returned Parameters:
                             European Date separated by the Customer Separator: DD-MM-YYYY

PSISIN - Is the first date between the other 2 dates
               Input Parameters:
                        Test Date:  MMDDYYYY
                        Start Date: MMDDYYYY
                        End Date:   MMDDYYYY
                Returned Parameters:
                        DATESTATUS
                              "I"   Date is in the period
                              "B"  Date is before the period
                              "A"  Date is after the period

This is great for those reports where you want all the dates for orders within a time frame.

PSJ2A - Convert Julian date to American date
              Input Parameters:
                      Julian Date: YYYYDDD
              Returned Parameters:
                     American Date: MMDDYYYY

PSJP2AM - Convert Japanese date to American date format
                   Input Parameters:
                           Japanese Date: YYYYMMDD
                   Returned Parameters:
                         American Date: MMDDYYYY

This one was critical for me since I store all of my dates in century YMD format, which just so happens to be a Japanese format date.

PSJPFMT - Format Japanese date with customer separators
                    Input Parameters:
                             Japanese Date: YYYYMMDD
                             Custom Separator Character: any single ascii character (i.e. "/")
                     Returned Parameters:
                             Japanese Date separated by the Customer Separator: YYYY/MM/DD


PSJUFMT - Format Julian date with custom separator
                    Input Parameters:
                            Julian Date: YYYYDDD
                           Custom Separator Character; any single ascii character (i.e. ".")
                    Returned Parameters:
                           Julian date separated by the Custom Separator: YYYY.DDD

PSLEAP - Test for Leap Year
                 Input Parameters:
                         Year YYYY
                 Returned Parameters:
                        DATESTATUS
                               "T"   True- the year is a Leap Year
                               "F"   False- the year is not a Leap Year

PSMFRM - Months from date
                   Input Parameters:
                           American Date: MMDDYYYY
                          +/- Number of months MMMMMMM
                   Returned Parameters:
                          Returned Date: MMDDYYYY  << zero if input date is invalid >>

Entering a negative value for months will give you a date that is 'n' months prior to the current date, a positive value will be a future date.

PSMODIF - Calculate the number of months between dates
                    Input Parameters:
                             American Date #1: MMDDYYYY
                             American Date #2: MMDDYYYY
                    Returned Parameters:
                            Number of months between difference: #######

PSMONNM - Name of the Month
                       Input Parameters:
                               American Date: MMDDYYYY
                       Returned Parameters:
                              Month Name: XXXXXXXXX

This is very cool, you will get the full English spelling of the month for the specified date.

PSTDATE - Test date for validity
                    Input Parameters:
                            American Date: MMDDYYYY
                    Returned Parameters:
                            Date Status: One ASCII character
                                              " " - Valid date
                                              "Y" - Year is zero
                                              "J" - Month is less than one
                                              "D" - Month is greater than 12
                                              "0" - Day is zero
                                              "1" - Day is greater than 30 in a 30 day month
                                              "2" - Day is greater than 31 in a 31 day month
                                              "9" - Day is out of range for February in a leap year
                                              "8" - Day is out of range for February in a non leap year

The date objects assume that you are passing a valid date to the routines, this keeps the overhead on the routines down.  You can use this date object to validate the dates before passing them to the other routines.

PSTEUR - Test date in European format for validity
                  Input Parameters:
                          European Date: DDMMYYYY
                  Returned Parameters:
                          Exactly the same as for PSTDATE

PSTJP - Test date in European format for validity
              Input Parameters:
                       Japanese Date: YYYYMMDD
              Returned Parameters:
                      Exactly the same as for PSTDATE

PSTJUL - Test date in Julian format
                 Input Parameters:
                         Julian Date: YYYYDDD
                 Returned Parameters:
                         Date Status: One ASCII characters
                                           " "  - Valid date
                                           "Y" - Year is zero
                                           "0" - Day is zero
                                           "6" - Day is <;> 365 on non leap year
                                           "7" -  Day is <;> 366 is leap year

PSUNFMT - Unformat a character string
                     Input Parameters:
                             Character String up to 30 characters with imbedded numbers
                             Length of imbedded string
                      Returned Parameters:
                             Imbedded number

This Date Object is amazing, it will pull out all the number from a string.  I tested this by input "SMG03FD04LLL1994" and it returned 03041994.  It's main purpose is to remove format characters from a date string, but I wanted to test the extreme.

PSWFRM - Weeks from date
                   Input Parameters:
                           American Date: MMDDYYYY
                           +/- Number of weeks WWWWWWW
                   Returned Parameters:
                          Returned Date: MMDDYYYY  << zero if input date is invalid >>

This will return a date that is offset plust or minus the number of weeks specified.

PSWHAT - Intuitive Date Finder
                   Input Parameters:
                           Occurrence
                           Day of the week
                           Month 
                           Year 
                   Returned Parameters:
                           Returned Date: MMDDYYYY
                           DATESETATUS
                                 SPACES  A valid date was found
                                 "N"          An invalid date was found << returned date will be set to zero >>

This is one of the most powerful date objects.  It allows you to generate a date based on information such as "the third Monday in May 1995".  There are many times I have wanted to do this type of calculation.

PSWKDIF- Calculate the number of weeks between dates
                   Input Parameters:
                           American Date #1: MMDDYYYY
                           American Date #2: MMDDYYYY
                   Returned Parameters:
                          Weeks Difference: +/- ########

This will return the number of weeks as a whole number rounded down, so if there are 13 days between the two weeks you will get a value of 1.

PSYRDIF - Calculate the number of years between dates
                   Input Parameters:
                           American Date #1: MMDDYYYY
                           American Date #2: MMDDYYYY
                   Returned Parameters:
                          Years Difference: +/- ########

This follows the same rules as PSWKDIF, it does however calculate across centuries correctly.

There you have it, all the routines, what they do, and what parameters they take. Some of these may seem trivial or unnecessary, but if you have ever tried to do date math you will realize that none of them are easily done. I used every Date Object that was supplied and I was really impressed at how much work could be saved with these routines. It’s nice to have centralized standard routines for this kind of stuff instead of reinventing it every time you need to find out something like if you Fiscal Year has crossed a Calendar Year yet.

Usability (also installation)

I got a special installation on diskette because of my cartridge drive, and this was completely automated, I only had to type in two commands and everything was uploaded from my PC to my 3000 in about 10 minutes. You can put the software in any group or account you want, so maybe you will want to make a special group for it to accommodate all the sample programs.

In terms of usability, well if you have ever used system intrinsics or Image data base call’s, you are not going to have any trouble calling a date object. All they are are subroutines with parameters, couldn’t be easier.

Reliability

<:#1680,10800>This stuff is great, I even tried to fake it out by passing the parameters as X types instead of 9 and it worked fine. If you have every used the date functions that are in the ’89 addendum to the COBOL 85 standard, you will know how picky they are, if you
r date is anything other than a PIC 9(08) it won’t work, the COBOL routines that is. COBOL functions can’t even handle if the date is broken down in subordinate levels, it must all be defined at the top level of the variable declaration. Date Objects has no such problem, you can break them down as much as you want it seems, I couldn’t seem to make them break, which is of course the desirable result.

Performance

I didn’t see any performance hit from the routines, but they have to making some sort of impact. I imagine if you did a serial read of a large file or data set and called several routines for each record you would probably start to get a measurable hit. I wouldn’t be to worried about it however. The code seems to be well written and executes quickly from what I could tell by my call’s to PROCTIME.

Supportability (including Doc)

The documentation is great. It is very complete and easy to read, the fact that all the examples are in COBOL made it that much easier for me to work with. Even if you are working in another language, the COBOL examples are clear enough that you won’t have a problem, remember COBOL is in English. There are a few mistakes that I found in the manual, but they have been corrected since I reported them.

Although I didn’t need any help with the product I did call to answer some generic philosophical questions about dates. Response is prompt and sure, no “Let me get back to you”, they always had the answer, and they seemed to always be correct.

Summary

I’ve said this before, but let me say it again, “Don’t let a low price fool you”. There are plenty of high quality products out their for very modest prices. Most vendors would sell their products cheaper, but the public seems to demand that high price will equal high quality, and this just isn’t the case. In the case of Date Objects it is less than a thousand dollars. Even if you had a hard copy of the code you couldn’t type it in fast enough to make it cost effective, let alone develop it yourself.

This product is solid, and it provides a slew of handy routines. I had one very special case that I wanted to do, and that was count the number or days between two dates, but exclude the weekends, although this wasn’t in the product they were willing to add it (we are still talking about doing it). At first I was distressed to see that all the dates were in MMDDYYYY format, but that is an American date format, and that is the correct way to represent it. I store all my dates in YYYYMMDD format, turns out that is a Japanese format, and since they support the Japanese date format for conversions I didn’t have any problem there. I would have kind of liked to have seen the date format routines give you the option of returning a 2 digit year since that is so common on most reports currently. That will probably change in the year 2000 though, because who wants to see a date 01/04/00.

If you are working with dates at all I would recommend that you buy this product. It’s going to save you a lot of time, and it has already been thoroughly tested. I can’t even come up with any complaints, although what would be really neet is a procedure that took a date expression and returned the value of the result, but that would sort of do away with all the other routines.

At-a-Glance box

Date Objects avaiable from Programmers Tool Shed
31097 Alehzon Circle
Temecula, CA 92592
Phone (909) 699-4287
FAX (909) 699-5024

Cost is $995, right to copy is $550, optional support is $99 per year, per system. 90 days free support is included with the product. There is no run time expense so you are free to incorporate it into your own products, you just need to buy a copy for each development environment.