ISO8601 plugin for Take Command / TCC / TCC/LE

Version 1.7.4     2024-10-02

Charles Dye

Purpose:

This plugin extends Take Command’s date-handling functions to support new date formats, including ISO 8601 week-date and ordinal-date formats, MS-DOS and ANSI day numbers, and offsets from today’s date; a larger (8,399-year), consistently enforced date range; and more consistent validity checking of input dates. Most of Take Command’s internal date-handling functions have been re-implemented to support this new functionality, and many new functions have been added to make date-handling tasks easier. A few ISO 8601-related internal variables have been re-implemented in order to make them available in older versions of 4NT and Take Command. This plugin also features a popup date picker for use in interactive batch files. The plugin also includes one new command which displays a simple calendar, and another to enforce the use of four-digit years.

In addition, there are several new functions to handle basic time-related math such as adding or subtracting times from a specified start time, reporting the difference between two times, converting local times to and from UTC time, and converting hour/minute/second times to and from decimal days.

Installation:

To use this plugin, copy ISO8601.dll, ISO8601.chm, and Holidays.ini to some known location on your hard drive. (If you are still using the 32-bit version of Take Command, take ISO8601-x86.dll instead of ISO8601.dll.) All three files should go in the same place. Load the plugin with a PLUGIN /L command, for example:

plugin /l c:\bin\tcmd\test\iso8601.dll

If you copy these files to a subdirectory named PlugIns within your Take Command program directory, the plugin will be loaded automatically when TCC starts.

Plugin Features:

New functions:
@CENTURY @DATEPLUS @DAYS @DECTOTIME @DOWIS
@EASTER @FILESTAMP @HOLIDAY @INLIEU @INRANGE
@ISDATE @ISHOLIDAY @ISTIME @JULIAN @LEAP
@LOCALDATETIME @MONTHLEN @MONTHNAME @NEXTDATE @NEXTDOW
@ORD @PICKDATE @ROMAN @TIMEDIFF @TIMEFMT
@TIMEPARTS @TIMEPLUS @TIMETODEC @USECONDS @USWEEK
@UXTODATETIME @UTCDATETIME
Enhanced functions:
@AGEDATE @DATE @DATECONV @DAY @DOW
@DOWF @DOWI @DOY @IDOW @IDOWF
@ISODOWI @ISOWEEK @ISOWYEAR @MAKEAGE @MAKEDATE
@MONTH @YEAR
Internal variables:
_ISODOWI _ISORDATE _ISOWDATE _ISOWEEK _ISOWYEAR
_T4 _TOMORROW _USECONDS _YESTERDAY
New commands:
ISO8601HELP LONGYEARS QCAL

Syntax Note:

The syntax definitions in the following text use these conventions for clarity:

BOLD CODEindicates text which must be typed exactly as shown
CODEindicates optional text, which may be typed as shown or omitted
bold italicsa required argument; a value must be supplied
regular italicsan optional argument
ellipsis…after an argument means that more than one may be given

Functions:


@AGEDATE — Converts an NTFS file age into a date and time. The returned date and time are separated with a comma. The date may be returned in any output date format supported by this plugin. If no date format is specified, ISO 8601 yyyy-mm-dd format is used by default.

Syntax:
%@AGEDATE[age,fmt,tfmt,opt]

agethe number of 100-ns ticks since midnight, January 1, 1601 (Gregorian calendar)
fmtthe date format used to return the date
tfmtthe format in which to return the time; defaults to 1408 (24-hour, with milliseconds)
optset to 1 to use T as the date-time separator character, instead of a comma

The age is the format used in NTFS file stamps, but it might be used for any event within the supported date range.

The tfmt parameter may be 0 to return the time in 24-hour format, or 1 - 12 for a variety of 12-hour formats. Add 128 to include seconds in the output time; add 256 to include milliseconds.

• Incompatibility: Unlike most of Take Command’s built-in date functions, the native @AGEDATE allows a very wide (but undocumented) range of dates. My replacement @AGEDATE function supports the same range of dates as all other functions in this plugin. Ages corresponding to dates after the year 9999 will fail with an error message.

See also: @MAKEAGE, which performs the reverse function.



@CENTURY — Returns the century number for a date or for a year.

Syntax:
%@CENTURY[date,infmt,flags]

datea date, or a four-digit year; defaults to today’s date
infmtthe input date format, used to interpret ambiguous dates
flags1 - append ordinal suffix, 2 - as a roman numeral

This function uses the convention that centuries begin with years ending in 01. The year 2000 was the last year of the 20th century, and 2001 began the 21st.



@DATE — Converts the specified date into an MS-DOS day number, with 0 being January 1, 1980. The date argument may be in any input date format supported by this plugin, and must be a valid date within the supported range. If the date is before 1980, the value returned will be negative.

Syntax:
%@DATE[date,infmt]

datethe date to convert; if omitted, uses today’s date
infmtthe input date format, used to interpret ambiguous dates

See also: @MAKEDATE, which performs the reverse function.



@DATECONV — converts a date from one format to another. The date may be in any input date format supported by this plugin, and it may be converted to any output format. It must be a valid date, and fall within the supported date range. If no output format is specified, it defaults to the local format.

Syntax:
%@DATECONV[date,infmt,outfmt]

datethe date to convert
infmtthe input date format, used to interpret ambiguous input dates
outfmtthe output date format in which the date should be returned

• Note: If you specify infmt but not outfmt, then infmt will be used for both roles: to interpret ambiguous input dates and to specify the output format.

• Note: This function does not exist in 4NT / Take Command v10 and earlier.



@DATEPLUS — adds a number of days to the specified date. The starting date may be in any input date format supported by this plugin, and the resulting date may be reported in any output date format. Both the input date and the resulting date must fall within the supported date range. If no output format is specified, it defaults to the local date format with a four-digit year.

Syntax:
%@DATEPLUS[date,offset,fmt]

datethe starting date
offsetthe number of days to add (or subtract, if negative)
fmtthe date format used to return the resulting date, and also to interpret ambiguous input dates; defaults to 256

• New: This function does not exist in Take Command.



@DAY — returns the day of the month (1 through 31) for the specified date. The date may be in any input date format supported by this plugin, and must be a valid date within the supported date range.

Syntax:
%@DAY[date,infmt]

datethe date to examine; if omitted, uses today’s date
infmtthe input date format, used to interpret ambiguous dates


@DAYS — subtracts one date from another, and returns the difference in days. Both input dates may be in any input date format supported by this plugin. Both must be valid dates, and both must fall within the supported date range.

Syntax:
%@DAYS[startdate,enddate,infmt,mode]

startdate, enddatethe dates to subtract
infmtthe input date format, used to interpret ambiguous dates
mode0 for the difference, 1 for the size of the (inclusive) range; defaults to 0

When mode is 0 or not specified, startdate is subtracted from enddate. If startdate is later than enddate, the result will be negative. If both refer to the same date, the result will be zero.

When mode is 1, the earlier date is subtracted from the later, and one added to the difference. The result will always be positive; if startdate and enddate refer to the same date, the result will be 1.

You can use this function to calculate the number of days until some future event by specifying T for the startdate:

echo Only %@days[T,%@nextdate[12,25]] days until Christmas!
echo %@days[T,%@easter[*]] days until Easter.

• New: This function does not exist in Take Command.



@DECTOTIME — converts a decimal fraction of a day into hours, minutes, and seconds.

Syntax:
%@DECTOTIME[value,tfmt]

valuea decimal fraction of a day; 0 ≤ value < 1.0
tfmtthe format in which to return the time; defaults to 128 (24-hour, with seconds)

• New: This function does not exist in Take Command.

See also: @TIMETODEC, which performs the opposite function.



@DOW — returns the abbreviated English name of the day of the week of the specified date. The date may be in any input date format supported by this plugin, and it must be a valid date within the supported range.

