STM$PKG Rev. 11 - A Date/Time Package Based on SYS$TIME/DWTIME$/MODSWTIME$
STM$PKG is a date/time retrieval and editing package. Its purpose is to:
1) Retrieve and convert date/time items based on ER SYS$TIME ("timeb" format), ER DWTIME$, ER MODSWTIME$, or the SWTIME word (local or UTC seconds, obtained by dividing DWTIME$ by 1 billion) instead of earlier ERs such as TDATE$ or DATE$. STM$PKG can assist in migrating programs as these older formats are phased out.
2) Provide a way of editing these items, as well as TDATE$ words, using only the basic EDIT$/AEDIT$ functions, without requiring the greatly expanded EDIT$T, AEDIT$T, and AEDIT$SFDT routines or the new routines TIMESUBR$ and TIMECONV$.
3) Perform the signon functions of the ID$ routine without requiring the additional SYSLIB elements ID$, SFDT$, and SDFTBL$.
STM$PKG contains these relocatable elements:
STM$PKT - Basic timestamp retrieval and conversion, also called by the *flagged routines below.
STM$AED$ - ASCII editing interface (AEDIT$).
STM$ED$ - Fieldata editing interface (EDIT$).
STM$TD$CV - Convert a TDATE$ word prior to editing.
*STM$YMDSW - Convert a given year, month, and day to STM$PKG format.
*STM$TD$SW - Convert standard, reversed, or modified TDATE$ word to STM$PKG format.
*STM$DT$SW - Convert a pair of DATE$ format words to STM$PKG format.
*STM$DSEC - Convert current timestamp or TDATE$ word to STM$PKG format and return the days & seconds after 12/31/1899. Also, convert a previously returned (days,seconds) word to STM$PKG format.
STM$SWT$TD$ - A routine to create a TDATE$ timestamp from the current STM$PKG packet (valid only though 2027).
*STM$MDYSW - A routine to convert a month/day/year call into one for STM$YMDSW.
TM$HMSMS - A standalone routine to convert an ER TIME$ word or elapsed time in milliseconds to store in a given address.
SWT$MSW - A standalone routine to convert a local SWTIME word to a MODSWTIME$ word using current local time zone and (optionally) seasonal offsets.
DSEC$MSW - A standalone routine to convert a (days,seconds) word to a MODSWTIME$ word similarly to SWT$MSW.
STM$PACKET$ - A separate STM$PKG packet, in case a program does not define its own.
The elements are separated based on the function they perform so that only those needed by your program are collected.
All routines use only the EDIT$ registers (X11, A0-A3, R1) and R0 (traditional reentrant version). There are reentrant and nonreentrant versions of each.
There are also three procedures: S$TMED and S$TMAED for editing, and S$TMID to provide the same functions as the ID$ routine using S$TM[A]ED. These procs are available in the ASM PROC element S$TMPROCS and the MSD omnibus STM$ED$DEF.
For size comparison, below are listed the sizes of the STM$PKG elements and the sizes of the SYSLIB elements they replace, showing how STM$PKG can help keep down the size of Basic Mode programs that might have expanded significantly because of these updated SYSLIB elements.
STM$PKG Rev. 11 | SYSLIB 77R2 ----------------+--------------- STM$PKT 100 | AEDIT$SFDT 688 STM$AED$ 123 | AEDIT$T 619 STM$ED$ 99 | EDIT$T 606 STM$TD$CV 23 | TIMECONV$ 703 STM$YMDSW 20 | TIMESUBR$ 150 STM$TD$SW 16 | STM$DT$SW 33 | ID$ 505 STM$DSEC 32 | SFDT$ 833 STM$SWT$TD$ 10 | SFDTBL$ 20 STM$MDYSW 5 | TM$HMSMS 12 | SWT$MSW 16 | DSEC$MSW 8 | STM$PACKET$ 10 | ----------------+--------------- -Total- 507 | 4124 (Octal: 0773 | 010034)
STM$PKG routine word counts vary based on mode (nonreentrant, reentrant) and CONFIG parameters, as discussed in later sections. The totals shown above are for the nonreentrant version and default CONFIG parameters. For other versions the overall totals are about 20 less for traditional reentrant or predefined registers A4-A19, R0, or R2-R15; and 40 less for predefined registers X1-X10.
On a side note, the relocatable SYSLIB 77R2 level of BSP$ is not only 173 words larger but calls two entry points in TIMESUBR$. Those entry points are only needed if BSP$ interface level 3 is used, so if level 3 and TIMESUBR$ are not needed, they may be excluded by adding the following statements to the MAP:
NOT TIMESUBR$ EQU TC$DTOYMD$/0, TC$YMDTOD$/0
BSP$ 77R2 also calls ER TIMEBYINDEX$ when inserting an element with a zero timestamp, which could cause a problem if a program collected with it is executed on a system that does not yet have it.
Alternatively, you could save a copy of the 77R1 BSP$ relocatable and use it instead; but be aware that this level still calls ER TDATE$ when inserting an element with a zero timestamp.
STM$PKG requires this 10- or 12-word packet. Words 0-3 are filled by calls to ER SYS$TIME or ER DWTIME$, pre-stored by the caller, or used for intermediate storage. Words 4-6 are filled by STM$PKT or any of the other STM$PKG routines. Words 8-9 are used to hold the editing string for S$TMED/S$TMAED calls; otherwise they may be used as intermediate storage. Words 10-11 are needed only if the configuration tag YR2988 is set to 1.
| H1 | H2 | | S1 | S2 | S3 | S4 | S5 | S6 | |-----------------------------------------------------------------------| 0-| UTCNSECS | 1 | (2 wds) | |-----------------------------------------------------------------------| 2 | SEASON | + TZOFF | |-----------------------------------------------------------------------| 3 | TZABBR | |-----------------------------------------------------------------------| 4 | SWTIME | |-----------------------------------------------------------------------| 5 | YEAR | MONTH | DAY | WEEKDAY | |-----------------------------------------------------------------------| 6 | HOUR | MINUTE | SECOND | MSECS | |-----------------------------------------------------------------------| 7 | X10MOD | X11MOD | |-----------------------------------------------------------------------| 8-| EDTSTG | 9 | (2 wds) | |-----------------------------------------------------------------------| 10-| SWT2WD | 11 | (2 wds) | |-----------------------------------------------------------------------| |UTCNSECS | 0 | UTC TIME OR DWTIME$ IN NANOSECONDS |SEASON | 2,,H1 | SEASONAL OFFSET IN SECONDS |TZOFF | 2,,XH2 | TIME ZONE OFFSET IN SECONDS |TZABBR | 3 | TIME ZONE ABBREVIATION IN ASCII |SWTIME | 4 | UTCNSECS LOCALIZED & CONVERTED TO SECONDS |YEAR | 5,,H1 | YEAR (1900-????) |MONTH | 5,,S4 | MONTH (1-12) |DAY | 5,,S5 | DAY (1-31) |WEEKDAY | 5,,S6 | WEEKDAY INDEX (0-6, 0=SUNDAY) |HOUR | 6,,S1 | HOUR (0-23) |MINUTE | 6,,S2 | MINUTE (0-59) |SECOND | 6,,S3 | SECOND (0-59) |MSECS | 6,,H2 | MILLISECONDS (0-999) |X10MOD | 7,,H1 | SAVE OF X10 MODIFIER |X11MOD | 7,,H2 | SAVE OF X11 MODIFIER |EDTSTG | 8 | EDITING STRING |SWT2WD | 10 | TEMP SAVE OF 2-WORD SWTIME |-------------------------------------------------------------------------
2. Generation and Configuration [Top][Contents]
The released nonreentrant version with default parameters is adequate to support dates from 1901-01-01 through 2100-02-28. If you are using this version, you can skip this section. If regenning is necessary, the runstream STM$PKG/QUICKGEN, which came with these STM$PKG routines, may be @ADDed out of the source file to generate the routines into the temporary file STM$PKGREL using an SSG skeleton. First, attach the @USE name REL to the release source file.
There are two SGSs in the runstream that control this generation:
1. MODE - Controls how many versions of the routines are generated with the given configuration tags, and for which modes (nonreentrant, reentrant, or predefined register). See the next section for a discussion of these modes.
Format: MODE MODE1[,COPY[X],file,version] MODE2[,COPY[X],file,version]
Each MODEn specifies a generation mode such as STM$NR (nonreentrant), STM$RE (traditional reentrant), or STM$rg (predefined register rg). These names may appear with or without the prefix STM$, as in NR, RE, or <rg>; but the routines will always be generated with the full name 'STM$mode' as the version.
The optional second subfield may be COPY, to copy the relocatables back to the source file, or COPYX, to copy them and also change their version names to blank. If neither is present, no copying will occur.
The third subfield may specify an alternate file into which to copy the relocatables. Format: QUAL*FILE or INTERNALNAME, no period. The file must be assigned.
If the second subfield is COPY, the fourth subfield may specify a version to change the relocatables to when copying.
Default: MODE STM$NR,COPYX . OTHER EXAMPLES: STM$RE R0 X9 STM$A19
In addition to the relocatables, the proc element S$TMPROCS and the MSD source and omnibus elements STM$ED$DEF are generated in the destination file.
2. CONFIG - Defines multiple configuration parameters that control the operation of the STM$PKG routines. There is a CONFIG image for each parameter. Formats:
CONFIG DATE$BASE,nnnn - the base for DATE$ conversion. Default: 1964.
CONFIG FDZONE,n - Determines support for editing the time zone in Fieldata. Possible values are:
0 - No support (the default).
1 - Support, assuming ASCII time zone consists only of upper case letters and space (10 additional words).
2 - Full ASCII-to-Fieldata conversion (7 additional words, plus the 256-word SYSLIB TABLE$ element, if not already being used by other routines).
CONFIG IDWOPT,n - If 1, the S$TMID proc is to obtain the absolute's compile timestamp from the newer DWTIME1$/DWTIME2$ rather than D$ATE/T$IME. If 0 (the default), this can still be selected by the 'W' option on the S$TMID call. DWTIME1$ and DWTIME2$ are introduced in CP 16.0.
CONFIG SEAOFF,nnnn - The local seasonal offset in seconds. Default: 3600. If set to 0, STM$PKG will assume that ER TIMECONFIG$ is available and use it to obtain the seasonal offset.
CONFIG YR2100,n - If 1, perform additional testing for dates after Feb. 28, 2100 to account for years that are a multiple of 100 but not leap years. Also perform additional tests to ensure correct handling of dates before 1901. Default:0.
If the YR2100 parameter is 0, calling STM$PKG functions to interpret or generate timestamps outside the range 1901-01-01 through 2100-02-28 will result in incorrect or garbage values.
Setting YR2100 to 1 adds 23 words to STM$PKT and 21 words to STM$YMDSW.
CONFIG YR2988,n - If 1, take extra steps when converting dates after Oct. 23, 2988 to avoid a divide fault. Also, generate a 12-word STM$PACKET$. It seems unlikely that this tag will ever be needed. Default: 0.
Setting YR2988 to 1 forces the setting of YR2100 to 1; adds 10 words to STM$PKT and 3 words to STM$YMDSW beyond those added by YR2100; and reduces STM$DSEC by 1 word.
Most applications will only need the nonreentrant versions of the STM$PKG routines. Only a single packet is required, allowing the packet load before each call to be omitted. The user's single STM$PKG packet is expected to be located at the externally defined tag STM$PACKET$. If that tag is not defined, a relocatable by the same name and with a packet reserved at that entry point will be included at collection time. (Having multiple programs in the same file that use the nonreentrant version may occasionally cause MAP warnings that the entry point is already defined. These may be ignored.)
STM$PKG as released contains only the nonreentrant version with blank version names. If this is the one you are using, you can skip the rest of this section.
There are two types of reentrant versions: traditional and predefined packet register. In the traditional version the packet address is loaded into A0 before every call. In the predefined register version a little-used or unused register is always assumed to contain the packet address and so only needs to be loaded once or a few times.
By default the @ADD runstream STM$PKG/QUICKGEN mentioned earlier generates the routines into temporary file STM$PKGREL under the STM$NR version (nonreentrant). It then copies them back to the source file and changes the version names to blank. Multiple versions may be generated and coexist in the same library file as long as a CLASS directive is used at @MAP time to select the desired version. Alternatively, the user may copy the preferred version into his own file, deleting the version name if desired, so they will always be LIB'd in:
@COPY,RVX STM$PKGREL./STM$xx,MYFILE.
Note that the version name given to predefined packet register relocatables is the register name preceded by 'STM$': STM$R0, STM$A19, etc.
The STM$PACKET element is the same for all versions unless the configuration tag YR2988 was set to 1, causing the generation of a 12- versus 10-word packet.
The MSD source and omnibus STM$ED$DEF, as well as the procedure element S$TMPROCS, are also the same for all versions unless YR2988 was set to 1 or the IDWOPT tag was set to 1 to have the S$TMID proc default to the W option for retrieving the absolute timestamp.
The user may alter the MODE SGS image to generate as many predefined register versions as desired, tailored to individual applications. You may specify any register except X11, A1-A3, or R1. This includes the four registers beyond A15, designated A16, A17, A18, and A19, though usually referenced as A15+n. It also includes register R0, not typically used in coding but available and normally not altered in Basic Mode. Specifying A0 has the same effect as STM$RE. It is permissible to use X1-X3, but since they are used by EDIT$ & AEDIT$ via S$TMED & S$TMAED, they must be avoided if any editing is to be done.
The nonreentrant version uses the same packet throughout. Therefore, all loads of the packet address, as well as the packet address in procedure calls, may be omitted in the call instructions that follow.
The traditional reentrant version allows multiple packets to be used by single- or multi-activity programs. The packet address is loaded into A0 before every call.
The predefined packet register reentrant version also allows multiple activities and packets, so long as each activity loads the predefined register with the address of its own packet. As with the nonreentrant version, packet loads before each call may be omitted. (A16-A19 are "extra" registers, and so must be stored into, not loaded.)
For all versions, when @MAPping programs be sure to LIB the file where the desired version is located, and if need be use a CLASS directive to specify the desired version if more than one version exists in the file.
STM$PKG can not only generate multiple modes using the same set of CONFIG tags; it can also generate multiple sets of modes with different CONFIG tags. This is done by modifying the generation runstream to insert additional SGSs.
The default MODE and CONFIG SGSs can be thought of as the "blank" set. To generate additional sets, assign each set a name and add an SGS called GENID listing those names:
GENID Y21 D2K
Then create MODE and CONFIG SGSs for each set by preceding the SGS label with the set name, as in these examples:
Y21MODE NR,COPY,Y21FILE,Y21 Y21CONFIG YR2100,1 Y21CONFIG FDZONE,1 ...
D2KMODE X4,COPYX,TESTFILE A19,COPY,TESTFILE2,REGVER D2KCONFIG DATE$BASE,2000 ...
(Any CONFIG tags omitted will assume default values.)
The following list shows the various types of calls to STM$PKG for retrieving and/or converting. After every call the packet items in words 4-6 will have been set and ready for editing or other use, except where noted for individual routines. In general, dates converted from older formats (TDATE$, DATE$) will have their time zone undefined and milliseconds set to zero. The weekday index, however, will be valid.
The routines in 1-10 and 11c will also return the Julian day, or day-of-year (1-366) of the date just converted in A1.
Routines that may involve a modified SWTIME word (3, 7, 10, 11a, 11b) will store that MODSWTIME$ word in word 0 of the packet (UTCNSECS), while the locally converted SWTIME will be stored in word 4 as usual.
1. Obtain current SYS$TIME and convert (assumes ER available on system):
[ LA,U A0,PACKET ] . (Omit for nonreentrant or predefined) LMJ X11,STM$PKT .
2. Obtain current DWTIME$ and convert. Offsets and time zone will be zeroed.
[ LA,U A0,PACKET ] . LMJ X11,DWT$PKT .
3. Obtain current MODSWTIME$ and convert. The MODSWTIME$ word will be stored in word 0 of the packet (UTCNSECS), while the locally converted SWTIME will be stored in word 4 as usual. Assumes MODSWTIME$ ER available on system.
[ LA,U A0,PACKET ] . LMJ X11,MSW$PKT .
3.1.2. Convert Pre-Stored or Pre-Loaded Timestamp [Top][Contents]
4. Convert a pre-stored SYS$TIME:
ER SYS$TIME . DS A0,PACKET . DS A2,PACKET+2 . [ LA,U A0,PACKET ] . LMJ X11,STM$PKTPS .
5. Convert a pre-stored DWTIME$:
ER DWTIME$ . DSL A2,72 . Zero offsets & time zone DS A0,PACKET . DS A2,PACKET+2 . [ LA,U A0,PACKET ] . LMJ X11,STM$PKTPS .
6. Convert an SWTIME word, assumed to be local. Time zone will be undefined.
[ LA,U A0,PACKET ] . LA A1,SWTIME-wd . LMJ X11,STM$PKTSW .
7. Convert an SWTIME word, assumed to be UTC, to local using the current time zone and seasonal offsets. Time zone will be undefined. A MODSWTIME$ word (bit 0 set) will be converted according to the local time zone and seasonal offsets.
[ LA,U A0,PACKET ] . LA A1,SWTIME-wd . LMJ X11,STM$PKTSWU .
3.1.3. Convert Date or Older Timestamp [Top][Contents]
8. Convert a year, month, and day (at 00:00:00) into STM$PKG format. Time zone will be undefined. The year must be at least 1899 but may go beyond 2027. If the year is 1899 or less, a date of 1899-12-31 will be assumed. (See also the YR2100 configuration parameter, which must be set to correctly handle dates outside the range 1901-01-01 through 2100-02-28.) If desired, a time of day in seconds may be loaded into R1 to combine with the date for the resulting local SWTIME. In this case use the second entry point.
HSSS FORM 18,6,6,6 . [ LA,U A0,PACKET ] . LA A1,(year,month*/12+day*/6) . Ex: LA A1,(HSSS 2017,8,31,0) [ LR R1,time-in-secs ] . { LMJ X11,STM$YMDSW . { LMJ X11,STM$YMDSWT . (If time loaded in R1)
Note that the format of the word loaded into A1 is the same as word 5 of the packet, minus the weekday index, which is ignored on input but stored after conversion.
[An earlier version of this routine required A1 to be in the format (month*/6+day,year). This format, with entry points STM$MDYSW and STM$MDYSWT, is still supported via a separate routine.]
9. Convert a pair of DATE$ words into STM$PKG format. Time zone will be undefined. The DATE$ format (Fieldata 'MMDDYYHHMMSS') means that the year must be associated with a century before it can be converted. This is done by defining a "base year" for DATE$ conversion. The default base year in STM$PKG is 1964, in keeping with the original range of DATE$ (1964-2063). This default can be changed by loading R1 with a different base year, such as 2000, and calling the alternate entry point; or by changing the CONFIG parameter DATE$BASE and regenning.
[ LA,U A0,PACKET ] . DL A1,(DATE$-WORDS) . [ LR,U R1,base-year ] . (DATE$ range = base thru base+99) { LMJ X11,STM$DT$SW . { LMJ X11,STM$DT$SWY . (If base year loaded in R1)
10. Convert a TDATE$ word into STM$PKG format. Time zone will be undefined. If the TDATE$ word is negative (bit 0 set) for the standard or reversed call, it will be recognized and converted as a MODSWTIME$ word. There are three entry points, depending on the type of TDATE$ word:
[ LA,U A0,PACKET ] . LA A1,TDATE$-wd . { LMJ X11,STM$STD$SW . Standard TDATE$ (mdy,secs) { LMJ X11,STM$RTD$SW . Reversed TDATE$ (secs,mdy) { LMJ X11,STM$MTD$SW . Modified TDATE$ (ymd,secs)
3.1.4. Working with (Days,Seconds) Words [Top][Contents]
11. The routines in 11a and 11b return the "(days,seconds)" word in A1. This is defined as the days since Dec. 31, 1899 in H1 and the time of day in seconds in H2, based on the locally converted time. This format can be used for monitoring the age of a file or other item, or for greater/less-than age comparison of two items.
All routines in this section return with registers as follows:
A0 - HWDATE (the days portion of days,seconds).
A1 - The (days,seconds) word.
A2-A3 - Words 5-6 of the STM$PKG packet, so date/time components may be saved in case the packet is overwritten.
Just as SWTIME is a convenient single-word timestamp in seconds, the days portion of the (days,seconds) word could be thought of as HWDATE (half-word date), a useful format derived by dividing SWTIME by 86400, the number of seconds in a day. It will be valid as a half-word through 2616. The seconds portion is the remainder from that division.
Since conversion between SWTIME and (days,seconds) requires only a few words of code, you may want to consider, based on what your program is doing, whether it is more economical to use these routines, or to write a short local routine and thereby avoid collecting the STM$DSEC element.
11a. Convert a TDATE$ word to STM$PKG format and return the (days,seconds) word in A1. Weekday will be defined, time zone will not, and milliseconds will be zero. If the TDATE$ word is negative (bit 0 set) for the standard or reversed call, it is recognized and converted as a MODSWTIME$ word.
There are three entry points, depending on the type of TDATE$ word:
[ LA,U A0,PACKET ] . LA A1,TDATE$-wd . { LMJ X11,STD$DSEC . Standard TDATE$ (mdy,secs) { LMJ X11,RTD$DSEC . Reversed TDATE$ (secs,mdy) { LMJ X11,MTD$DSEC . Modified TDATE$ (ymd,secs)
11b. Convert a newly-retrieved or existing timestamp to STM$PKG format and return the (days,seconds) word in A1. There are five entry points:
[ LA,U A0,PACKET ] . [ LA A1,SWTIME-wd ] . (SWTL$DSEC or SWTU$DSEC only) { LMJ X11,DWT$DSEC . Retrieve new DWTIME$ & convert { LMJ X11,STM$DSEC . Retrieve new SYS$TIME & convert { LMJ X11,SWT$DSEC . Return (days,secs) for local SWTIME . currently in packet { LMJ X11,SWTL$DSEC . Convert local SWTIME loaded in A1 { LMJ X11,SWTU$DSEC . Convert possibly modified UTC SWTIME . loaded in A1.
11c. Convert the (days,seconds) word supplied in A1 into STM$PKG format. This is intended for converting or editing a previously saved (days,seconds) word returned by any of the routines in 11a or 11b.
[ LA,U A0,PACKET ] . LA A1,daysecs-wd . LMJ X11,DSEC$SWT .
3.1.5. Standalone Routines [Top][Contents]
12. Convert a time of day from ER TIME$ or an elapsed time in milliseconds into hours, minutes, seconds, and milliseconds; and store them respectively into S1, S2, S3, and H2 of the word whose address is loaded in A3. This routine does not specifically involve the STM$PKG packet, but the output word is the same format as word 6 of the packet. If A3 is loaded with the address of that word, then on return S$TMED or S$TMAED may be used to edit the time. Uses X11, A0-A3.
On return A0, A1, and A2 still contain the hours, minutes, and seconds. Because the input word may be an elapsed time, the number of hours may exceed 23. If it exceeds 63, only the value in A0 will be valid, since it is too large to fit in S1 of the word.
LA A0,MSECS-word . LA,U A3,Output-Addr . LMJ X11,TM$HMSMS . [ Or: LMJ X11,TM$HMSMSER ] . To do ER TIME$ first (omit load of A0)
13. Convert a local SWTIME word, such as the one stored in word 4 of the STM$PKG packet, to a MODSWTIME$ word, using the current time zone and seasonal offsets as returned by ER SYS$TIME. Alternatively, convert a (days,seconds) word to a MODSWTIME$ word in the same manner.
In either case, the result is returned in A1, with bit 0 set and bit 1 set if the CURRENT seasonal offset is nonzero (which may not necessarily have been the case when the input word was generated). As with TM$HMSMS, this is a standalone routine that does not involve the STM$PKG packet. Uses X11, A0-A3, R1.
To have either routine use only the time zone offset and not the seasonal offset when converting, call the alternate entry point formed by adding 'NS' to the name.
LA A1,SWTIME-word . LMJ X11,SWT$MSW[NS] .
Or: LA A1,(days,secs) . LMJ X11,DSEC$MSW[NS] .
14. Convert the local SWTIME and date words currently in the STM$PKG packet to a TDATE$ word, which will be returned in A0. The year is assumed to be in the range of 1964-2027; else the result will be invalid. Uses X11, A0-A3.
Although this routine requires an STM$PKG packet address as input, it is standalone in that it does not involve any of the other routines.
LA,U A3,STM$PKG-packet . LMJ X11,STM$SWT$TD$ .
Editing of the STM$PKG date/time items is done using one of two procedure calls -- S$TMED or S$TMAED -- based on whether you are editing in Fieldata or ASCII. At the time of the call you are assumed to have opened EDIT$ or AEDIT$ and be positioned at the point in the edit buffer where the insertion is to occur. Calls to S$TMED/S$TMAED may be mixed in with any other EDIT$/AEDIT$ calls.
To make the procedures available, $INCLUDE 'STM$ED$DEF' in your program or make sure the procedure element S$TMPROCS is available when compiling.
Call:
S$TM[A]ED[,TDATE$-wd] [Packet-addr] 'Edit-string'
TDATE$-wd will be discussed in a later section.
Packet-addr is the address of the STM$PKG packet, required only for the traditional reentrant version.
Edit-string is a 1-12 Fieldata character string, left-justified and zero-filled, which will be used to control the editing of items. The procedure call ensures the string will be correctly formatted regardless of mode. Characters in Edit-string are described in the next section.
Packet-addr and Edit-string may occur in either order. If either or both is omitted, the corresponding load will not be generated. Standard U,X,J format may be used for the packet. Edit-string is always either a standalone string or a '1' or '2' followed by a U,X,J format. The '1' or '2' denotes the word length of the string; if it appears alone the string is assumed to be already loaded in A2 or A2-A3.
The typical call to S$TMED/S$TMAED will generate the following:
[ LA,U A0,Packet-addr ] . DL A2,('Edit-string') . LMJ X11,STM$ED$ . (or STM$AED$)
If the string is 6 characters or less, only one word will be generated and the jump will be to STM$ED-1, which has the instruction 'LA,U A3,0', to avoid the generation of an extra literal word.
If there might be multiple edit strings to choose from, they can be generated as standalone items by flagging them:
STGTBL . S$TMED *'Y-M-D' . S$TMAED *'N/D/Y' .
Such separately generated strings can be loaded by the proc by coding a '1' or '2' in the Edit-string field to indicate their word length, followed by the U,X,J address to use starting in the second subfield. Example:
S$TMAED PKT '2',STGTBL,*X9 .
If generating a table of such strings and it is desired they all be the same length for indexing, force shorter strings to be 2 words by right-filling them with "@" to at least 7 characters, as in 'N/D/Y@@'.
Edit-strings can also be generated at the time of loading:
DL A2,(S$TMED *'W%, M% D%, Y') .
But in such a case a '1' or '2' must still be coded as the string on the S$TMED call to let the proc know the string's length, as well as identifying it as the edit string parameter.
Whether generated as standalone or with a load instruction, in either case it is essential to use the proc call for the edit mode in which the string will be used: S$TMED for EDIT$ or S$TMAED for AEDIT$.
There are two types of characters in the string: letters that represent the various date/time items, and non-alphanumeric characters that can be used for formatting and separating. One special character, "%" (percent), may immediately follow a letter to indicate an alternate format for this item.
The following table lists the editing code letters, showing the date or time items they represent and their default and alternate formats.
Letter |Item --------|----------------------------------- Y |4-digit year R |Last 2 (rightmost) digits of year M |3-letter month abbreviation M% |Full month name N |2-digit month number N% |Month number, 1 or 2 digits D |2-digit day of month D% |Day, 1 or 2 digits W |3-letter weekday abbreviation W% |Full weekday name H |2-digit hour H% |Hour, 1 or 2 digits T #1|2-digit minute T% |Minute, 1 or 2 digits S |2-digit second S% |Second, 1 or 2 digits L |3-digit milliseconds Z #2|Time zone abbreviation -------------------------------------------
#1. Note that while 'T' is used for minutes to distinguish them unambiguously from months, an 'M' immediately preceded or followed by a colon will be converted to 'T' by the procedures, so you can safely use strings like 'H:M:S'. However, use 'HTS', not 'HMS'.
#2. The time zone abbreviation returned by ER SYS$TIME is in ASCII. By default there is no support for editing it in Fieldata unless the CONFIG parameter FDZONE is set to 1 or 2.
While migrating to these new date formats there will still often be a need to edit a TDATE$ format. The optional argument in the S$TMED call, TDATE$-wd, is provided to convert a TDATE$ word into full or partial STM$PKG format. TDATE$-wd is the address of the TDATE$ format word.
There are two forms of S$TMED call for TDATE$ words:
This type of call assumes that mostly actual TDATE$ words are to be expected, whether in standard form (mdy,secs) or reversed (secs,mdy), as in a program file. An auxiliary relocatable routine, STM$TD$CV, performs the conversion prior to editing. The typical call to this form of S$TMED with a TDATE$ word will generate the following. Note the different register usage.
Call: S$TM[A]ED,TDATE$-word [ Packet-addr ] 'Edit-string' Generates: [ LX,U X11,Packet-addr ] . LA A0,TDATE$-word . DL A2,('Edit-string') . LXI,U A1,STM[A]ED$ . (Alternate entry after converting) LMJ A1,STM$TD$CV .
If the TDATE$ word is already in A0 at the time of the call, code *0 for it in the S$TMED or S$TMAED proc call, as in S$TMED,*0 ...
When this form of S$TMED call is used for TDATE$ editing, time zone, SWTIME, weekday, and milliseconds are undefined. However, if the TDATE$ word is negative, it will be assumed to be a MODSWTIME$ word and converted accordingly before editing.
As with other parameters, the U,X,J form may be used with TDATE$-word:
S$TMED,9,X9 'D M R-H:M:S';.
Furthermore, as an aid when editing the reversed TDATE$ words from program files, flagging a non-zero J designator will generate an LXI of A0 instead of LA:
S$TMED,9,X9,*H2 'D M R' . Edit date S$TMAED,9,X9,H1 'HM:S' . Edit time
And flagging a zero (Whole word) J designator will generate an 18-bit SSC of A0 following the load to restore the word to TDATE$ format, providing its bit 0 is not set indicating MODSWTIME$ format.
S$TMED,9,X9,*W 'D M R-H:M:S' .
3.2.2.2. Mixed TDATE$/SWTIME Call [Top][Contents]
This type of call assumes that the word being loaded may be either a TDATE$ word or a MODSWTIME$ word. The S$TMED proc call will first generate a call to the STM$TD$SW element to convert it to STM$PKG format, followed by a non-TDATE$ call to STM$ED$/STM$AED$. The type of TDATE$ word expected is identified by a single character coded before the address of the TDATE$ word. Based on the sign of the word, the call will convert either the TDATE$ word or the MODSWTIME$ word to STM$PKG format, then proceed with the editing. Format:
S$TMED,'x',TDATE$-word [PKT] 'Edit-string'
where 'x' is 'S', 'R', or 'M', denoting which type of TDATE$ word is expected: standard, reversed, or modified. Note that when 'M' is used no test for a MODSWTIME$ word will be made because a modified TDATE$ will likely already have bit 0 set. Example:
S$TMED,'R',9,X9 'N/D/R H:M:S'
When this type of call is used, weekday is defined and milliseconds are zero. As MODSWTIME$ becomes the standard, this type of call should replace the TDATE$-only type from the previous section.
Because this type of call involves a call to a conversion routine followed by a call to STM$[A]ED$, the editing string may not be preloaded and indicated on the call with a '1' or '2'; it must be included on the S$TM[A]ED call, either as a standalone string or a '1' or a '2' followed by a U,X,J format.
LMJ X11,DWT$PKT . (Nonreentrant) E$DIT EDITPK . E$MSG ('THIS TEST WAS RUN ON &, AT &') S$TMED 'W%, M% D%, Y' . E$MSGR . S$TMED 'H:M:S.L.' . E$PRINT 1 . Output: THIS TEST WAS RUN ON MONDAY, NOVEMBER 6, 2013, AT 14:38:41.726. la,u a0,pkt . (Reentrant) lmj x11,stm$pkt . a$edit aedpkt . a$emsg ('Current time: &') s$tmaed pkt 'H:M:S Z' . a$eprint 1 . Output: Current time: 14:35:13 EDT E$DIT EDITPK . E$MSG ('OLD TDATE$ WORD: &') S$TMED,TDATE$-ADDR PKT 'D M R-H:M:S' E$PRINT 1 . Output: OLD TDATE$ WORD: 23 FEB 13-12:28:44
3.3. Notes on Date Calculations & Limitations [Top][Contents]
1. In the course of converting, STM$PKT performs divisions by one billion and one million. These numbers have been located respectively at externally defined tags STM$1BILL and STM$1MILL, in case the user should need them.
2. Dates beyond February 28, 2100 will need additional testing for possible adjustment, as years that are a multiple of 100 are not leap years unless they are also a multiple of 400. The code to handle this adds about 20 words each to STM$PKT and STM$YMDSW. It is currently PROC'd off but may be activated by changing the CONFIG parameter YR2100 to 1 and regenning.
The YR2100 parameter is also needed to ensure correct handling of dates before 1901 should the need arise.
3. Dates beyond October 23, 2988 must be handled differently because the usual conversion step of dividing the DWTIME$ nanoseconds by 1 billion will get a divide fault. The code to handle this adds 13 words beyond those added by YR2100. It is currently PROC'd off but may be activated if needed by changing the CONFIG parameter YR2988 to 1 and regenning. This will also force the setting of YR2100. As mentioned earlier, it is unlikely this code will ever be needed except for test scenarios.
4. October 23, 2988 is also the last full day for which a local SWTIME value can be represented as a 35-bit signed integer less than or equal to 0377777777777. (The actual upper end, SWTIME 0377777777777, is 2988-10-24 03:46:07.) STM$PKG will handle SWTIMEs up to and including the 36-bit unsigned value 0777777777777, provided the YR2988 parameter was set to 1.
5. August 17, 4077 is the last full day for which the SWTIME value will fit in a single word. STM$PKG will handle dates beyond that, but the value stored in the SWTIME cell in the STM$PKG packet will be truncated to its lower 36 bits and therefore invalid. As an aid, the two-word "SWTIME" that may have been generated during intermediate calculations will be stored in SWT2WD, provided the configuration tag YR2988 was set to generate words 10-11 of the packet.
6. September 21, 2617 is the last date for which the HWDATE value (SWTIME/86400) will fit in a half word (0777777). If the high bit of an HWDATE is used to flag it as being that ("MODHWDATE"?), as opposed to a TDATE$ format date, then the last day it will fit in a half word is November 10, 2258. This same limitation applies to the days portion of a (days,seconds) word.
7. May 27, 2444 is the last full day for which a MODSWTIME$ word is valid.
8. When converting a MODSWTIME$ word, STM$PKG will use the local time zone offset returned by ER SYS$TIME. If the seasonal offset indicator is set in bit 1, it will add the local seasonal offset to the time. The default seasonal offset is 3600 seconds (1 hour), but if the configuration tag SEAOFF has been set to 0, it will be obtained from ER TIMECONFIG$.
Bear in mind that an otherwise valid timestamp at the extreme ends of the MODSWTIME$ range - 1899-12-31 and 2444-05-28 - may be rendered invalid (out of range) by applying or removing the zone or seasonal offset.
9. The routines that are passed a TDATE$ word for conversion or editing always test bit 0 in case it is a MODSWTIME$ word. In the case where a reversed TDATE$ word is being passed, such as the STM$RTD$SW routine or a flagged proc call item (S$TMED,TDATE$-word,,*W), the test will be made before the word is shifted (SSC A1,18).
10. Because the emphasis in STM$PKG is on saving space, it does no error checking; it assumes parameters and values passed to it are in the correct format and range.
The S$TMID proc can be used to perform most functions of the ID$ routine. It generates its own calls to [A]EDIT$ as well as STM[A]ED$ and STM$PKT so the caller does not need to be already in edit mode. In addition it can optionally generate its own [A]EDIT$ and STM$PKG packets. S$TMID requires the S$TMPROCS element or an $INCLUDE of 'STM$ED$DEF'.
Unlike ID$, S$TMID only provides for a single signon line.
Call:
S$TMID[,'options'[,DATALC]] {'ID String'|stglen,stgadr} [PKTADR]
Options:
C - Include program creation date & time (format: 131029 0837:16). See W.
D - Use DWTIME$ vs. SYS$TIME to obtain current timestamp. See also T.
E - An EDIT$ or AEDIT$ packet has already been opened for this call; do not generate an internal packet or an EDIT$/AEDIT$ open call.
F - Assume Fieldata when stglen,stgadr given.
G - Generate the STM$PKG packet internally, for use by this call only. If G is not set, S$TMID will assume it is using either the nonreentrant or the predefined packet register version of STM$PKG. Compare with X.
H - Use home vs. single spacing for ID line.
I - Use ISO format for time of execution (2013-10-29 08:37:16).
M - Include milliseconds with time of execution. Ignored if I or S option.
N - Do not print ID line. The [A]PRINT$ word is always returned in A0 regardless of the N option, and the [A]EDIT$ packet is always closed.
S - Use shorter form for time of execution (131029 0837:16).
T - If used instead of D, test word 2 of packet (offsets). If > 0, implying previous SYS$TIME call, call SYS$TIME; else call DWTIME$. Not supported for predefined register version. If neither D nor T, call SYS$TIME.
U - Do not show code & data generated during the call; do an $UNLIST/$LIST.
V - If C but not W, use newer TDATE$ conversion routine vs. STM$TD$CV.
W - Retrieve program creation time from DWTIME1$/DWTIME2$ vs. D$ATE/T$IME. This can be made the default -- see Generation & Configuration section.
X - Generate the STM$PKG packet internally, but with the externally defined tag STM$PACKET$ attached. Compare with G. All other S$TM[A]ED and STM$PKT calls in the program will use this packet.
Z - Include time zone (ASCII string only unless FDZONE CONFIG parameter set). Ignored if D option.
Default format for time of execution: 2013 Oct 29 Tue 0837:16
DATALC - Location counter for generated data items. Must not be the same as the one in which the call is made. Default: 0, or 2 if current LC is 0.
'ID String' - The processor ID string; e.g., 'PROGRAM 1R1'. The ID line is edited in Fieldata or ASCII based on the mode of this string. A space is inserted after the string before the date/time items.
stglen,stgadr - Instead of a string, this field may contain the character length and address of the string. When this format is used, S$TMID will assume ASCII unless the F option is present; and no extra space will be inserted after the string.
PKTADR - User's STM$PKG packet address. Needed only for the traditional reentrant version. If omitted and neither the G nor X option is present, S$TMID will assume that either the nonreentrant or the predefined packet register version is being used.
Because of this, including the packet address for the nonreentrant version, or omitting both it and the G option for the reentrant version, can produce unexpected results.
The most economical use of space in a program that uses S$TMID and other S$TM[A]ED calls with the nonreentrant version is:
A$EDIT EDITPK . Open user's existing edit packet S$TMID,'EX' 'Signon String' . Print signon line
S$TMID will generate the STM$PKG packet with the external tag for use by the entire program, and avoid generating its own AEDIT$ packet.