Syntax:
%@DOW[date,infmt]

datethe date to examine; defaults to today’s date if omitted
infmtthe input date format, used to interpret ambiguous dates


@DOWF — returns the full English name of the day of the week of the specified date. The date may be in any input date format supported by this plugin, and it must be a valid date within the supported range.

Syntax:
%@DOWF[date,infmt]

datethe date to examine; defaults to today’s date if omitted
infmtthe input date format, used to interpret ambiguous dates


@DOWI — returns the day of the week of the specified date as a number, 1 for Sunday through 7 for Saturday. The date may be in any input date format supported by this plugin, and it must be a valid date within the supported range.

Syntax:
%@DOWI[date,infmt]

datethe date to examine; defaults to today’s date if omitted
infmtthe input date format, used to interpret ambiguous dates


@DOWIS — returns 1 if the input date matches one of the specified days of the week, 0 if it doesn’t. The date may be in any input date format supported by this plugin, and it must be a valid date within the supported range.

Syntax:
%@DOWIS[dowmask,date,infmt]

dowmaska list of days of the week to test
datethe date to examine; defaults to today’s date if omitted
infmtthe input date format, used to interpret ambiguous dates

echo %@dowis[mon wed fri]
rem  (1 if today is a Monday, Wednesday, or Friday)

echo %@dowis[weekend,07/04,1]
rem  (1 if the Fourth of July falls on a Saturday or Sunday this year)

• New: This function does not exist in Take Command.



@DOY — returns the day of the year for the specified date. January 1 will return 1; December 31 will return 365 or 366. The date may be in any input date format supported by this plugin, and it must be a valid date within the supported range.

Syntax:
%@DOY[date,infmt]

datethe date to examine; if omitted, uses today’s date
infmtthe input date format, used to interpret ambiguous dates


@EASTER — returns the date of Easter for the specified year. The date may be returned in any output date format supported by this plugin. If no output format is specified, it defaults to the local date format with a four-digit year.

Syntax:
%@EASTER[year,church,fmt,offset]

yearfour digits, 1601 - 9999; * next occurrence; if omitted, defaults to the current year
church0 = Western (Catholic, Protestant); 1 = Eastern Orthodox; defaults to 0
fmtthe date format used to return the date; defaults to 256
offsetoptional number of days to add to (or subtract from) Easter’s date; useful for other moveable feasts

If you specify an asterisk for the year, @EASTER will return the date of the next Easter after today’s date. If you use an asterisk for year and specify an offset, @EASTER will return the next matching date after today’s date.

For example: When is the next Mardi Gras? (It’s celebrated 47 days before Easter.)

qcal %@easter[*,,,-47]

• New: This function does not exist in Take Command.



@FILESTAMP — returns a file’s date and time stamps, in a consistent format and with correct localization.

Syntax:
%@FILESTAMP[filename,flags,fmt,opt]

filenamethe file to examine. It may not contain wildcards. Quote it if it contains spaces, commas, or other significant characters.
flagsindicate which time stamp to return, and how to interpret it:
   W: returns the last-write (modification) time stamp; the default
   C: returns the creation time stamp
   A: returns the last-access stamp; see note below
   L: returns the selected time stamp correctly localized; the default
   U: returns the selected time stamp in UTC time, not localized
   B: uses bad, broken, backward-compatible localization; see below
fmtthe date format used to return the date; defaults to 4, ISO 8601 format
optset to 1 to use T as the date-time separator character, instead of an @ sign

This function returns a file’s date and time stamps together, in one call. The date and time will be separated by an @ sign. @FILESTAMP works like a combination of TCC’s internal @FILEDATE and @FILETIME functions, but with some differences that you should be aware of. The most important difference is that this function correctly localizes time stamps of files on NTFS volumes. It will return the same value for the same file, whether you call it in May or in December. @FILETIME, along with DIR and Explorer, can return different values for the same file depending on when you examine it. Specifically, @FILETIME et al. will return incorrect values if a timestamp on an NTFS drive was set during Daylight Saving Time, but read during Standard Time, or vice versa. In short, @FILESTAMP may return different times than @FILETIME, DIR, Explorer, and so on for NTFS files — this is a deliberate feature and not a bug! If you want localized file times to match DIR and so on, specify the B flag, or just use @FILETIME.

Since the date and time are read in one single operation, @FILESTAMP is also immune to the possible errors that may occur if some other process happens to access the target file between separate calls to @FILEDATE and @FILETIME.

The flags may be in any order. If you specify incompatible flags, e.g. W with C or L with U, the first one “wins”.

If you use the U option, the time stamp will not be localized (and will therefore agree with @FILETIME given the same option.) The returned time info will have the letter Z appended to indicate UTC time.

File times will always be returned with seconds. There is no option to suppress the seconds.

The FAT filesystem, used on floppies and most flash sticks, records only the date and not the time of the last access. If you specify the A flag for a file on a FAT drive, the last-access time will always be returned as 00:00:00. If you specify both A and U, the date will be returned as UTC, but the time will be 00:00:00Z. This behavior differs from TCC’s, but I think it’s the more correct way of handling this situation.

Wildcards are not permitted in the filename. This also differs from @FILEDATE and @FILETIME. It would be easy enough to support wildcards, but if the filename contains wildcards, then you may be getting info on a different file than you thought you were checking; I prefer to require unambiguous filenames here.

This function also supports a special output format which is not supported elsewhere in this plugin. If fmt is 276, then it will return a packed date and time without an @ sign, fourteen digits: YYYYMMDDhhmmss. (276 is 20 plus 256.) UTC timestamps will still include a Z.

New in version 1.7.2: @FILESTAMP supports internet files beginning with ftp://, http://, or https://. For internet files, options W, C, and A have no effect (there is only one time stamp to return), and times are always localized unless you specify U.

• New: This function does not exist in Take Command.



@HOLIDAY — returns the date of a specific day of the week within a month (e.g., the second Monday in October.) The date may be returned in any output date format supported by this plugin. If no output format is specified, it defaults to the local date format with a four-digit year.

Syntax:
%@HOLIDAY[index,dow,month,year,fmt,offset]

indexthe position of the day-of-the-week within month; 1 = first, 2 = second, 3 = third, 4 = fourth, 5 = final
dowthe day of the week: 1 = Monday, 2 = Tuesday, etc.; or MON … SUN
monththe month in which the holiday falls: 1 = January, 2 = February, etc., or JAN … DEC
yearfour digits, 1601 - 9999; * next occurrence; if omitted, defaults to the current year
fmtthe date format used to return the date; defaults to 256
offsetoptional number of days to add to (or subtract from) the resulting date; useful for e.g. Election Day

For example, to see when Thanksgiving falls this year: (Thanksgiving Day is the fourth Thursday in November.)

qcal %@holiday[4,thu,nov]

If you specify an asterisk for the year, @HOLIDAY will return the next matching holiday after today’s date.

• New: This function does not exist in Take Command.

A few U.S. federal holidays and other days:
Martin Luther King, Jr. Day%@holiday[3,mon,jan]
Washington’s Birthday%@holiday[3,mon,feb]
Daylight Saving Time begins%@holiday[2,sun,mar]
Mother’s Day%@holiday[2,sun,may]
Memorial Day%@holiday[5,mon,may]
Father’s Day%@holiday[3,sun,jun]
Labor Day%@holiday[1,mon,sep]
Columbus Day%@holiday[2,mon,oct]
Daylight Saving Time ends%@holiday[1,sun,nov]
Election Day (even years only)%@holiday[1,mon,nov,,,1]
Thanksgiving Day%@holiday[4,thu,nov]


@IDOW — returns the abbreviated local name for the day of the week of the specified date. The date may be in any input date format supported by this plugin, and it must be a valid date within the supported range.

Syntax:
%@IDOW[date,infmt]

datethe date to examine; if omitted, uses today’s date
infmtthe input date format, used to interpret ambiguous dates


@IDOWF — returns the full local name for the day of the week of the specified date. The date may be in any input date format supported by this plugin, and it must be a valid date within the supported range.

Syntax:
%@IDOWF[date,infmt]

datethe date to examine; if omitted, uses today’s date
infmtthe input date format, used to interpret ambiguous dates


@INLIEU — Substitutes a weekday for a weekend date. The date may be in any input date format supported by this plugin; it must be a valid date within the supported range.

Syntax:
%@INLIEU[date,fmt,mode,flags]

datethe date to check; defaults to today
fmtthe date format used to return the resulting date, and also to interpret ambiguous input dates; defaults to 256
mode0 = nearest, 1 = previous Friday, 2 = following Monday, 3 = Sunday (only) to Monday; defaults to 0
flags1: return an empty string if no substitution is made; used internally by QCAL

If the input date is a weekday, no substitution will be made.

In mode 0 (the default), if the date falls on a Saturday, the previous Friday will be returned; if it is a Sunday, the following Monday will be returned. In mode 1, either a Saturday or a Sunday input date will return the previous Friday; in mode 2, either a Saturday or a Sunday input date will return the following Monday. In mode 3, Sundays will be remapped to the following Monday, but Saturdays are returned unchanged.

As of version 1.3.10, @INLIEU adds two new modes to support some floating Chilean holidays:

4if date is a Tuesday, Wednesday, or Thursday, return the preceding Monday; if it’s a Friday, return the following Monday; otherwise, return the original date
5if date is a Tuesday, return the preceding Friday; if it’s a Wednesday, return the following Friday; otherwise just return date

• New: This function does not exist in Take Command.



@INRANGE — determines whether a date falls within a specified range. This function takes three dates, which may be in any date format supported by this plugin. All three must be legal dates within the supported date range.

Syntax:
%@INRANGE[date,startdate,enddate,infmt]

datethe date to test
startdate, enddatedefine the range to compare date against
infmtthe input date format, used to interpret ambiguous dates

startdate and enddate may be in either order. If date is within the range defined by startdate and enddate, this function will return 0. If date falls before the range (i.e. less than both startdate and enddate), the result will be -1. If date falls after the defined range (i.e. greater than both), the function will return 1.

• New: This function does not exist in Take Command.



@ISDATE — returns 1 if its argument is a valid date within the supported range; returns 0 if the argument is missing, not a valid date, or outside of the supported range. The date may be in any input date format supported by this plugin.

Syntax:
%@ISDATE[date,infmt]

datethe date to examine
infmtthe input date format, used to interpret ambiguous dates

The date argument is not optional. Unlike many of the functions in this plugin, @ISDATE will not assume today’s date if you omit it.

• New: This function does not exist in Take Command.



@ISHOLIDAY — returns 1 if the specified date matches an annual holiday, 0 otherwise. The date may be in any input date format supported by this plugin, and it must be a valid date within the supported range.

Syntax:
%@ISHOLIDAY[date,infmt,country]

datethe date to examine; defaults to today’s date
infmtthe input date format, used to interpret ambiguous dates
countrythe section in Holidays.ini; defaults to the user’s country

@ISHOLIDAY will attempt to read a list of annual holidays from Holidays.ini. If Holidays.ini is not found, if no appropriate section is found in Holidays.ini, or if no holidays are defined within that section, then a default list of United States annual holidays is used. For a list of those default holidays, see the QCAL command. For information on customizing the list, see Holidays.ini Format.

• New: This function does not exist in Take Command.



@ISODOWI — returns the day of the week for the specified date as an integer, 1 for Monday through 7 for Sunday, per ISO 8601. The date may be in any input date format supported by this plugin, and it must be a valid date within the supported range.

Syntax:
%@ISODOWI[date,infmt]

datethe date to examine; if omitted, uses today’s date
infmtthe input date format, used to interpret ambiguous dates

• Note: This function does not exist in 4NT / Take Command v10 and earlier.



@ISOWEEK — returns the ISO 8601 week number (1 through 53) for the specified date. The date may be in any input date format supported by this plugin, and it must be a valid date within the supported range.

Syntax:
%@ISOWEEK[date,infmt]

datethe date to examine; if omitted, uses today’s date
infmtthe input date format, used to interpret ambiguous dates

This function can also be used to find the number of ISO weeks in a given year by passing December 28 as the date:

echo There are %@isoweek[%_year-12-28] ISO weeks in %_year.

• Note: This function does not exist in 4NT / Take Command v10 and earlier.



@ISOWYEAR — returns the ISO 8601 week-numbering year (1601 through 9999) for the specified date, i.e. the year in which the closest Thursday falls. The date may be in any input date format supported by this plugin; it must be a valid date within the supported range.

Syntax:
%@ISOWYEAR[date,infmt]

datethe date to examine; if omitted, uses today’s date
infmtthe input date format, used to interpret ambiguous dates

• Note: This function does not exist in 4NT / Take Command v10 and earlier.



@ISTIME — returns 1 if its argument is a valid time, 0 if it is not.

Syntax:
%@ISTIME[time]

timethe time to check

• New: This function does not exist in Take Command.



@JULIAN — Converts the specified date into a day number, with 1 being January 1, 1601. The date argument may be in any input date format supported by this plugin, and must be a valid date within the supported range.

Syntax:
%@JULIAN[date,infmt]

datethe date to convert; if omitted, uses today’s date
infmtthe input date format, used to interpret ambiguous dates

• New: This function does not exist in Take Command.



@LEAP — returns 1 if the specified year is a leap year, 0 if common.

Syntax:
%@LEAP[year]

year four digits, 1601 to 9999; defaults to the current year

• New: This function does not exist in Take Command.



@LOCALDATETIME — converts a UTC date and time to the local time zone. The date may be in any input date format supported by this plugin, and must be a valid date within the supported range.

Syntax:
%@LOCALDATETIME[date,time,fmt,tfmt]

datethe UTC date to convert; defaults to today’s date
timethe UTC time to convert; defaults to the current time
fmtthe date format used to return the resulting date, and also to interpret ambiguous input dates; defaults to 256
tfmtthe format in which to return the time; defaults to 384 (24-hour, with seconds and milliseconds)

The time may be entered in either 12-hour or 24-hour format. tfmt may be 0 to return the time in 24-hour format, or 1 - 12 for a variety of different 12-hour formats. Add 128 to include seconds in the output time; add 256 to include milliseconds.

See also: @UTCDATETIME, which performs the reverse operation.

• New: This function does not exist in Take Command.



@MAKEAGE — converts a date and time into an NTFS file age. The date may be in any input date format supported by this plugin; it must be a valid date within the supported range.

Syntax:
%@MAKEAGE[date,time,infmt]

datethe date to convert
timethe time on date; if not specified, 00:00:00 is assumed
infmtthe input date format, used to interpret ambiguous dates

• Incompatibility: Unlike most of Take Command’s built-in date functions, the native @MAKEAGE allows a very wide (but undocumented) range of dates. My replacement @MAKEAGE function supports the same range of dates as all other functions in this plugin. Dates after the year 9999 will fail with an error message.

See also: @AGEDATE, which performs the reverse function.



@MAKEDATE — converts an MS-DOS day number to a date in any date format supported by this plugin. The day number must be in the range -138426 through +2929244, corresponding to dates from 1601-01-01 through 9999-12-31. If no output format is specified, the local format is assumed.

Syntax:
%@MAKEDATE[n,fmt]

nthe MS-DOS day number
fmtthe date format used to return the date

The day number is the count of days since January 1, 1980. Negative day numbers are allowed, and will return dates prior to 1980.

See also: @DATE, which performs the reverse function.



@MONTH — returns the month number (1 through 12) for the specified date. The date may be in any input date format supported by this plugin, and must be a valid date within the supported range.

Syntax:
%@MONTH[date,infmt]

datethe date to examine; defaults to today’s date
infmtthe input date format, used to interpret ambiguous dates


@MONTHLEN — returns the number of days in a given month.

Syntax:
%@MONTHLEN[month,year]

month1 through 12, or JAN … DEC; if omitted, defaults to the current month
yearcan be either 1601 through 9999, or 1 for leap years, 0 for common

The year parameter is only significant when month is 2. If year is not specified, the default is the current year.

• New: This function does not exist in Take Command.



@MONTHNAME — returns the name of a month.

Syntax:
%@MONTHNAME[month,n]

month1 through 12, or JAN … DEC; if omitted, defaults to the current month
nis one of:
 0: the full English name (the default)
 1: the English name abbreviated to three letters
 2: the full local name
 3: the abbreviated local name

• New: This function does not exist in Take Command.



@NEXTDATE — returns the next date matching a specified month and day. The date may be returned in any output date format supported by this plugin. If no output format is specified, it defaults to the local date format with a four-digit year.

Syntax:
%@NEXTDATE[month,day,date,fmt]

month1 through 12, or JAN … DEC
day1 through 31
datethe starting date, in any supported input format; defaults to today’s date
fmtthe date format used to return the resulting date, and also to interpret ambiguous input dates; defaults to 256

This function is handy for dealing with annual events which may or may not have occurred already. For example,

qcal %@nextdate[dec,25]

will display the next Christmas after today’s date — this year’s or next year’s, depending.

• New: This function does not exist in Take Command.



@NEXTDOW — returns the next date matching a specified day (or days) of the week. The date may be returned in any output date format supported by this plugin. If no output format is specified, it defaults to the local date format with a four-digit year.

Syntax:
%@NEXTDOW[dowmask,date,index,fmt]

dowmaskthe day(s) of the week to find
datethe starting date, in any supported input format; defaults to today’s date
indexwhich matching day-of-the-week to find; defaults to 1 (next after; see below)
fmtthe date format used to return the resulting date, and also to interpret ambiguous input dates; defaults to 256

When index is 1 (the default), this function returns the first matching date after today’s date (or the specified start date.) If index is set to 0, then @NEXTDOW will return the first matching date on or after today. If index is -1, then the last matching date before today’s date is returned. Higher (or lower) values for index will return later (or earlier) matching dates.

For example:

echo Next Wednesday:         %@nextdow[wed]
echo Wednesday after next:   %@nextdow[wed,,2]
echo Next Monday or Tuesday: %@nextdow[mon tue]
echo First Monday after Christmas: %@nextdow[mon,%_year-12-25]
echo Last Friday before Christmas: %@nextdow[fri,%_year-12-25,-1]

• New: This function does not exist in Take Command.



@ORD — Returns a number with an English ordinal suffix.

Syntax:
%@ORD[n]

na non-negative integer value

C:\> for /l %n in (1,1,5) echo %@ord[%n]
1st
2nd
3rd
4th
5th

Commas will be inserted for values over 999.

• New: This function does not exist in Take Command.



@PICKDATE — allows the user to select a date using a popup calendar control. The date may be returned in any output date format supported by this plugin. If no output format is specified, it defaults to the local date format with a four-digit year.

Syntax:
%@PICKDATE[title,initdate,fmt,startdate,enddate,flags,leftcol,dowmask,timeout]

titlethe caption for the popup. To include commas in the title, double-quote it.
initdatethe date selected by default when the dialog opens, in any supported input format; defaults to today’s date
fmtthe date format used to return the date; defaults to 256
startdate, enddatethe range of dates the user may select; see note below
flagsbitmapped value controlling miscellaneous features:
   2: remove the Cancel button; disable Esc and Alt-F4
   4: restrict the date range to 1980 through 2099
   128: don’t highlight holidays
   256: don’t allow the user to select holidays
leftcolday of the week in the left column; 1 = Monday, 2 = Tuesday, etc., or MON … SUN; defaults to local layout
dowmasklist of days of the week to disable
timeoutnumber of seconds before the popup automatically closes; 0 or not specified disables the countdown

Note: The startdate and enddate parameters can be entered in any of the usual input formats, with one exception. A number preceded by a + or - sign will be interpreted as an offset relative to initdate, not as an MS-DOS day number. In the unlikely event that you want to specify either startdate or enddate as a day number, either type it without a leading sign (e.g. 3766), or else prefix the letter D (e.g. D3766 or D-74324).

The date picker dialog allows the user to select a date using either the mouse or the keyboard. To select a date using the mouse, first browse to the desired month using the buttons at the top, to the left and right of the calendar’s header line. The inner pair of buttons display earlier or later months; the outer pair display earlier or later years. Once the desired month is shown, select the desired date by clicking on it, then click OK to close the dialog; or double-click on a date to select it and close the dialog immediately. (Note that it is possible to display months other than the one containing the selected date! The status line near the bottom always shows the currently selected date. Clicking on the status line will return the calendar display to the selected date.)

To select a date with the keyboard, use the arrow keys, PgUp, and PgDown to move the highlighted box. The left and right arrow keys move the selection one day backward or forward; up and down move it by one week; PgUp and PgDown move by months, and Ctrl-PgUp and Ctrl-PgDown move by years. When the desired date is selected, press Enter or click on the OK button.

Dates which are outside the specified range or otherwise disabled will appear in gray italics. You cannot select disabled dates using either the mouse or the keyboard. To cancel the dialog without selecting a date, click on Cancel or press Esc.

This function returns the user’s selected date in the specified format, or *CANCEL* if the user cancels the dialog.

For example:

set duedate=%@pickdate[Due Date,T+7,4,T,T+21,,,weekends]

Displays the date selection popup, with a caption of “Due Date”. The default due date is one week from today; the permitted range is from today through three weeks from today, and weekends are not allowed. The user’s selected date is returned in ISO 8601 format.

• Note: Holidays are highlighted by default. To disable this feature, add 128 to flags. For a list of the default annual holidays, see the QCAL command. For information on customizing the holidays, see Holidays.ini Format.

• New: This function does not exist in Take Command.



@ROMAN — Converts an integer to a Roman numeral, or vice versa.

Syntax:
%@ROMAN[n | text]

nan integer in the range 1 … 4999, or
texta Roman numeral

If the argument begins with a letter, it is assumed to be a Roman numeral, and @ROMAN will attempt to convert it into an integer (case is not significant.) If the argument does not begin with a letter, it’s an integer to be converted to a Roman numeral.

C:\> echo %@roman[%_year]
MMX

C:\> echo %@roman[cclix]
259

• Note: This function does not check that input Roman numerals are well-formed or canonical. If you pass it an ill-formed string such as VVVC or IXXM, it will return a (meaningless) integer rather than an error message; purgamentum init, exit purgamentum.

• New: This function does not exist in Take Command.



@TIMEDIFF — subtracts one time from another and returns the difference.

Syntax:
%@TIMEDIFF[time1,time2,infmt,tfmt]
%@TIMEDIFF[date1@time1,date2@time2,infmt,tfmt]

time1the time to subtract from time2
date1@time1you can also give a time on a specific date
time2if not specified, defaults to the current time
date2@time2you can also give a time on a specific date
infmtthe input date format, used to interpret ambiguous dates
tfmtthe format in which to return the time difference; defaults to 128 (24-hour with seconds)

You can specify date-time pairs for the starting and ending times. The date may be in any format supported by this plugin. Separate the date from the time with an @ sign or the letter T.

The tfmt parameter controls the display of the time difference. It’s a subset of the usual time display formats; all of the 12-hour options are disabled because they make no sense here. You can specify 0 to return only hours and minutes; add 128 to include seconds; add 256 to include milliseconds; or add 1024 or 2048 to left-pad the hours field with zeros or spaces, respectively. You can also specify format 15 to return the time difference as a fraction of a day.

The difference between the two times will be reported as a positive value, regardless of whether time1 is before or after time2.

rem  How long until 8 o'clock Christmas morning?
echo %@timediff[%@nextdate[12,25]@8:00]


• New: This function does not exist in Take Command.



@TIMEFMT — formats a time for display.

Syntax:
%@TIMEFMT[time,tfmt]

time:the time to format; defaults to the current time
tfmt:the format in which to display it

The time may be entered in either 12-hour or 24-hour format. tfmt may be 0 to return the time in 24-hour format, or 1 - 12 for a variety of different 12-hour formats. Add 128 to include seconds in the output, even if none were specified in time; add 256 to include milliseconds. If you do not specify a tfmt, the default is 24-hour format, with seconds and milliseconds only if they were given in the input time.

• New: This function does not exist in Take Command.



@TIMEPARTS — parses a time and indicates which parts were specified.

Syntax:
%@TIMEPARTS[time]

timethe time to examine

If the time is not a valid time, the return value is 0.

If the specified time is valid, then this function returns a bitmapped value:

16the time is in 12-hour (AM/PM) format
8the hour was specified
4the minute was specified
2seconds were specified
1fractional seconds were specified

A valid time will always have the 8 bit set, and either 16 or 4 or both. In other words, a time must include the hour; minutes are required in 24-hour format, but optional in 12-hour format; seconds and fractional seconds are always optional.



@TIMEPLUS — adds an offset to a time.

Syntax:
%@TIMEPLUS[time,offset,fmt,tfmt]
%@TIMEPLUS[date@time,offset,fmt,tfmt]

timethe starting time; defaults to the current time
date@timeyou can also give a time on a specific date
offsetthe amount of time to add; defaults to zero
fmtthe date format used to return the resulting date, and also to interpret ambiguous input dates; defaults to 256
tfmtthe format in which to return the resulting time; defaults to 128 (24-hour with seconds)

Specify the offset in hours, or as HH:MM or HH:MM:SS. If the offset begins with minus sign, it will be subtracted from the starting time.

You can specify a date-time pair for the starting time. The date may be in any format supported by this plugin. Separate the date from the time with an @ sign or the letter T.

• Note: This function does not consider possible changes to or from Daylight Saving Time.

• New: This function does not exist in Take Command.



@TIMETODEC — converts a time into a decimal fraction of a day.

Syntax:
%@TIMETODEC[time]

timethe time to convert

• New: This function does not exist in Take Command.

See also: @DECTOTIME, which performs the opposite function.



@USECONDS — converts a date and time to seconds past the Unix epoch.

Syntax:
%@USECONDS[date,time,infmt,flags]

datedefaults to today
timedefaults to now
infmtthe input date format, used to interpret ambiguous dates
flags1: input date and time are UTC, else local

This function returns the number of seconds past 1970-01-01 00:00:00 UTC.

See also: @UXTODATETIME and _USECONDS.

• New: This function does not exist in Take Command.



@USWEEK — returns a week number (1 to 53) for a given date. The date may be in any input date format supported by this plugin, and must be a valid date within the supported range.

Syntax:
%@USWEEK[date,infmt,dow]

datethe date to examine; defaults to today
infmtthe input date format, used to interpret ambiguous dates
dowthe first day of the week; defaults to Sunday

This function returns the week number for a given date, using a convention common in the United States. All weeks begin on Sunday (or as specified in dow) and end on Saturday (or the sixth day following dow). Week 1 is the week containing January 1, and ends on the first Saturday of the year. Up to six days at the end of a year may fall in week 1 of the following year.

See also: @ISOWEEK, which implements the ISO 8601 week-numbering standard.

• New: This function does not exist in Take Command.



@UTCDATETIME — converts a local date and time to UTC. The date may be in any input date format supported by this plugin, and must be a valid date within the supported range.

Syntax:
%@UTCDATETIME[date,time,fmt,tfmt]

datethe local date to convert; defaults to today’s date
timethe local time to convert; defaults to the current time
fmtthe date format used to return the resulting date, and also to interpret ambiguous input dates; defaults to 256
tfmtthe format in which to return the time; defaults to 384 (24-hour, with seconds and milliseconds)

The time may be entered in either 12-hour or 24-hour format. tfmt may be 0 to return the time in 24-hour format, or 1 - 12 for a variety of different 12-hour formats. Add 128 to include seconds in the output time; add 256 to include milliseconds.

See also: @LOCALDATETIME, which performs the reverse operation.

• New: This function does not exist in Take Command.



@UXTODATETIME — converts a Unix time stamp to a date and time.

Syntax:
%@UXTODATETIME[seconds,flags,fmt,tfmt]

secondsseconds past 1970-01-01 00:00:00 UTC
flags1: return date and time as UTC, else local
fmtthe date format used to return the date; defaults to 4 (ISO 8601 format)
tfmtthe time format used to return the time; defaults to 1152 (24-hour with seconds and leading zeros)

See also: @USECONDS and _USECONDS.

• New: This function does not exist in Take Command.



@YEAR — returns the year (1601 through 9999) for the specified date. The date may be in any input date format supported by this plugin, and must be a valid date within the supported range.

Syntax:
%@YEAR[date,infmt]

datethe date to examine; defaults to today’s date
infmtthe input date format, used to interpret ambiguous dates

• Incompatibility: In 4NT / Take Command v10 and earlier, the native @YEAR function will return a two-digit year if the input date uses a two-digit year. I don’t like this behavior, and choose not to replicate it. My @YEAR will always return four digits.



Internal Variables:


%_ISODOWI — returns the current day of the week as an integer, 1 = Monday through 7 = Sunday, per ISO 8601.

• Note: This internal variable does not exist in 4NT / Take Command v10 and earlier.



%_ISORDATE — returns today’s date in ISO 8601 yyyy-nnn ordinal-date format.

• Note: This internal variable does not exist in 4NT / Take Command v10 and earlier.



%_ISOWDATE — returns today’s date in ISO 8601 yyyy-Www-d week-day format.

• Note: This internal variable does not exist in 4NT / Take Command v10 and earlier.



%_ISOWEEK — returns the ISO 8601 week number (1 through 53) for today’s date.

• Note: This internal variable does not exist in 4NT / Take Command v10 and earlier.



%_ISOWYEAR — returns the ISO 8601 week-numbering year for the current week, i.e. the year in which the nearest Thursday falls.

• Note: This internal variable does not exist in 4NT / Take Command v10 and earlier.



%_T4 — returns the current local time as four digits, HHMM.

• New: This variable does not exist in Take Command.



%_TOMORROW — returns tomorrow’s date in ISO8601 format.

• New: This variable does not exist in Take Command.



%_USECONDS — returns the current time in Qeng Ho format.


There were programs here that had been written five thousand years ago, before Humankind ever left Earth…. Take the Traders’ method of timekeeping. The frame corrections were incredibly complex — and down at the very bottom of it was a litle program that ran a counter. Second by second, the Qeng Ho counted from the instant that a human had first set foot on Old Earth’s moon. But if you looked at it still more closely… the starting instant was actually about fifteen million seconds later, the 0-second of one of Humankind’s first computer operating systems….

— Vernor Vinge, A Deepness in the Sky

See also: @USECONDS and @UXTODATETIME.

• New: This variable does not exist in Take Command.



%_YESTERDAY — returns yesterday’s date in ISO8601 format.

• New: This variable does not exist in Take Command.



Commands:


ISO8601HELP — open this plugin’s help file.

Syntax:
ISO8601HELP /C /F /S /S:text /V topic

/Cselect the ‘Contents’ tab
/Fselect the ‘Favorites’ tab
/Sselect the ‘Search’ tab
/S:textselect the ‘Search’ tab and search for text
/Vshow detailed plugin version info
topicthe page to display

This ISO8601HELP command will locate and open this plugin’s help file. In most cases, the internal HELP command, and the F1 and Ctrl-F1 keys, will be more convenient. The main advantage to this command is that it can be used to open the help file to any desired topic, not only to the names of commands, functions, and variables.

Note that any /C /F or /S must precede the topic on the command line. (This command has a very simple-minded parser.)

• New: This command does not exist in Take Command.



LONGYEARS — enforce the use of four-digit years in local date formats 0-3, and optionally in date entry.

Syntax:
LONGYEARS OFF | ON | STRICT

This command affects the way years are returned or displayed in the local date formats, 0-3. When LONGYEARS is OFF, dates are returned with two-digit years. When it is ON, dates are shown with full four-digit years, making date formats 0 through 3 functionally the same as formats 256 through 259. STRICT works the same as ON, but also requires the use of four-digit years in input dates.

LONGYEARS defaults to OFF for compatibility with long-standing Take Command / 4NT behavior. Type LONGYEARS with no parameters to see the current setting.

• New: This command does not exist in Take Command.



QCAL — display a quick-and-dirty calendar.

Syntax:
QCAL [date | [month] [year]] /3 /6 /C:country /D /E /H /H:date,date… /I /L /N /P /W:dow /Y

/3display a three-month calendar
/6display a six-month calendar
/C:countryspecify a section in Holidays.ini; implies /H
/Ddisable color
/Edisplay English names for months and days of the week
/Hhighlight annual holidays
/H:datehighlight the specified holidays
/Idisplay ISO week numbers
/Llist holiday names; use in combination with /H or /C
/Ndon’t highlight today’s date
/Ppause after each screenful
/W:dowday of the week in the left column (1 = Monday, 2 = Tuesday, etc.; or MON … SUN)
/Ydisplay a one-year calendar

You may specify any one of: a full date, in any input date format supported by this plugin; a month (1 - 12, or JAN - DEC), and/or a four-digit year; or nothing, in which case QCAL will default to today’s date. If only a year is specified, then QCAL will display a calendar for the entire year; otherwise, it will show a one-month calendar by default. If a month is specified without a year, QCAL will assume the current year if the specified month is greater than or equal to the current month, or next year if the specified month is less than the current month.

If you want to specify a date using its MS-DOS day number, prefix a + or - sign; otherwise QCAL may misinterpret it as a month or a year.

If /I is specified, QCAL will automatically put Mondays on the left, unless directed otherwise with /W:dow. The week numbers shown are for the leftmost valid date in each row — this is tolerably obvious when Mondays are on the left, but less intuitive in other arrangements.

/H:date allows you to specify a list of dates to highlight. Dates may be entered in any supported format; separate them with commas or semicolons. You can use functions like @HOLIDAY or @EASTER to compute the dates. If /H is typed without any dates, QCAL will attempt to read a list of local annual holidays from Holidays.ini; failing that, a built-in list of common United States holidays will be used by default.

Note that /H and /H:date are basically two different options. The first reads a default set of annual holidays from a list; the second highlights specific dates listed on the command line. You can use either option alone, or combine them to highlight the default holidays and the dates specified on the command line.

QCAL’s output may be piped or redirected.

See also: List of default holidays.

• New: This command does not exist in Take Command.



Reference Information:


Output Date FormatsThe various formats in which dates can be returned
Input Date FormatsDifferent ways that dates may be entered in functions and commands
Supported Date RangeThe earliest and latest dates which this plugin can handle
Entering Day and Month NamesHow to enter day names, month names, and day-of-the-week lists
ISO 8601 Week NumberingA brief description
Default HolidaysA list of common United States holidays
Holidays.ini FormatCustomize the list of annual holidays
Time FormatsFormats in which times can be returned
Startup MessageYes, you can disable it if you wish
What’s Not SupportedThings you might reasonably expect to work
ChangesWhat’s new in this update
Status and LicensingOr you could read your mattress tag instead


Output Date Formats:


The @AGEDATE, @DATECONV, @DATEPLUS, @EASTER, @FILESTAMP, @HOLIDAY, @INLIEU, @MAKEDATE, @NEXTDATE, @NEXTDOW, and @PICKDATE functions can return dates in any of these formats:

fmtFormatExample
0local date formatvaries; 11/04/08 in the U.S.
1mm/dd/yy11/04/08
2dd/mm/yy04/11/08
3yy/mm/dd08/11/04
4ISO 86012008-11-04
5ISO 8601 week-day2008-W45-2
6ISO 8601 ordinal date2008-309
16MS-DOS day number+10535
17using English wordsTuesday, November 4, 2008
18T format (offset from today’s date)
19ANSI day numberA+148962
20ISO8601, packed20081104
21days since 1970-01-01U+14187
32Windows user locale “long date” formatvaries; mardi 4 novembre 2008 in France
256local date format, four-digit yearvaries; 11/04/2008 in the U.S.
257mm/dd/yyyy11/04/2008
258dd/mm/yyyy04/11/2008
259yyyy/mm/dd2008/11/04

Formats 0 through 3 return two-digit years, for compatibility with Take Command’s native behavior. Where compatibility is not an issue, I recommend using formats 256-259 instead. These formats are equivalent to 0-3, but return four-digit years. (A note in TakeCmd.h suggests that TCC supports similar formats internally; unfortunately, this capability doesn’t seem to be available to the user.)

The LONGYEARS command can be used to display four-digit years in formats 0-3, making them functionally identical to formats 256-259.

MS-DOS day numbers are based on January 1, 1980 as day 0; dates before 1980 will have negative MS-DOS day numbers. ANSI day numbers use January 1, 1601 as day 1.

Note that all of these output formats except for #17 and #32 are also valid input formats.

Input Date Formats:


This plugin’s internal functions and commands can accept dates in any of these formats:

infmtFormatExampleWould Be Interpreted As
0(according to system locale)01/02/03varies; January 2, 2003 in the U.S.
  04/05varies;
1mm/dd/yy or mm/dd/yyyy01/02/03January 2, 2003
 mm/dd04/05
2dd/mm/yy or dd/mm/yyyy01/02/03February 1, 2003
 dd/mm04/05
3 or 4yy/mm/dd or yyyy/mm/dd01/02/03February 3, 2001
 mm/dd04/05
-ISO 8601 format1941-12-07December 7, 1941
-ISO 8601 week-day format1969-W29-7July 20, 1969
-ISO 8601 ordinal format1863-323November 19, 1863
-ISO 8601, packed19120623June 23, 1912
-days since 1970-01-01U+2701May 25, 1977
-MS-DOS day number+3333February 15, 1989
-T format (offset from today’s date)T+21
-ANSI day numberA+78169January 8, 1815

For compatibility with long-standing 4DOS/4NT/Take Command behavior, dates may be entered in local formats using two-digit years. Years 80 to 99 are interpreted as 1980 through 1999; 00 to 79 are interpreted as 2000 through 2079. Although two-digit years are legal and documented, I strongly recommend passing only four-digit years to avoid confusion. If you omit the year, the plugin will assume the current year.

You can use the LONGYEARS command to require four-digit years in input dates. When LONGYEARS is set to STRICT, dates entered using two-digit years (e.g. 08/12/81) or without a year (e.g. 05/23) are illegal and will raise an error.

Dates entered as mm/dd/yy, mm/dd/yyyy, dd/mm/yy, dd/mm/yyyy, yy/mm/dd, mm/dd, or dd/mm are all ambiguous: the parser cannot know for certain which format was intended. You can use an infmt parameter to tell the parser how to interpret them. If no infmt is present, they will be interpreted according to your system’s locale settings.

Dates in any of the ISO formats must be specified using four-digit years. Two-digit years in ISO date formats will raise an error. The ISO date formats are unambiguous; the parser can automatically determine the intended format, and any infmt parameter will be ignored.

The local date formats (0-3) will accept the slash, minus sign, or period as a date separator. The ISO date formats require a minus sign. MS-DOS day numbers may be positive or negative (or zero); they may have a leading plus or minus sign. T-format dates may also be positive or negative; they may start with either T+ or T-. A lone T with no offset is also valid, and refers to today’s date. You may also spell out TODAY in full, e.g. TODAY-1 for yesterday’s date.

MS-DOS day numbers are based on January 1, 1980 as day 0; dates before 1980 will have negative MS-DOS day numbers. ANSI day numbers use January 1, 1601 as day 1.

Supported Date Range:

Dates passed to any internal function or command in this plugin must be in the range of January 1, 1601 through December 31, 9999. Any date outside this range will cause an error. Invalid dates such as April 31, or February 29 of a common year, will also be detected and raise an error.

 MinimumMaximum
ISO 86011601-01-019999-12-31
   week-day1601-W01-19999-W52-7
   ordinal1601-0019999-366
MS-DOS day number-138426+2929244
ANSI day numberA+1A+3067671

Be aware that this plugin uses the Gregorian calendar only. I have made no allowance for earlier or different calendars. Many countries converted from the older Julian calendar at some point within this range, so this plugin may return info that disagrees with actual historical calendars. For instance, dates prior to September of 1752 in the English-speaking world will almost certainly be “wrong”.

Entering Days of the Week, Months, and Day-of-the-Week Lists:

Some of the functions in this plugin take days of the week or months as arguments. Where you see a dow parameter, you should supply a day of the week. Day names may be abbreviated to the first three letters of their English names: MON, TUE, and so on. If Windows is set up for a non-English locale, you can also use the local abbreviated day names as reported by the @IDOW function. Localized day names must match all characters returned by @IDOW, including any accents or other diacriticals. Finally, you may use numbers: 1 for Monday, 2 for Tuesday, and so on. (Sunday may be specified as either 0 or 7.)

A month parameter may be entered as an English month name (only the first three letters are significant): JAN, FEB, MAR, and so on. In a non-English locale, you may instead use local abbreviated month names as reported by @MONTHNAME[n,3]. Localized month names must match all characters, including any accents or diacriticals. You can also use numbers: 1 for January, 2 for February, and so on.

A few of the functions in this plugin accept lists of days of the week. Wherever you see a dowmask parameter, you can enter:

•   One or more days of the week, separated with spaces or semicolons: MON WED FRI for Mondays, Wednesdays, and Fridays
•   a range, two days separated by a dash: TUE-FRI for Tuesdays, Wednesdays, Thursdays, and Fridays
•   the word WEEKDAYS (equivalent to MON-FRI) or WEEKENDS (equivalent to SAT-SUN)

If you type an exclamation point before the list, the meaning is inverted: !TUE THU means all days except for Tuesdays and Thursdays. You can use local day names or digits in a dowmask if you wish.

ISO 8601 Week Numbering:

Several of the functions in this plugin make use of ISO 8601 week numbers. This system is unfamiliar to many people; here’s a brief summary of how it works.

In the ISO 8601 standard, a “week” is defined as a seven-day period, always beginning on a Monday and always ending on a Sunday. (This differs from the traditional week running from Sunday through Saturday.) The fourth and central day of any ISO week is therefore a Thursday.

Because New Year’s Day does not always fall on a Monday, it’s possible for the year to change in mid-week. In other words, an ISO week can begin in one year and end in another. ISO 8601 defines a week as belonging to the year in which its Thursday falls. Think of Thursday as the “anchor” of the ISO week: the entire week is tied to the year where Thursday drops anchor.

ISO weeks are numbered starting with 1 (not zero.) Week 1 of a year is the week containing the first Thursday of the year. Week 2 is the week containing the second Thursday of the year, week 3 contains the third Thursday, and so on. The last ISO week of a year is numbered 52 or 53, since some years contain 52 Thursdays and others have 53.

As many as three days at the start of January may belong to the final week of the previous year; as many as three days at the end of December may belong to the first week of the following year. For ISO week-numbering purposes, any date falls in the same week as the nearest Thursday.

For example, consider Friday, December 31, 2010. The closest Thursday is December 30; so December 31 falls in the last ISO week of 2010. If we look at Sunday, January 2, 2011, we see that the nearest Thursday is still December 30, 2010; so January 2, 2011 is also in the final week of 2010. But for Monday, January 3, 2011, the closest Thursday is January 6 — the first Thursday of the new year — so January 3, 2011 falls in the first ISO week of 2011.

YearWeekMonTueWedThuFriSatSun
201050Dec 13Dec 14Dec 15Dec 16Dec 17Dec 18Dec 19
201051Dec 20Dec 21Dec 22Dec 23Dec 24Dec 25Dec 26
201052Dec 27Dec 28Dec 29Dec 30Dec 31Jan 1Jan 2
201101Jan 3Jan 4Jan 5Jan 6Jan 7Jan 8Jan 9
201102Jan 10Jan 11Jan 12Jan 13Jan 14Jan 15Jan 16

You can use QCAL /I to display ISO 8601 week numbers.

Default Holidays:


— Common United States Holidays —
New Year’s DayMartin Luther King, Jr. DayWashington’s Birthday
Easter (western)Mother’s DayMemorial Day
Father’s DayJuneteenthIndependence Day
Labor DayColumbus DayHalloween
Election DayVeterans DayThanksgiving
ChristmasNew Year’s Eve 

Future holidays are calculated as currently defined, e.g. by the 1968 Uniform Monday Holiday Act. Congress may change them in the future. I have made some fairly arbitrary decisions on how to handle holidays in past years, for instance showing FDR’s week-early Thanksgivings for 1939 - 1941 rather than the traditional date. Actual historical and local observances may have differed; user beware.

Holidays.ini Format:

The QCAL /H command and the @PICKDATE function highlight holidays in a different color, and @ISHOLIDAY tests whether a specific date matches a holiday. But what holidays does the plugin recognize? A list of common United States holidays is supplied by default, but it may be desirable to change or replace this list. You can define custom holidays by creating a text file named Holidays.ini in the same directory where ISO8601.DLL resides.

Holidays.ini will have one or more sections, each defining annual holidays for a different country. Each section is identified by a header line consisting of the English name of the country between square brackets, e.g. [Latvia] or [United Kingdom]. The plugin will use the appropriate section for your locale.

Each holiday is defined on a separate line within the appropriate section. Use an asterisk as a placeholder for the year. When the calendar is displayed, asterisks will be replaced with the year. Enter fixed dates in ISO 8601 format (with an asterisk in place of the year): *-07-04 for the Fourth of July, *-05-05 for Cinco de Mayo, *-11-05 for Guy Fawkes Night. You can also use variable functions: %@holiday[2,1,6,*] for the second Monday in June, or %@easter[*,,,-2] for Good Friday. Do not omit the percent sign — it is required for variable expansion!

Occasionally it is useful to restrict the years in which a holiday is observed. You can define a year restriction at the start of the line; it must be typed in parentheses, before the holiday definition. Two types of year restrictions are supported: ranges and periods. A year range sets a minimum or maximum year, or both; a periodic holiday occurs once every so many years. Enter a year range as (start-end), e.g. (1868-1970) to limit a holiday to the years 1868 through 1970. You may omit either the start or the -end; don’t type the minus sign unless you specify an end.

An annual period is entered as (?period=remainder). This defines a holiday observed only when the year divided by the period leaves remainder. For example, (?2=0) restricts a holiday to even-numbered years, and (?2=1) to odd-numbered years. Where remainder is zero, you may omit the =0; (?4) means “in years evenly divisible by four.”

You can combine both types within one set of parentheses: (1910-1935?2=1) would select odd-numbered years between 1910 and 1935. As a practical example, since 1848 United States federal elections have been held the day after the first Monday of November in even-numbered years. We could define this date in Holidays.ini using:

[United States]

(1848?2) %@holiday[1,1,11,*,,1]   ; Election Day

In Mexico, a new Presidente has taken office on the first of December every sixth year since 1934. (1934 divided by 6 leaves 2.)

[Mexico]

(1934?6=2) *-12-01   ; Transmisión del Poder Ejecutivo Federal

Note that the semicolon introduces a comment: the name of the holiday, displayed by QCAL /L.

Time Formats:

A few of the functions in this plugin can return times in different formats. The tfmt parameter controls how times are returned. The lower four bits of tfmt select between 24-hour time or a variety of different 12-hour formats. If the lower four bits are all zero, then the time is returned in 24-hour format; if any is set, 12-hour format is used:

tfmt  tfmt 
05:23 75:23A.M.
15:23 AM 85:23a.m.
25:23 am 95:23 A
35:23 A.M. 105:23 a
45:23 a.m. 115:23A
55:23AM 125:23a
65:23am   

You can also add the following values to tfmt:

valuemeaning
128include seconds
256include milliseconds
512use local time and decimal separators, not hardcoded : and .
1024use leading zero in hours
2048left-pad one-digit hours with a space
4096omit time and decimal separators; use leading zero in hours
5120omit time separators; use leading zero in hours

There is also a special value 15, which reports a time as a decimal fraction of a day:

tfmt 
15.22430556

Startup Message:

This plugin displays an informational line when it initializes. The message will be suppressed in transient or pipe shells. You can disable it for all shells by defining an environment variable named NOLOADMSG, for example:

set /e /u noloadmsg=1

What Is Not Supported:

The new date formats are not supported in date ranges in file-handling commands. You can use @DATECONV[newdate,4] within a date range to convert the new date formats into something TCC understands.

The internal @FILEDATE function has not been replaced, as I have no foolproof way to get date stamp info for FTP files. If needed, you can massage @FILEDATE’s output with @DATECONV.

Changes:


VersionDateChanges
1.7.4.22024-10-02Changed http:// to https:// in the PLUGININFO block.
1.7.42024-04-18Fixed some issues with QCAL’s highlighting of holidays.
1.7.3.32024-04-03NewHelp.cpp v1.0.8.14, mmfiles.cpp v1.4.4.5, codepages.cpp v2.1.0.3. Simplified the ‘Quick Links’ box in the .HTML file; all of the reference info has been collapsed into a single section, the same as in the .CHM file.
1.7.3.22023-10-15Tweaked ShowPluginVersion()’s output format slightly.
1.7.3.12023-10-12Updated the plugin’s web address.
1.7.32023-07-31Updated to the current versions of mmfiles.cpp, codepages.cpp, and NewHelp.cpp. Documented the newer options to ISO8601HELP.
1.7.2.22023-07-21Updated to current versions of ParseArgs.cpp and NewHelp.cpp.
1.7.2.12023-06-13Updated help system to avoid an issue in TCC 30.00.20.
1.7.22023-02-13Updated @FILESTAMP to support internet files.
1.7.1.12021-08-12Tweaked the version info structure; no changes to the code.
1.7.12021-07-06Added @JULIAN.
1.7.02021-07-04Changed the .DLL names; now ISO8601.dll is the 64-bit build. Adds @CENTURY, @USECONDS, @UXTODATETIME, and _USECONDS. Added /6 /L and /N to QCAL. Changed the default output format in @TIMEFMT, @LOCALDATETIME, and @UTCDATETIME. Added an option to prevent the user from selecting holidays in @PICKDATE. Added a flags arg to @INLIEU. Fixed an issue with @PICKDATE not freeing holiday definitions. Added Juneteenth to holidays. Sundry bug fixes. Much cleanup of the code and documentation.
1.6.52019-09-19Bodged around an issue with QCAL’s colors bleeding in the Windows 10 console.
1.6.42017-12-06Updates to the help system; fixed a cosmetic issue with ISO8601HELP /?
1.6.32017-11-13Removed dependency on Evaluate() for compatibility with TCC-RT.
1.6.22017-11-10Bug fix: QCAL /H delayed variable expansion clobbering settings.
1.6.12017-02-02Minor tweak for TCC v21 compatibility.
1.6.02016-08-16Add convenience variables _TOMORROW and _YESTERDAY.
1.5.42016-03-09Reworks the help system, for systems where the documented HtmlHelp() API is broken.
1.5.32015-04-28Added _T4, for no better reason than that this was a convenient place to stick it.
1.5.22014-11-03Bug fix: CallInternal() calling Command() with nonzero nReserved parameter.
1.5.12014-10-31Bug fix: CallInternal() adding an asterisk when it shouldn’t. Documented TODAY synonym for T.
1.5.02014-10-29Changes for TCC v17 compatibility.
1.4.12014-05-21Fixed the default time format in @AGEDATE to match TCC’s.
1.4.02014-04-25Rewrote the holiday handling code. Tweaks to the help system. Automatically unload QCAL when loading ISO8601 (and vice versa).
1.3.102013-10-14Added Chile to Holidays.ini, thanks to Miguel Farah. Added two new modes to @INLIEU to support Chilean holidays.
1.3.92013-10-04Added Poland and Hungary to Holidays.ini; thanks to jbanaszczyk and Steve Fabian respectively. Tweaked the code to allow for UTF-16 Holidays.ini.
1.3.82013-04-11Updated the plugin’s web address
1.3.72012-08-21Minor changes to make HTML Validator (dead link) happy
1.3.62012-06-15Adds @ISTIME and @TIMEPARTS
1.3.52012-06-13Puts @DATECONV back the way it was, for compatibility with TCC
1.3.42012-06-13@DATECONV outputs four-digit years by default
1.3.32012-06-12New option to @AGEDATE and @FILESTAMP to return date/time pairs separated by a T, per ISO 8601; made the offset optional in @TIMEPLUS
1.3.22012-06-08Allow T as a date/time separator in @TIMEDIFF and @TIMEPLUS.
1.3.12012-06-06Tweaks to the display of time format 15 when combined with a day offset; disabled 12-hour output time formats in @TIMEDIFF; documented the expanded date range
1.3.02012-06-06Added @DECTOTIME, @TIMEDIFF, @TIMEPLUS, @TIMETODEC, time format 15; extended the valid date range to the year 9999
1.2.42012-03-05Converted to VS 2010; disallow negative values for @ORD; close help on shutdown.
1.2.32011-06-29Bug fix: @LOCALDATETIME, @TIMEFMT, and @UTCDATETIME were dividing args at unquoted spaces.
1.2.22011-04-25Bug fix: @MAKEAGE wasn’t initializing variable before calling the reworked time parser.
1.2.12011-04-15Added time-format bit 12 (Dave Cantor suggestion)
1.2.02011-04-14Per a suggestion by Steve Fabian, reworked the time parser to accept 12-hour or 24-hour input. Added @TIMEFMT, @LOCALDATETIME and @UTCDATETIME functions. Tweaked @AGEDATE to output different time formats.
1.1.52011-03-28Don’t call HtmlHelp() to close the help file on shutdown; this is insanely slow for some reason.
1.1.42011-03-03Further tweaks to the help system
1.1.32011-02-26Further tweaks to the help system
1.1.22011-02-09Added ISO8601HELP command, date format 21; tweaked online help to be sorta-kinda “single instance”
1.1.12010-12-27Tweaked @ORD function to allow an expression instead of just a number
1.1.02010-07-30Added date format 20, YYYYMMDD
1.0.02010-06-17First release

Status and Licensing:

This plugin is © Copyright 2024, Charles Dye. Unaltered copies of the binary and documentation files may be freely distributed without restriction. I make no guarantee and give no warranty for its operation. Be aware that this plugin definitely does alter the behavior of internal functions; use it at your own risk.

If you find a problem, you can report it in the JP Software support forum.

Download:

You can download the current version of the plugin from https://charlesdye.net/dl/iso8601.zip.