home *** CD-ROM | disk | FTP | other *** search
/ Bila Vrana / BILA_VRANA.iso / 005A / FDATE91C.ZIP / FDATE.DOC < prev    next >
Text File  |  1995-10-22  |  141KB  |  3,563 lines

  1. FDATE                     Version 9.1c               1995 Oct 22
  2. ======================================================================
  3. AUTHOR:     Stephen Ferg             
  4.             608 N. Harrison Street
  5.             Arlington, VA 22203-1416
  6.             USA
  7.  
  8.             telephone (voice, not FAX): (703) 525-2241
  9.             CompuServe ID             : 73377,1157
  10.             Internet                  : 73377.1157@compuserve.com
  11.  
  12. =======================================================================
  13.  
  14. WHAT TO DO IF THIS DOCUMENTATION SEEMS TOO OVERWHELMING
  15. ========================================================
  16.  
  17. As Fdate has grown in functionality over the years, its documentation has
  18. also grown.  Lately I've been getting feedback from people who encounter
  19. Fdate for the first time, telling me that Fdate's documentation is so
  20. massive that it is overwhelming: they have no idea where to start, or how
  21. to use the documentation to help them figure out how to make Fdate do what
  22. they need to do.
  23.  
  24. If that is the situation you're in right now, take heart!  There is hope!
  25.  
  26. To help you get started using Fdate, I've created a much shorter file
  27. called FDATEBEG.DOC (FDATE beginners documentation), which shows how to use
  28. Fdate to do the things most users want to do.
  29.  
  30. So if you're trying to use Fdate for the first time, and feeling
  31. overwhelmed (or even if you're not feeling overwhelmed), I suggest that you
  32. read FDATEBEG.DOC.
  33.  
  34.                              Table of Contents
  35.  
  36. Page numbers in the WordPerfect version of FDATE.DOC (which is not
  37. distributed with FDATE) are lost in the conversion to ASCII format. 
  38. Nevertheless, these page numbers give you a rough idea of the relative
  39. locations of the different sections.
  40.  
  41.   WHAT TO DO IF THIS DOCUMENTATION SEEMS TOO OVERWHELMING . . . . . . .   1
  42.   WHAT IS FDATE?. . . . . . . . . . . . . . . . . . . . . . . . . . . .   5
  43.      OTHER UTILITIES NAMED "FDATE". . . . . . . . . . . . . . . . . . .   6
  44.      OVERVIEW OF PARAMETERS . . . . . . . . . . . . . . . . . . . . . .   7
  45.      OVERVIEW OF FUNCTIONS. . . . . . . . . . . . . . . . . . . . . . .   9
  46.   FUNCTIONS: DETAILED DESCRIPTIONS. . . . . . . . . . . . . . . . . . .  11
  47.      DATE FORMATTING FUNCTIONS. . . . . . . . . . . . . . . . . . . . .  11
  48.      DATE ARITHMETIC FUNCTIONS. . . . . . . . . . . . . . . . . . . . .  12
  49.      MONTH DATE ARITHMETIC FUNCTIONS. . . . . . . . . . . . . . . . . .  13
  50.      WEEKDAY DATE ARITHMETIC FUNCTIONS. . . . . . . . . . . . . . . . .  14
  51.      DATE/TIME COMPARISON FUNCTIONS . . . . . . . . . . . . . . . . . .  15
  52.      COMPARE-FUNCTION ERRORLEVELS . . . . . . . . . . . . . . . . . . .  15
  53.      NUMERIC ARITHMETIC FUNCTIONS . . . . . . . . . . . . . . . . . . .  16
  54.      DATE VALIDATION FUNCTION . . . . . . . . . . . . . . . . . . . . .  18
  55.   STRING FUNCTIONS. . . . . . . . . . . . . . . . . . . . . . . . . . .  19
  56.      GET and GETU (GET USER INPUT) FUNCTION . . . . . . . . . . . . . .  19
  57.      GETK (GET KEYPRESS) FUNCTION . . . . . . . . . . . . . . . . . . .  20
  58.        Specifying the Keymask . . . . . . . . . . . . . . . . . . . . .  20
  59.        GetK Results also in ERRORLEVEL. . . . . . . . . . . . . . . . .  21
  60.        Modifying the Keymask. . . . . . . . . . . . . . . . . . . . . .  22
  61.        Displaying a User Prompt With GETK . . . . . . . . . . . . . . .  22
  62.      SUBSTR (SUBSTRING) FUNCTION. . . . . . . . . . . . . . . . . . . .  23
  63.      LEN (LENGTH) FUNCTION. . . . . . . . . . . . . . . . . . . . . . .  25
  64.      UPPER FUNCTION . . . . . . . . . . . . . . . . . . . . . . . . . .  25
  65.      ECHO FUNCTION. . . . . . . . . . . . . . . . . . . . . . . . . . .  25
  66.      /J: JUSTIFYING OUTPUT. . . . . . . . . . . . . . . . . . . . . . .  26
  67.   DATE FORMATS. . . . . . . . . . . . . . . . . . . . . . . . . . . . .  28
  68.      SYMBOL CONVENTIONS . . . . . . . . . . . . . . . . . . . . . . . .  28
  69.      PSEUDODATES. . . . . . . . . . . . . . . . . . . . . . . . . . . .  29
  70.   INPUT DATE FORMATS. . . . . . . . . . . . . . . . . . . . . . . . . .  30
  71.      CALENDAR DATE INPUT FORMATS. . . . . . . . . . . . . . . . . . . .  30
  72.      BUSINESS JULIAN DATE INPUT FORMATS . . . . . . . . . . . . . . . .  31
  73.      GETTING DATE/TIME A FILE WAS CREATED . . . . . . . . . . . . . . .  32
  74.   OUTPUT DATE FORMATS . . . . . . . . . . . . . . . . . . . . . . . . .  33
  75.      DAY-OF-WEEK AND MONTH OUTPUT FORMATS . . . . . . . . . . . . . . .  35
  76.      MISCELLANEOUS OUTPUT FORMATS . . . . . . . . . . . . . . . . . . .  35
  77.      LEAP-YEAR FLAG OUTPUT FORMAT . . . . . . . . . . . . . . . . . . .  36
  78.      TIME OUTPUT FORMATS. . . . . . . . . . . . . . . . . . . . . . . .  36
  79.      BUSINESS JULIAN DATE OUTPUT FORMATS. . . . . . . . . . . . . . . .  37
  80.      ABSOLUTE DATE/TIME OUTPUT FORMATS. . . . . . . . . . . . . . . . .  38
  81.      /T: TIME OVERRIDE PARAMETER. . . . . . . . . . . . . . . . . . . .  39
  82.      /J: JUSTIFYING OUTPUT. . . . . . . . . . . . . . . . . . . . . . .  39
  83.   HOW TO PUT FDATE OUTPUT INTO AN ENVIRONMENT VARIABLE. . . . . . . . .  40
  84.      CALL A BATCH FILE. . . . . . . . . . . . . . . . . . . . . . . . .  40
  85.      USE AN ENVIRONMENT-MANIPULATION UTILITY. . . . . . . . . . . . . .  40
  86.      FDATE'S /V PARAMETER . . . . . . . . . . . . . . . . . . . . . . .  41
  87.      /V WHEN RUNNING UNDER MICROSOFT WINDOWS. . . . . . . . . . . . . .  42
  88.        Turbo Professional: "Highly Recommended" . . . . . . . . . . . .  43
  89.      /V WHEN USING 4DOS, NDOS, AND UMB. . . . . . . . . . . . . . . . .  44
  90.   FDATE'S ERROR HANDLING. . . . . . . . . . . . . . . . . . . . . . . .  45
  91.   EXAMPLES OF HOW TO USE FDATE. . . . . . . . . . . . . . . . . . . . .  46
  92.      :01 Display Fdate output on screen . . . . . . . . . . . . . . . .  46
  93.      :02 Redirect FDATE output to a file. . . . . . . . . . . . . . . .  46
  94.      :03 Put FDATE output in an environment variable using a batch file  46
  95.      :04 Put FDATE output in an environment variable using /V parm. . .  46
  96.      :05 Put FDATE output in an environment variable using STRINGS. . .  46
  97.      :06 Put FDATE output in an environment variable using GET. . . . .  46
  98.      :07 Get user input . . . . . . . . . . . . . . . . . . . . . . . .  47
  99.      :08 Get a user menu selection. . . . . . . . . . . . . . . . . . .  48
  100.      :10 Change a date from one format into another . . . . . . . . . .  49
  101.      :11 Find the difference in days between two dates. . . . . . . . .  49
  102.      :12 Find the elapsed days/hours/minutes between two date/times . .  50
  103.      :13 Find the elapsed years/months/days between two dates.. . . . .  53
  104.      :14 Determine how long it took a program to run. . . . . . . . . .  56
  105.      :15 Find years when a given date fell on a given day of the week .  57
  106.      :16 Find calendar date corresponding to a "business Julian" date .  59
  107.      :17 Set your PC's date to a business julian date . . . . . . . . .  60
  108.      :18 Determine if parm %1 contains a valid date . . . . . . . . . .  62
  109.      :19 "Roll your own" date format  . . . . . . . . . . . . . . . . .  62
  110.      :20 Find the 4th Thursday in November (Thanksgiving) . . . . . . .  63
  111.      :22 On a date, show what anniversary it is for some event. . . . .  63
  112.      :23 Show a list of holidays in a given year. . . . . . . . . . . .  63
  113.      :24 Show a list of Federal holidays in a given year. . . . . . . .  63
  114.      :25 Determine if a year is valid, and evenly divisible by 4. . . .  64
  115.      :30 Compare a file's date to today's date. . . . . . . . . . . . .  64
  116.      :31 Compare two files' date/time . . . . . . . . . . . . . . . . .  65
  117.      :32 Display a list of all files that were created/updated today. .  66
  118.      :33 Delete files more than X days old (use a batch-file subroutine) 67
  119.      :34 Get date to tell PKZIP to compress files older than 30 days. .  72
  120.      :40 Loop through an array of environment variables . . . . . . . .  73
  121.      :44 Do something on the last day (or last Friday) of the month . .  74
  122.      :45 Get information about the month prior to the current month . .  75
  123.      :50 Represent a date in 3 bytes of "extended hex" notation . . . .  76
  124.      :51 Represent a date in a short (4-byte) format (technique #1) . .  76
  125.      :52 Represent a date in a short (4-byte) format (technique #2) . .  77
  126.      :53 Convert numbers to "extended hex" (XX) format. . . . . . . . .  77
  127.      :54 Customize Fdate for a language of your choice. . . . . . . . .  78
  128.      :55 Fergian.BAT (used in the previous example) . . . . . . . . . .  79
  129.      :61 DO-ONCE: Run apps when booting for the first time of the day .  81
  130.      :62 Run specific software, depending on the day of the week. . . .  82
  131.      :63 Run a program at a specified time later in the day . . . . . .  82
  132.      :66 Change a filename to contain today's date. . . . . . . . . . .  84
  133.      :67 Change a file's name to a name that contains today's date. . .  84
  134.      :68 Change a file's name to a name containing an absolute minute .  84
  135.      :71 Extract the rightmost n characters of a string . . . . . . . .  84
  136.      :72 Left-pad a number with zeroes. . . . . . . . . . . . . . . . .  84
  137.   HOW FDATE THINKS ABOUT DATES. . . . . . . . . . . . . . . . . . . . .  85
  138.      FDATE'S BUSINESS VIEW OF THE CALENDAR. . . . . . . . . . . . . . .  85
  139.      FDATE'S BASE DATE. . . . . . . . . . . . . . . . . . . . . . . . .  85
  140.      FDATE'S LEAP YEAR ALGORITHM. . . . . . . . . . . . . . . . . . . .  86
  141.      FDATE'S CENTURY-ASSUMPTION ALGORITHM . . . . . . . . . . . . . . .  87
  142.      FDATE'S IMPLEMENTATION LIMITS. . . . . . . . . . . . . . . . . . .  87
  143.   DISTRIBUTION ISSUES . . . . . . . . . . . . . . . . . . . . . . . . .  88
  144.      USE, REGISTRATION, AND DISTRIBUTION OF FDATE . . . . . . . . . . .  88
  145.      TECHNICAL SUPPORT FOR FDATE. . . . . . . . . . . . . . . . . . . .  89
  146.      WHERE TO FIND THE MOST CURRENT VERSION OF FDATE. . . . . . . . . .  89
  147.      UPLOADING FDATE TO ELECTRONIC BULLETIN BOARDS. . . . . . . . . . .  89
  148.      CONTENTS OF THE FDATE.ZIP DISTRIBUTION FILE. . . . . . . . . . . .  89
  149.      RECENT FDATE REVISION HISTORY. . . . . . . . . . . . . . . . . . .  90
  150.  
  151. WHAT IS FDATE?
  152. ==============
  153. Fdate is a utility for doing date formatting and date arithmetic in DOS
  154. batch files.  There are a number of different ways to put FDATE's output
  155. into environment variables.  Once this has been done, the environment
  156. variables can be used and manipulated in many ways in the batch file.
  157.  
  158. FDATE is freeware, or what is technically known as "zero-cost shareware". 
  159. There is no requirement to register FDATE in any way.  For more details,
  160. see the DISTRIBUTION ISSUES section.
  161.  
  162. Here are some of the things you can do with FDATE.
  163.  
  164.     accept user input from the keyboard
  165.  
  166.     retrieve today's date in a variety of formats
  167.       place today's date into a file name
  168.  
  169.     reformat dates 
  170.        Output formats include common American and European formats, or you
  171.        can "roll your own" by manipulating environment variables.  Month
  172.        and weekday names can be produced in several languages (English,
  173.        French, German, Spanish).
  174.  
  175.     calculate when certain holidays occur in a given year
  176.  
  177.     do date arithmetic
  178.       determine the date N days before/after a given date
  179.       compare two dates to determine which is earlier
  180.       compare two dates to determine how many days apart they are
  181.  
  182.     determine if a year is a leap year
  183.     determine whether a year is evenly divisible by some number
  184.  
  185.     determine what day of the week a date falls on
  186.       run certain software only on certain days of the week
  187.  
  188.     retrieve the date/time from the date/timestamp of a file
  189.     do simple integer arithmetic (add, subtract, modulus)
  190.     calculate the time a piece of software takes to run
  191.     convert a calendar date to/from a "business julian" date
  192.  
  193.     extract a substring from an environment variable
  194.     right, left, or center justify a string
  195.  
  196.  
  197. OTHER UTILITIES NAMED "FDATE"
  198. =============================
  199.  
  200. There is another shareware utility named FDATE in circulation.  It is an
  201. implementation of the UNIX "touch" utility, and is used to change the
  202. date/time stamp of a file.  
  203.  
  204. Both FDATEs have been in circulation for too long to make it practical to
  205. change the name of either one.  All that can be done is to warn you of a
  206. potentially confusing situation.
  207.  
  208. OVERVIEW OF PARAMETERS
  209. ======================
  210.  
  211. FDATE accepts the following parameters:
  212.  
  213.        /F /A /B /I /O /P /S /N /D /L /V /T /Q /J /K
  214.  
  215. If the /F parameter is not present, FDATE displays a help screen.  
  216.      If you get FDATE's help screen when you don't expect it, you probably
  217.      forgot to specify the /F parameter or mistyped it.
  218.  
  219. Parameters can be in any order and upper or lower case.
  220.      Note that although function and format parms are not case sensitive,
  221.      they are "text sensitive".  If any characters are missing, added, or
  222.      mistyped, the parameter will be rejected.
  223.  
  224. What parameters are required (other than /F) depends on the function
  225. requested with the /F parameter.  Unnecessary parameters are simply
  226. ignored.
  227.  
  228.  
  229.  
  230. HERE IS A BRIEF SUMMARY OF WHAT EACH OF THE PARAMETERS MEANS
  231. ------------------------------------------------------------
  232.  
  233. /F   requests a particular FDATE function.  This is Fdate's most important
  234.      parameter.  See the OVERVIEW OF FUNCTIONS section, and the detailed
  235.      description of each Fdate function.
  236.  
  237. /A   For date functions, these two parameters are used to specify dates. 
  238. /B   For the ordinary arithmetic functions, these parameters are used to
  239.      specify numbers.  For date functions, if either of these parameters is
  240.      omitted, it defaults to today's date.
  241.  
  242. /D   day-of-week number (used only with W function)
  243.  
  244. /I   specifies format of input date(s)
  245.      If the /I parameter is omitted, /Imm-dd-ccyy is assumed.
  246.  
  247. /J   specifies justification, length, and pad character
  248.      If the /J parameter is omitted, no justification formatting is done.
  249.  
  250. /K   The GETK function takes a /K "keymask" parameter that tells it which
  251.      keys to accept.
  252.  
  253. /L  specifies language of output.
  254.      /Lus   US (American) English-language output
  255.      /Lfr   French-language output
  256.      /Lgr   German-language output
  257.      /Lsp   Spanish-language output
  258.      If the /L parameter is omitted, /Lus [American English] is assumed.
  259.  
  260. /N   number of days (always a number)
  261.  
  262. /O   specifies format of output date
  263.      If the /O parameter is omitted, /Od1 is assumed.
  264.  
  265. /Q   specifies a prompt string for a GET, GETU, or GETK function, or the
  266.      input string for a string-handling function (SUBSTR, LEN, UPPER).
  267.  
  268. /P   specifies a prefix string for the output
  269. /S   specifies a suffix string for the output
  270.      These optional parameters may always be specified or omitted.
  271.      They must be enclosed in single quotes, double quotes, or
  272.                   square brackets
  273.  
  274.      Note that "whitespace" will be removed from these strings, so
  275.      formatting of /P and /S strings cannot be controlled using spaces.  To
  276.      format strings, use periods or ASCII 255 (hex'ff') as filler.
  277.  
  278.        EXAMPLES
  279.           FDATE /Ff                /P"Today is "
  280.           FDATE /Fdif /B12-25-TTTT /P"It is " /S" days until Christmas"
  281.  
  282. /T   For date functions, /T overrides the time portion of the date on the
  283.      /A parm. (Note that it does NOT override the time portion of the date
  284.      on the /B parm.)  
  285.  
  286. /V   specifies that output is to be placed in an environment variable
  287.      rather than written to standard output.
  288.      If /V is specified but not followed by the name of an environment
  289.      variable, then /Vfdate is assumed, and output is placed in the FDATE
  290.      environment variable.
  291.  
  292. OVERVIEW OF FUNCTIONS
  293. =====================
  294.  
  295. Fdate's most important parameter is the function parameter, /F.  Here is a
  296. brief summary of the functions that may be specified on the /F parm, for
  297. example: /Fadd.  Detailed descriptions of each of the functions can be
  298. found on the next few pages.
  299.  
  300. If the /F parameter is omitted, it defaults to the null string, which
  301. causes Fdate to display its HELP screens.
  302.  
  303. f         Format the date in the /A parm into format specified in /O parm
  304.  
  305. add       Add the number of days in the /N parm to the date in the /A parm
  306.  
  307. sub       Subtract the number of days in the /N parm from the date in the
  308.           /A parm
  309.  
  310. dif       Return the number of days between dates in the /A and /B parms
  311.  
  312. w         Do date arithmetic in terms of weeks rather than days.  Using the
  313.           date in the /A parm, a number specified in the /N parm, and a
  314.           day-of-the-week number specified in the /D parm, return the date
  315.           of the /Nth /Day-of-the-week before (or after) /Adate.  
  316.  
  317. m         Do date arithmetic in terms of months rather than days.  Add the
  318.           number of months in the /N parm to the date in the /A parm.  /N
  319.           may be a negative number.
  320.  
  321. STRING-HANDLING FUNCTIONS
  322.  
  323. get       get user input from the keyboard, and produce it as output
  324.           Optionally, display a prompt string.
  325.  
  326. getu      same as get, but produce output converted to upper case
  327.  
  328. getk      get a keypress and produce it (converted to upper case)
  329.  
  330. len       produce the length of a string in the /Q parm
  331.  
  332. upper     convert the string in the /Q parm to upper case
  333.  
  334. e         Echo the strings on the /P and /S parameters.
  335.  
  336. substr    Extract a substring from the /Q parm, starting in column
  337.           specified on /A parm, for a length specified on /B parm.
  338.  
  339. DATE/TIME COMPARISON FUNCTIONS
  340.  
  341. comp      Compare the dates in the /A and /B parms. Return LT, EQ, or GT.
  342.  
  343. tcomp     Compare the times specified on the /A and /B parms.
  344.  
  345.  
  346. ORDINARY (AS OPPOSED TO DATE) ARITHMETIC FUNCTIONS
  347.  
  348.           Functions whose names begin with "#" do ordinary arithmetic, i.e.
  349.           arithmetic on numbers rather than dates.
  350.  
  351. #add      Add the integers specified on the /A and /B parms.  To do
  352.           subtraction, add a negative number to a positive number.
  353.  
  354. #dif      returns the difference between the integers specified on the /A
  355.           and /B parms. 
  356.  
  357. #comp     Compare the integers specified on the /A and /B parms.  Return
  358.           LT, EQ, or GT.
  359.  
  360. #mod      Modulus.  Divide the integer on the /A parm by the integer on the
  361.           /B parm, and return the remainder.  
  362.  
  363. #mult     Multiply the integer on the /A parm by the integer on the /B
  364.           parm, and return the result.
  365.  
  366. #div      Divide the integer on the /A parm by the integer on the /B parm,
  367.           and return the result as a decimal number with two decimal
  368.           places.
  369.  
  370. #idiv     Integer division. Divide the integer on the /A parm by the
  371.           integer on the /B parm, and return the result as an integer.
  372.  
  373. #2xx      Convert an integer in the range of 0-35 to "extended hex" (XX)
  374.           notation.
  375.  
  376. FUNCTIONS: DETAILED DESCRIPTIONS
  377. ================================
  378.  
  379.  
  380. DATE FORMATTING FUNCTIONS
  381. =========================
  382.  
  383. FUNCTION  FDATE /Ffunc /Adate /Iformat /Oformat
  384. --------  -------------------------------------------
  385. format    this is a synonym for function "f"
  386.  
  387. f         returns /Adate in format specified by /Oformat
  388.           Since /Aformat and /Oformat can be different, the FORMAT
  389.           function is used to change a date from one format to another.
  390.           Because of the wide variety of output formats, the FORMAT
  391.           function can also be used to determine the day of week of the
  392.           date, whether the date is in a normal or leap year, etc.
  393.  
  394. EXAMPLES
  395.           FDATE /Ff /A19920101 /Iccyymmdd /O"mn zd, ccyy"
  396.           FDATE /Ff       /Atoday         /Od1
  397.           FDATE /Fformat  /Atoday         /Od1
  398.           FDATE /Ff /If /Afdate.exe /P"FDATE.EXE last updated: " /Ofull
  399.  
  400. DATE ARITHMETIC FUNCTIONS
  401. =========================
  402.  
  403. Internally, numbers in Fdate are stored in Turbo Pascal's LONGINT datatype,
  404. which means that Fdate can accept numbers up to 9 digits long.
  405.  
  406. FUNCTION  FDATE /Ffunc /Nnumdays /Adate /Iformat /Oformat
  407. --------  -------------------------------------------
  408. add       Adds      /Ndays to   /Adate, produces date in /Oformat format
  409. sub       Subtracts /Ndays from /Adate, produces date in /Oformat format
  410.  
  411.           EXAMPLES
  412.           FDATE /Fadd /N90 /A01-01-1992 /Imm-dd-ccyy /Od1
  413.           FDATE /Fsub /N90 /A01-01-1992 /Imm-dd-ccyy /Od1
  414.           FDATE /Fadd /N90 /Atoday                   /Od1
  415.  
  416. dif       Returns number of days between /Adate and /Bdate
  417.           Order of the two dates is not significant.
  418.  
  419.           NOTE THAT:
  420.           For DIF, both dates must be in the SAME format, the input format
  421.           specified in /Iformat.  If the two dates are not in the same
  422.           format, you must first reformat one of the dates using the /Ff
  423.           function, then use DIF to get their difference.
  424.  
  425.           EXAMPLES
  426.           FDATE /Fdif /A01-01-1992 /B11-11-1992  /Imm-dd-ccyy
  427.           FDATE /Fdif /A11-11-1992 /B01-01-1992  /Imm-dd-ccyy
  428.           FDATE /Fdif /Atoday      /B01-01-1992  /Imm-dd-ccyy
  429.  
  430. MONTH DATE ARITHMETIC FUNCTIONS
  431. ===============================
  432.  
  433. FUNCTION  FDATE /Ffunc /Nnumdays /Adate /Iformat /Oformat
  434. --------  -------------------------------------------
  435. m         [month arithmetic]
  436.  
  437.           This function adds /N months to /Adate, and produces a date in
  438.           /Oformat format.  It can be used to do monthly subtraction by
  439.           making the number in the /N parameter a negative number.
  440.  
  441.           EXAMPLES
  442.  
  443.           FDATE /Fm /N1  /A03-15-1992 /Imm-dd-ccyy /Omm-dd-ccyy
  444.                   produces:   04-15-1992
  445.  
  446.           FDATE /Fm /N-1 /A03-30-1991 /Imm-dd-ccyy /Omm-dd-ccyy
  447.                   produces:   02-28-1991
  448.  
  449.           FDATE /Fm /N-1 /A03-30-1992 /Imm-dd-ccyy /Omm-dd-ccyy
  450.                   produces:   02-29-1992
  451.  
  452.  
  453.           Note that a too-simple algorithm for month arithmetic can produce
  454.           non-existent dates.  Subtracting a month from March 30, 1991 (as
  455.           in the second example) could produce a result of February 30,
  456.           1991, a date which cannot exist.  
  457.  
  458.           Fdate's month arithmetic is more sophisticated than that.  If
  459.           Fdate finds that a simple month-arithmetic operation produces an
  460.           invalid date, it subtracts the minimum number of days required to
  461.           produce a valid date.  
  462.  
  463.           Thus, in the second example, it produces February 28, 1991, the
  464.           last date in February, 1991.  In the third example, it produces
  465.           February 29, 1992 because 1992 is a leap year.  
  466.  
  467.  
  468. Note that telling Fdate to add 12 months to February 29, 1992 produces a
  469. result of February 28, 1993, since 1993 is not a leap year.  See Peter G.
  470. Neumann's INSIDE RISKS column in COMMUNICATIONS OF THE ACM, June 1992 (Vol.
  471. 35, No. 6), entitled "Leap-Year Problems":
  472.  
  473.   Prime Computer's MAGSAV failed at midnight [on Feb 29, 1992]...  G. M.
  474.   Lack noted that MAGSAV probably failed on leap-day because it tried to
  475.   increment the year by one to set a tape label expiration date, and the
  476.   resulting nonexistent date of Feb 29, 1993 threw it for a loop.
  477.  
  478. WEEKDAY DATE ARITHMETIC FUNCTIONS
  479. =================================
  480.  
  481. FUNCTION  FDATE /Ffunc /Adate /Iformat /Oformat /Ddow#  /Ndow-count
  482. --------  -----------------------------------------------------------
  483. w         [week arithmetic]
  484.           This function provides a way of doing date arithmetic in terms of
  485.           weeks rather than days.
  486.  
  487.           This function accepts a date specification in parm /A and
  488.           returns the date of the /Nth /Day-of-the-week
  489.           before or after /Adate.  For example:
  490.  
  491.           If    /A specifies November 14, 1992
  492.                 /D specifies the number for Thursday (i.e., 5)
  493.                 /N specifies a week count of 3
  494.           then /Fw returns the date of the third Thursday after
  495.           November 14, 1992. (See full example, below)
  496.  
  497.           Note that /N may be negative.  If, in the above example, /N
  498.           is specified as -3, then Fdate returns the date of the third
  499.           Thursday BEFORE November 14, 1992.
  500.  
  501.           If the date specified on the /A parms falls on the same day
  502.           of the week as was specified on the /D parm, then that will
  503.           be considered to be the first date meeting that day-of-week
  504.           criterion.  That is, if November 14, 1992 fell on a
  505.           Thursday, and if /N was 1 or -1, then the output date would
  506.           be the same as the input date, i.e.  November 14, 1992.
  507.  
  508.           The acceptable values for /N (number of weeks) is in
  509.           the range of 99..-99.  A value of zero (i.e. /N0) is invalid.
  510.  
  511. EXAMPLES
  512.      find date of Thanksgiving (4th Thursday in November) in 1992
  513.          FDATE /Fw /A11-01-1992 /Imm-dd-ccyy /D5 /N4 /Od1
  514.      returns: Thursday November 26, 1992
  515.  
  516.      find the beginning of the work-week (Monday, 2nd day of week)
  517.      AFTER Thanksgiving, 1992
  518.          FDATE /Fw /A11-26-1992 /Imm-dd-ccyy /D2 /N1 /Od1
  519.  
  520.      find the beginning of the work-week (Monday, 2nd day of week)
  521.      BEFORE Thanksgiving, 1992
  522.          FDATE /Fw /A11-26-1992 /Imm-dd-ccyy /D2 /N-1 /Od1
  523.  
  524.      get last Friday's date
  525.         rem Find next Friday's date (or today's date, if today is Friday).
  526.         rem Then find the Friday that precedes that Friday.
  527.         FDATE /Fw /At        /Omm-dd-ccyy  /D6 /N+1  /V
  528.         FDATE /Fw /A%fdate%  /Imm-dd-ccyy  /D6 /N-2  /V
  529.         Echo Last Friday was %fdate%
  530.  
  531. DATE/TIME COMPARISON FUNCTIONS
  532. ==============================
  533.  
  534. FUNCTION  FDATE /Ffunc /Adate /Bdate /Iformat
  535. --------  -------------------------------------------
  536. comp      compares the dates (time granularity = 1 day)
  537.           specified on the /A and /B parms.
  538.           returns         when
  539.             LT            /A  is less than    (earlier than) /B
  540.             EQ            /A  is equal to     (same as)      /B
  541.             GT            /A  is greater than (later than)   /B
  542.  
  543.           In addition, the errorlevel is set to a special value:
  544.             LT = 101     EQ = 102     GT = 103
  545.  
  546.  
  547.  
  548. tcomp     compares the times (time granularity = 1 second)
  549.           specified on the /A and /B parms.
  550.           This is useful when input format /If (file) is specified.
  551.           It can be used to compare the timestamps of two files and
  552.           determine which is older.
  553.               EXAMPLE: Fdate /Ftcomp /If /Amyfile.1 /Byourfile.1
  554.  
  555.           returns         when
  556.             LT            /A  is less than    (earlier than) /B
  557.             EQ            /A  is equal to     (same as)      /B
  558.             GT            /A  is greater than (later than)   /B
  559.  
  560.           In addition, the errorlevel is set to a special value:
  561.             LT = 101     EQ = 102     GT = 103
  562.  
  563.  
  564.  
  565. COMPARE-FUNCTION ERRORLEVELS
  566. ============================
  567.  
  568. Starting with version 8.3, Fdate's "comparison" functions (comp, tcomp,
  569. #comp) return distinct errorlevels as well as distinct output strings:
  570.  
  571.           returns         errorlevel
  572.             LT            101
  573.             EQ            102
  574.             GT            103
  575.  
  576. NUMERIC ARITHMETIC FUNCTIONS
  577. ============================
  578.  
  579. Note that all of Fdate's arithmetic functions operate on integers.  A
  580. decimal number on an input parameter will be rejected, and an error message
  581. will be displayed.
  582.  
  583. FUNCTION  FDATE /Ffunc /Anum  /Bnum
  584. --------  -------------------------------------------
  585.  
  586. #add      returns the sum of the integers specified
  587.           on the /A and /B parms.  Can be used to calculate the
  588.           "absolute" minute(second, date) in the future from a given
  589.           "absolute" minute(second, date).   Also useful in generating
  590.           sequences of numbers and looping (see EXAMPLES).
  591.  
  592. #sub      (not supported)
  593.           Fdate does not provide a numeric subtraction operation as such. 
  594.           To do subtraction, add two numbers, one of which is a negative
  595.           number.  For example, to subtract 3 from 2:
  596.               FDATE /F#add /A2 /B-3          [ returns: -1 ]
  597.  
  598. #dif      returns the difference between the integers specified on the /A
  599.           and /B parms.  #dif is the same as subtraction in which the
  600.           smaller number is subtracted from the larger number; it will
  601.           never return a negative number.  It can be used to calculate the 
  602.           number of minutes(seconds, days) between two "Absolute"
  603.           minutes(seconds, dates).
  604.  
  605. #comp     compares the integers specified on the /A and /B parms.
  606.           returns         when
  607.             LT            /A  is less    than /B
  608.             EQ            /A  is equal   to   /B
  609.             GT            /A  is greater than /B
  610.  
  611.           In addition, the errorlevel is set to a special value:
  612.             LT = 101     EQ = 102     GT = 103
  613.  
  614. #mod      divides the integer on the /A parm by the integer on the /B parm,
  615.           and returns the remainder.  
  616.  
  617.           This is useful for determining whether a number is evenly
  618.           divisible by some other number.  If the remainder is 0, then /A
  619.           is evenly divisible by /B.  If a year is evenly divisible by 4,
  620.           for example, then it is an American election year.  If it is
  621.           evenly divisible by 100, then it is a century year, etc.
  622.  
  623.  
  624. #mult     multiplies the integer on the /A parm by the integer on the /B
  625.           parm, and returns the result.
  626.  
  627. #div      (division) divides the integer on the /A parm by the integer on
  628.           the /B parm, and returns the result as a decimal number, with two
  629.           digits to the right of the decimal.
  630.  
  631.           This is useful for dividing a number (representing the number of
  632.           minutes in some period) by 60 to get the length of the period
  633.           expressed in terms of hours, or by 1440 to get the length of the
  634.           period expressed in terms of days.  Or you could divide a number
  635.           of days by 7 to get the number of weeks, etc.
  636.  
  637.  
  638. #idiv     (integer division) divides the integer on the /A parm by the
  639.           integer on the /B parm, and returns the result as an integer.
  640.  
  641.           This is useful, especially in conjunction with the #mod function,
  642.           for converting a number of minutes into a number of hours and
  643.           minutes, or days and hours and minutes.  See the EXAMPLES
  644.           section, below.
  645.  
  646. #2xx      (convert number to "extended hex" format)
  647.           "Extended hexadecimal" (XX) notation uses all of the digits, and
  648.           all of the letters of the alphabet, to express numbers in the
  649.           range of 0 to 35 as a single character.  
  650.  
  651.           This function takes a number supplied on parameter /A, and
  652.           returns a single character in extended hex notation.  The input
  653.           number should be in the range of 0-35.  A number of less than 0
  654.           or larger than 35 is rejected as an error (returns "ERROR" and
  655.           errorlevel of 1).
  656.  
  657.           EXAMPLE: Fdate /F#2xx /A35    =====> returns the letter Z
  658.  
  659. DATE VALIDATION FUNCTION
  660. ========================
  661.  
  662. v    If the date specified on the /A parm is valid, produces "" (the null
  663.      string).  Otherwise, produces "ERROR" and a non-zero errorlevel by
  664.      triggering Fdate's error-handling function.  (See the section on
  665.      FDATE'S ERROR HANDLING, later in this documentation.)
  666.  
  667.      When using the /Fv parameter, you will almost always want to check
  668.      success of the date validation by checking the errorlevel, and to
  669.      redirect Fdate's output to NUL (so that when it writes the null
  670.      string, it does not produce a blank line on your screen).
  671.  
  672.      When processing an input date, Fdate does not reject all invalid
  673.      dates: specifically, it is very forgiving about the number in the day-
  674.      of-the-month part of input dates.  It will accept, for example,
  675.      19931144 (November 44, 1993 in CCYYMMDD format) and process it quite
  676.      happily (as December 14, 1993).  This is not a bug, it is a feature. 
  677.      This feature provides one way (admittedly a crude one) of doing date
  678.      arithmetic.  The date part (JJJ) of a Business Julian input date can
  679.      be used in the same way.  
  680.  
  681.      This feature can be a drawback, however, if you want to be sure that
  682.      some date (say a date that a user entered as an input parameter) is
  683.      valid.  The /Fv function provides a way of completely checking a date
  684.      for validity.  It will, for example, reject November 44, 1993 as
  685.      invalid. 
  686.  
  687.  
  688. STRING FUNCTIONS
  689. ================================
  690.  
  691. GET and GETU (GET USER INPUT) FUNCTIONS
  692. =======================================
  693.  
  694. get  get user input
  695. getu get user input (uppercase)
  696.  
  697.      These functions wait for the user to enter an input string, terminated
  698.      by a press of the ENTER key.  Then Fdate simply produces that same
  699.      input string (or in the case of GETU, that input string in all upper
  700.      case) as its output.  
  701.  
  702.      If the /Q prompt-string parameter is specified, then the prompt string
  703.      is displayed, but a NEWLINE is not written to the screen before
  704.      waiting for the user's input.
  705.  
  706.      As with Fdate's other forms of output, this output can be displayed,
  707.      redirected to a file, or (if your environment supports Fdate's /V
  708.      parameter) placed into an environment variable.
  709.  
  710.      This "get" function provides no edit mask for input -- Fdate will
  711.      accept anything.  The situation is helped by the fact that Fdate also
  712.      provides a validate function (/Fv) which can be used to validate the
  713.      user input, so that one can:
  714.  
  715.           1.   use /Fget to get user input and place it in an environment
  716.                variable 
  717.           2.   use /Fv to validate the date in the Evar
  718.           3.   use the rest of the batch file to process the user input
  719.  
  720.      See examples: "Get user input" and FORATIM2.BAT
  721.  
  722.      For a program that provides more sophisticated functions for getting
  723.      user input in batch files (type checking, edit masks, etc.), I
  724.      recommend Bob Stephan's shareware program GET, which is described
  725.      elsewhere in this documentation.
  726.  
  727. GETK (GET KEYPRESS) FUNCTION
  728. =======================================
  729. getK get keypress 
  730.  
  731.      This function waits for the user to press an acceptable key, then
  732.      produces the key as its output.  If the key pressed is a letter, then
  733.      the letter is returned IN UPPER CASE.  This feature is designed to
  734.      support simple "pick a menu selection" processing in batch files.
  735.  
  736.      The GETK function takes a /K "keymask" parameter that tells it which
  737.      keys to accept.  If the user presses an unacceptable key (i.e. one
  738.      that is not in the keymask), the keypress is ignored.
  739.  
  740.      If no /K parm is specified, the default keymask is:
  741.              ABCDEFGHIJKLMNOPQRSTUVWXYZx
  742.      That is, the default keymask will accept letters and the ESCAPE key.
  743.  
  744.   Specifying the Keymask
  745.  
  746.      NOTE THAT THE VALUES SPECIFIED ON THE /K PARM ARE CASE-SENSITIVE.  
  747.  
  748.      The keymask may contain numbers, uppercase letters, and any of the
  749.      other printable characters on the keyboard.  
  750.  
  751.      There is no way to tell FDATE to accept "special" keypresses such as
  752.      function keys, ALT or CONTROL keys, arrow keys, etc.
  753.  
  754.      If the keymask contains an uppercase letter (e.g. "A"), and the user
  755.      presses the corresponding unshifted letter (e.g. "a"), then the
  756.      keypress will be accepted and the uppercase letter will be returned.
  757.  
  758.      The keymask may contain the following lowercase letters, which have
  759.      special meanings:
  760.  
  761.        x  represents the ESCAPE key
  762.        e  represents the ENTER (RETURN) key
  763.        z  [a place-holder character]
  764.  
  765.             Lowercase "z" will be ignored when FDATE decides which
  766.             keypresses are acceptable.  Its presence in the keymask will
  767.             affect the positions of other characters in the keymask, and
  768.             hence the ERRORLEVEL that FDATE returns when the user presses
  769.             an acceptable key.  (For the uses of "z", see "GetK Results
  770.             also in ERRORLEVEL" and "Modifying the Keymask", below.)
  771.  
  772.      All other lowercase letters are reserved for possible future use.  In
  773.      the current release of FDATE, they are treated like lowercase "z".
  774.  
  775.      EXAMPLE:  If a keymask of "/kXx" was specified, then if the user
  776.                pressed the (shifted or unshifted) "X" key, then uppercase
  777.                "X" would be returned.  If he pressed the ESCAPE key, then
  778.                lowercase "x" would be returned.
  779.  
  780.   GetK Results also in ERRORLEVEL
  781.  
  782.      When the GETK function returns a key, it sets the DOS errorlevel to a
  783.      value corresponding to the position of that key in the keymask.  For
  784.      example, with keymask of "/kABx", if the user presses:
  785.  
  786.           "A": value returned will be "A", errorlevel will be 1
  787.           "B": value returned will be "B", errorlevel will be 2
  788.        ESCAPE: value returned will be "x", errorlevel will be 3
  789.  
  790.      If the user presses CONTROL+BREAK, FDATE will abort and return
  791.      errorlevel 255.
  792.  
  793.      Here is an example batch file:
  794.      ==================================================================
  795.      @echo off
  796.      cls
  797.      echo Demonstration of FDATE's GETK (get keypress) function
  798.      echo Press CONTROL+BREAK to end
  799.      :top
  800.      echo.
  801.      fdate /fGetK /P"You pressed: " /Q"Press a key: "  /K"12ABxe "
  802.      if errorlevel 1  if not errorlevel 2  echo errorlevel : 1
  803.      if errorlevel 2  if not errorlevel 3  echo errorlevel : 2
  804.      if errorlevel 3  if not errorlevel 4  echo errorlevel : 3
  805.      if errorlevel 4  if not errorlevel 5  echo errorlevel : 4
  806.      if errorlevel 5  if not errorlevel 6  echo errorlevel : 5
  807.      if errorlevel 6  if not errorlevel 7  echo errorlevel : 6
  808.      if errorlevel 7  if not errorlevel 8  echo errorlevel : 7
  809.      if errorlevel 255 echo ERRORLEVEL 255
  810.      if errorlevel 255 goto endit
  811.      goto top
  812.      :endit
  813.      ==================================================================
  814.  
  815.      Note that the keymask may contain blanks if the keymask is enclosed in
  816.      quotes (as in this example batch file).  But remember that Fdate
  817.      eliminates redundant spaces when obtaining its parameter input, so you
  818.      should never include more than one blank in your keymask.
  819.  
  820.   Modifying the Keymask
  821.  
  822.      It it is often necessary to make program modifications during the life
  823.      of a batch file.  If you are using the GETK function and testing the
  824.      errorlevel rather than the environment, then the insertion or deletion
  825.      of characters into the existing keymask will change the errorlevels
  826.      returned by the following characters in the keymask.  This will force
  827.      you to re-write the errorlevel tests, which may be a big job if the
  828.      keymask is long.
  829.  
  830.      Here are some tips on how to avoid this work:
  831.  
  832.          When ADDING a character to the keymask, always add it at the END
  833.           of the keymask.
  834.  
  835.          When DELETING a character from the keymask, do not actually
  836.           delete it.  Instead, replace it by a lowercase "z".
  837.  
  838.  
  839.  
  840.   Displaying a User Prompt With GETK
  841.  
  842.      The /Q (user prompt) parameter is especially handy when used in
  843.      conjunction with the GETK function.  If the /Q prompt-string parameter
  844.      is specified (as in the example batch file, above), then the prompt
  845.      string is displayed, but a NEWLINE is not written to the screen before
  846.      waiting for the user's keypress.
  847.  
  848.      For a program that provides more sophisticated "get key" functions for
  849.      batch files, I recommend Bob Stephan's shareware program GET, which is
  850.      described elsewhere in this documentation.
  851.  
  852. SUBSTR (SUBSTRING) FUNCTION
  853. ===============================
  854.  
  855. substr
  856.      This function returns a substring of the string supplied in the /Q
  857.      parm, starting in the column supplied in the /A parm, for a length
  858.      supplied in the /B parm.  
  859.  
  860.      The start column specified in the /A parm may be a negative number; if
  861.      it is, then the start column is calculated from the end of the string
  862.      rather than from the beginning.  This feature makes it easy to extract
  863.      the rightmost characters of a string.  
  864.  
  865.                Specifically, when the ParmA is negative, the start position
  866.                is calculated using the following formula:
  867.  
  868.                       StartColumn = length(ParmQ) + 1 + ParmA
  869.  
  870.                Example:   Fdate /Fsubstr  /A-2  /Qabcd
  871.                       StartColumn = length(ParmQ) + 1 + ParmA
  872.                       StartColumn =      4        + 1 + (-2)     = 3  
  873.  
  874.      If /Q is omitted, Fdate reports an error.
  875.  
  876.      If /A is zero, Fdate reports an error.
  877.      If /A is omitted, it defaults to 1 (that is, the start of the string).
  878.      If /A is negative,  and longer than the length of the string, then the
  879.                          start column is 1 (the start of the string)
  880.  
  881.      If /B (length) is so great that it exceed the length of the /Q input
  882.      string, then only the remainder of the string is returned.
  883.  
  884.      If /B is zero, Fdate returns a null string.
  885.      If /B is omitted, it defaults to 999.
  886.  
  887.      EXAMPLES:
  888.           Fdate /Fsubstr /A7 /B2 /Q"STEVE FERG"   ===> "FE"
  889.           Fdate /Fsubstr /A7     /Q"STEVE FERG"   ===> "FERG"    
  890.           Fdate /Fsubstr     /B5 /Q"STEVE FERG"   ===> "STEVE"   
  891.  
  892.      EXAMPLES using a negative start position:
  893.           Fdate /Fsubstr /a-6 /B3 /Q"1994 Jun 03"   ===> "Jun         
  894.  
  895.           rem extract the rightmost 6 characters of a string
  896.           Fdate /Fsubstr /a-6     /Q"1994 Jun 03"   ===> "Jun 03"     
  897.  
  898.           rem pad YEAR environment variable to the left with zeroes, 
  899.           rem to make sure it is 4 bytes long
  900.           Fdate /Fsubstr /A-4 /q0000%year% /vyear
  901.  
  902.  
  903.      REMEMBER that Fdate eliminates redundant spaces when obtaining its
  904.      parameter input:
  905.  
  906.           Fdate /Fsubstr /A7     /Q"STEVE FERG"      ===> "FERG" 
  907.           Fdate /Fsubstr /A7     /Q"STEVE  FERG"     ===> "FERG" 
  908.           Fdate /Fsubstr /A7     /Q"STEVE    FERG"   ===> "FERG" 
  909.  
  910. LEN (LENGTH) FUNCTION
  911. =====================
  912.  
  913. len       Produces a number that is the length of the string on the /Q
  914.           parm.
  915.  
  916.  
  917. UPPER FUNCTION
  918. ===============
  919.  
  920. upper     Produces the string on the /Q parm, converted to upper case.
  921.  
  922.  
  923.  
  924. ECHO FUNCTION
  925. =============
  926.  
  927. e         Produces only the strings specified using the /P and /S
  928.           parameters.
  929.  
  930. You can use /Fe for situations in which you want Fdate to produce output
  931. that doesn't include any sort of date.  In these cases, Fdate functions
  932. just like the DOS "echo" command.  
  933.  
  934. The /Fe function is especially useful in conjunction with the /J (justify)
  935. parm (see below).
  936.  
  937. One nifty feature of /Fe (although one that will be of interest only to
  938. extreme batch-file power users) is its ability, when used in conjunction
  939. with /V, to put a character into an environment variable that the SET
  940. command would not accept: characters such as an equal-sign "=" , the
  941. redirection symbol ">", and the pipe symbol "|".
  942.  
  943. /J: JUSTIFYING OUTPUT
  944. ==========================
  945. Using the /J (justify) parameter, it is possible to right, center, or left-
  946. justify FDATE's output, truncate it, or pad it with a certain character.   
  947.  
  948. Note that /J is not a function, but a parameter.  The /J parameter may be
  949. used in conjunction with any of FDATE's functions.  (It is discussed here,
  950. with the string-handling functions, because that's where it seemed most at
  951. home.)
  952.  
  953. Justification takes place AFTER the strings specified on the /P (prefix)
  954. and /S (suffix) parms have been added to the output.
  955.  
  956. The format of the /J parm is:      /J"tp##"         where
  957.  
  958.   t is a single character indicating the type of justification desired:
  959.        R  right
  960.        L  left
  961.        C  centered
  962.  
  963.   p  is a single character specifying the character to be used to pad the
  964.      output out to the desired length.  The most common values for this
  965.      character will be the period (".") and the blank.  In order for a
  966.      blank to be recognized as a pad character (and not to be taken as the
  967.      terminator of the /J-parm value), the /J-parm value must be enclosed
  968.      in single or double quotes, e.g.:   /J"C 79"
  969.  
  970. ##   is a number that specifies the length of the field within which
  971.      justification should take place.  This must be a number between 1 and
  972.      240.
  973.  
  974.      If ## is less than the length of the un-justified output string, then
  975.      the un-justified output string will be truncated to ## characters,
  976.      starting at the point specified by the justification type (i.e. at the
  977.      right, left, or center of the un-justified output string).
  978.  
  979.  
  980. SOME USES FOR THE /J PARM  
  981.  
  982.   (Most of these uses are illustrated in HOLIDAYS.BAT, which is included
  983.   in the FDATE distribution ZIP file.)
  984.  
  985.   In conjunction with the "echo" function (/Fe), the /J parm can be used
  986.   to justify any value that you wish, not just output dates created by
  987.   Fdate.  Put the value to be justified in the /P (prefix) parm and/or the
  988.   /S (suffix) parm.  Put a title, for example, as the value of the /P
  989.   parm, and specify center justification, padded with spaces, to a length
  990.   of 79 characters (/J"c 79").  This will display the title, centered on
  991.   the screen.
  992.  
  993.   If you use the "echo" function and the /J parm, and specify the /P or /S
  994.   parm but do not specify values for them, then only the pad character
  995.   will be displayed. (That is, the null string will be padded with the pad
  996.   character to the desired length.) 
  997.  
  998.      EXAMPLE:  This is a handy way to draw horizontal lines of dashes,
  999.                dots, or any other desired character.
  1000.                          FDATE  /Fe  /P  /JC-79 
  1001.  
  1002.   The /J parm can be used to left-pad a number with zeroes.
  1003.  
  1004.      EXAMPLE:  Many of Fdate's input formats require the year to be in
  1005.                complete 4-digit CCYY format.  If your batch file obtains a
  1006.                value for YEAR from the user, the user might enter a YEAR
  1007.                that is less than 1000.  You can add leading zeroes to YEAR
  1008.                by right justifying it, padded it with '0' to a length of 4. 
  1009.                
  1010.                     FDATE  /Fe  /P%year%  /JR04  /vyear
  1011.  
  1012.   Because /J can be used to truncate a string to a specified length, it
  1013.   can be used to extract the rightmost, leftmost, or centermost ##
  1014.   characters of a string. 
  1015.  
  1016.  
  1017. EXAMPLES
  1018.  
  1019.   Fdate /Fe /J"C 79" /P"SCREEN TITLE"
  1020.      Fdate's output is not put into an environment variable, so it will be
  1021.      displayed on the screen.  This command will echo the string "SCREEN
  1022.      TITLE" to the screen, centered in a field 79 characters long (that is,
  1023.      centered on the screen), and padded to the left and right with blanks.
  1024.  
  1025.   Fdate /Fe /J"L.40" /P"Next report due date" /Vtitle
  1026.   Fdate /fadd /N60  /Od1 /p"%title% "
  1027.      The first command left-justifies "Next report due date" in a string 40
  1028.      characters wide, padded to the right with periods, and puts it into
  1029.      the TITLE environment variable.  In the second step, the TITLE
  1030.      environment variable is used as the label for a date 60 days in the
  1031.      future.  In the second step, note the space between the end of %title%
  1032.      and the trailing double-quote.  This leaves a nice space between the
  1033.      dot leader and the date.
  1034.  
  1035.   For more examples, see HOLIDAYS.BAT.
  1036.  
  1037. DATE FORMATS
  1038. ============
  1039.  
  1040. SYMBOL CONVENTIONS
  1041. ==================
  1042.  
  1043. The following symbols are used in specifying date formats:
  1044.  
  1045. SYMBOL  EXAMPLE   MEANING
  1046. ------  -------   -------------------------------------
  1047. cc        19      century
  1048. yy        93      year
  1049. mm        02      month
  1050. zm         2      month without leading zero
  1051. dd        08      day
  1052. zd         8      day   without leading zero
  1053. mn       February month name
  1054. mn3      Feb      month name, first 3 characters only
  1055. dow      Tuesday  day of week
  1056. dow3     Tue      day of week, first 3 characters only
  1057. dow#      3       day of week as a number (Sunday=1, Monday = 2, etc.)
  1058. today             is a "pseudodate" representing the current date
  1059. t                 is an alias for the "today" pseudodate
  1060. hh:mm    09:05    hours and minutes
  1061. hhmm     0905     hours and minutes
  1062. ss        13      seconds
  1063.  
  1064.  
  1065.  
  1066. PSEUDODATES
  1067. ===========
  1068.  
  1069. t (or today)
  1070.           can be used with either /A or /B, e.g. /Atoday or /At.
  1071.           This is the default for both /A and /B.  That is, if /A is not
  1072.           specified, /At is assumed, and the same for /B.
  1073.  
  1074.           NOTE THAT
  1075.           "Today" as a date specification operates independently of any
  1076.           input format.  You need to specify an input format (either
  1077.           explicitly via the /I parameter, or implicitly by accepting the
  1078.           default value of /I) only for input dates that are supplied to
  1079.           Fdate in some other way than via the "today" pseudodate: as a
  1080.           date literal, a filename, etc.
  1081.  
  1082. EXAMPLES:
  1083.           rem Get the date that is 90 days from today
  1084.           FDATE /Fadd /N90 /Atoday /Omm-dd-ccyy
  1085.           FDATE /Fadd /N90 /At     /Omm-dd-ccyy
  1086.  
  1087.           rem determine if this year is a leapyear
  1088.           FDATE /Ff /At /OLY
  1089.  
  1090.  
  1091.  
  1092.  
  1093. tttt      When used in place of a 4-digit CCYY string, "tttt"
  1094.           will cause Fdate to use today's 4-digit year (CCYY).
  1095.  
  1096. tt        When used in place of a 2-digit DD, MM, or YY string,
  1097.           "tt" will cause Fdate to use today's day-of-the-month,
  1098.           month, or 2-digit year, respectively.
  1099.  
  1100.           Note that "tt" can NOT be used for the YY portion of a CCYY
  1101.           input year.  The following, for example, is NOT valid:
  1102.                FDATE /Ff /Imm-dd-ccyy /A01-01-19tt /Od1
  1103.  
  1104. EXAMPLES:
  1105.  
  1106.      FDATE /Ff /Imm-dd-ccyy /A01-01-tttt
  1107.      FDATE /Ff /Imm-dd-yy   /A01-01-tt 
  1108.  
  1109.      rem report the 15th day of this month, this year
  1110.      FDATE /Ff /Imm-dd-ccyy /Att-15-tttt
  1111.  
  1112.      rem Show the first Monday in the second quarter of this year
  1113.      FDATE /Fw /Iccyymmdd /Atttt0401 /D2 /N1  /P"First Monday in QTR#2: "
  1114.  
  1115.      rem Show the last Friday on/before the 15th of this month.
  1116.      FDATE /Fw /Iccyymmdd /Atttttt15 /D6 /N-1 /P"Friday before the 15th: "
  1117.  
  1118.  
  1119. INPUT DATE FORMATS
  1120. ==================
  1121.  
  1122.  
  1123. CALENDAR DATE INPUT FORMATS
  1124. ===========================
  1125.  
  1126. FORMAT      EXAMPLES      DISCUSSION
  1127. ------      ---------     -----------------------------
  1128. ccyymmdd    19922002  
  1129.  
  1130.  
  1131. On the /I (input format) parm, the separator character of the following
  1132. input formats must be a dash.  This simply tells Fdate that the input
  1133. date will contain SOME separator character.  The separator character that
  1134. actually occurs in dates in the /A and /B parms is ignored, and may be
  1135. any non-numeric character: a slash "/", a dash "-", a dot ".", etc.
  1136.  
  1137. In specifications that begin with "mm-dd" or "dd-mm", leading zeros need
  1138. not be present in the "mm" and "dd" part of the date.
  1139.  
  1140. ccyy-mm-dd  1992-02-20    Leading zeros MUST be present, since the
  1141.             1992/02/20    date does not begin with dd-mm or mm-dd.    
  1142.             1992.02.20    
  1143.  
  1144.  
  1145. mm-dd-ccyy  02-20-1992    
  1146.             02/20/1992    The dash represents ANY non-numeric character.
  1147.  
  1148.              2-5-1992     Leading zeros need not be present.
  1149.              2/5/1992
  1150.  
  1151. mm-dd-yy    02-05-92      February 5, 1992.  See discussion of
  1152.              2/5/92       FDATE'S CENTURY ASSUMPTION ALGORITHM, below
  1153.  
  1154.                           ---------------------------------------
  1155.                           In the following formats, days
  1156.                           precede months  (European style)
  1157.                           ---------------------------------------
  1158.  
  1159. dd-mm-ccyy  05-02-1992 
  1160.             05/02/1992 
  1161.  
  1162.              5-2-1992     Leading zeros need not be present.
  1163.              5/2/1992
  1164.  
  1165. dd-mm-yy    05-02-92      February 5, 1992.  See discussion of
  1166.              5/2/92       FDATE'S CENTURY ASSUMPTION ALGORITHM, below
  1167.  
  1168. BUSINESS JULIAN DATE INPUT FORMATS
  1169. ==================================
  1170.  
  1171. These are formats for "business julian" dates: dates expressed as the
  1172. number of days from the beginning of the year, when January 1 is day 1.
  1173.  
  1174. EXAMPLES:
  1175.  
  1176.       date      BUSINESS JULIAN DATE
  1177.   -----------   --------------------
  1178.   Jan  5, 1992  92005
  1179.   Jan  5, 1993  93005
  1180.   Dec 31, 1993  93365  [Dec 31 is 365th day of year 1993]
  1181.   Dec 31, 1996  96366  [Dec 31 is 366th day, because 1996 is a leap year]
  1182.  
  1183. -----------------------------------------------------------------------
  1184. NOTE:   * JJJ can be 1 - 4 digits
  1185.         * may include a prefix of a plus or minus ( + or - ) sign
  1186. -----------------------------------------------------------------------
  1187.  
  1188. FORMAT      EXAMPLES      DISCUSSION
  1189. ------      ---------     -----------------------------
  1190. ccyyjjj     1992003       Third day of 1992, i.e. Jan 3, 1992
  1191.             19923         Third day of 1992
  1192.             tttt003       Third day of this year
  1193.             tttt3         Third day of this year
  1194.  
  1195.   yyjjj       92003       Third day of 1992
  1196.               923         Third day of 1992
  1197.               tt003       Third day of this year
  1198.               tt3         Third day of this year
  1199.               01003       Third day of 2001           See
  1200.                           FDATE'S CENTURY ASSUMPTION ALGORITHM, below
  1201.  
  1202. NOTE THAT FDATE WILL ACCEPT "JJJ" OF LESS THAN 1 & MORE THAN 366.
  1203. -----------------------------------------------------------------
  1204.  
  1205.   yyjjj       tt1000      the 1000th day from beginning of this year
  1206.               tt0         last day of last year
  1207.               tt-1        next-to-last day of last year
  1208.  
  1209. FDATE /Ff /Iccyyjjj /Od1 /A1992-1  produces... Monday December 30, 1991
  1210. FDATE /Ff /Iccyyjjj /Od1 /A19920   produces... Tuesday December 31, 1991
  1211. FDATE /Ff /Iccyyjjj /Od1 /A1992+1  produces... Wednesday January 1, 1992
  1212.  
  1213. FDATE /Ff /Iccyyjjj /Od1 /A1992366 produces... Thursday December 31, 1992
  1214. FDATE /Ff /Iccyyjjj /Od1 /A1992367 produces... Friday January 1, 1993
  1215.  
  1216. This feature allows limited date arithmetic with ordinary business
  1217. Julian days.  For example, 90 days from tt300 can be shown by:
  1218.  
  1219.                   FDATE /Ff /Iyyjjj /Att390
  1220.  
  1221. GETTING DATE/TIME A FILE WAS CREATED
  1222. ====================================
  1223.  
  1224. FORMAT      EXAMPLES      DISCUSSION
  1225. ------      ---------     -----------------------------
  1226. f           MYFILE.1      Input format F (file) tells Fdate that
  1227.                           /A and /B will specify filenames, and that
  1228.                           Fdate should pick up the input date and time
  1229.                           from the date/time stamp on a file.
  1230.  
  1231. Example: FDATE /Ff /If /Afdate.exe /P"FDATE.EXE last updated: " /Ofull
  1232.  
  1233.      Note that if you specify /If, then both /A and /B will be interpreted
  1234.      as filenames.
  1235.  
  1236.      Because the input format applies to both /A and /B parms, it is not
  1237.      possible to put a filename in /A and a date literal in /B, and then
  1238.      (say) use the "comp" or "dif" function to compare them.  You must
  1239.      first extract the file's date into an environment variable, and then
  1240.      compare that environment variable to the date literal.
  1241.  
  1242.           The only exception to this rule is the pseudodate "t" (i.e. /At
  1243.           or /Bt) which will pick up the current date and time from the
  1244.           system clock.  This feature will allow you, for example, to
  1245.           compare the date of a file to today's date (see EXAMPLES).
  1246.  
  1247.      A filename may (but need not) be fully qualified: i.e. "MYFILE.1" and
  1248.      "C:\DBASE\WORKDIR\MYFILE.1" are both acceptable.
  1249.  
  1250.      A filename may contain wildcards.  If it does, the date/time stamp
  1251.      will be retrieved from the first file that FDATE finds that meets the
  1252.      filespec.  Giving FDATE a filespec containing a wildcard is pretty
  1253.      useless, but FDATE will not reject it.
  1254.  
  1255. OUTPUT DATE FORMATS
  1256. ===================
  1257.  
  1258. FORMAT        EXAMPLES      COMMENTS
  1259. ------        ---------     -----------------------------
  1260. dd-mn3-yy     08-Feb-92     CompuServe-style date
  1261.   yy            93          2-digit year number
  1262. ccyy          1993          4-digit year number (includes century)
  1263. ccyymm        199302        useful for triggering monthly processing
  1264. ccyymmdd      19930208      useful for putting current date in filename
  1265.   yymmdd        930208      PKZIP's Japanese date format
  1266.     mmdd          0208
  1267.     mmddyy        020892    PKZIP's American date format
  1268.       mm            02      2-digit month number
  1269.       zm             2      month number, no leading zeros
  1270.       dd            08      2-digit day-of-month number
  1271.       zd             8      day-of-month number, no leading zeros
  1272.  
  1273. In the following formats, months precede days (American style)
  1274. ------------------------------------------------------------------
  1275. mm/dd/ccyy    02/08/1993
  1276. mm-dd-ccyy    02-08-1993
  1277. mm.dd.ccyy    02.08.1993    British-style dates
  1278.  
  1279. zm/zd/ccyy     2/8/1993     no leading zeros in day or month
  1280. zm-zd-ccyy     2-8-1993     no leading zeros in day or month
  1281. zm.zd.ccyy     2.8.1993     British-style dates
  1282.  
  1283. mm/dd/yy      02/08/92
  1284. mm-dd-yy      02-08-92
  1285. mm.dd.yy      02.08.92      British-style dates
  1286.  
  1287. zm/zd/yy       2/8/92       no leading zeros in day or month
  1288. zm-zd-yy       2-8-92       no leading zeros in day or month
  1289. zm.zd.yy       2.8.92       no leading zeros in day or month
  1290.  
  1291.  
  1292.  
  1293. In the following formats, days precede months  (European style)
  1294. ------------------------------------------------------------------
  1295.  
  1296. ddmmccyy      02081993
  1297. ddmmyy        020893       PKZIP's European date format
  1298.  
  1299. dd/mm/ccyy    02/08/1993
  1300. dd-mm-ccyy    02-08-1993
  1301. dd.mm.ccyy    02.08.1993    British-style dates
  1302.  
  1303. zd/zm/ccyy     2/8/1993     no leading zeros in day or month
  1304. zd-zm-ccyy     2-8-1993     no leading zeros in day or month
  1305. zd.zm.ccyy     2.8.1993     British-style dates
  1306.  
  1307. dd/mm/yy      02/08/93
  1308. dd-mm-yy      02-08-93
  1309. dd.mm.yy      02.08.93      British-style dates
  1310.  
  1311. zd/zm/yy       2/8/93       no leading zeros in day or month
  1312. zd-zm-yy       2-8-93       no leading zeros in day or month
  1313. zd.zm.yy       2.8.93       British-style dates
  1314.  
  1315. DAY-OF-WEEK AND MONTH OUTPUT FORMATS
  1316. ====================================
  1317.  
  1318. dow#           5            Sunday=1, Monday=2 .... Saturday=7.
  1319.  
  1320. dow            Thursday     name of day of week
  1321.                jeudi        if /Lfr specified
  1322.                Donnerstag   if /Lgr specified
  1323.  
  1324. dow3           Thu          first 3 characters of name of day of week
  1325.                jeu          if /Lfr specified
  1326.                Don          if /Lgr specified
  1327.  
  1328. mn             February     name of month
  1329.                fevrier      if /Lfr specified
  1330.                Februar      if /Lgr specified
  1331.  
  1332. mn3            Feb          first 3 characters of name of month
  1333.                fev          if /Lfr specified
  1334.                Feb          if /Lgr specified
  1335.  
  1336.  
  1337.  
  1338. MISCELLANEOUS OUTPUT FORMATS
  1339. ============================
  1340.  
  1341. full      9:05 pm on Wednesday February 5, 1992
  1342.           9:05 pm, mercredi le 5 fevrier 1992  [/Lfr specified]
  1343.           9:05 pm, miércoles el 5 de febrero de 1992 [/Lsp specified]
  1344.           Mittwoch, 5. Februar 1992, 21:05     [/Lgr specified]
  1345.  
  1346. d1        Saturday, February 5, 1992
  1347.           samedi le 5 fevrier 1992      [/Lfr specified]
  1348.           Mittwoch, 5. Februar 1992     [/Lgr specified]
  1349.  
  1350. ddmn3yy   05Feb92
  1351.  
  1352. xxx       2CP  (...Dec 25, 1992)
  1353.           This format represents dates for the years 1990-2024 in 3
  1354.           characters of "extended hex" ("XX") notation.  For more on XX
  1355.           notation, see the discussion of the #2XX function.
  1356.  
  1357.           The first character is the XX representation of the number of
  1358.           years since 1990 (1990 = 0, 1991 = 1, etc.).  If you attempt to
  1359.           output a date outside of the 1990-2024 range in XXX format, Fdate
  1360.           will report an error (i.e. return "ERROR" and errorlevel of 1).
  1361.  
  1362.           The second and third characters contain the XX representation of
  1363.           the month-number and day-of-month-number, respectively.
  1364.  
  1365.           EXAMPLE: "1993 Feb  1"  is represented as  "321"
  1366.           EXAMPLE: "2000 Dec 25"  is represented as  "ACP".
  1367.  
  1368. -----------------------------------------------------------------------
  1369. NOTE that the following formats contain embedded spaces.  Consequently
  1370. they must be enclosed in double quotes. EXAMPLE: /O"mn zd, ccyy".
  1371. -----------------------------------------------------------------------
  1372. "zd mn ccyy"      5 February 1992
  1373. "zd mn, ccyy"     5 February, 1992
  1374. "zd. mn ccyy"     5. February 1992   [German-style date format]
  1375. "zd. mn3 ccyy"    5. Feb 1992        [German-style date format]
  1376. "mn3 dd ccyy"     Feb 05 1992
  1377. "mn3 dd, ccyy"    Feb 05, 1992
  1378. "mn zd, ccyy"     February 5, 1992
  1379.  
  1380.  
  1381.  
  1382. LEAP-YEAR FLAG OUTPUT FORMAT
  1383. ============================
  1384.  
  1385. LY              0     "1" if date occurs in a leapyear, otherwise "0".
  1386.  
  1387.                  365 + this number gives total number of days in the year.
  1388.                   28 + this number gives total number of days in February.
  1389.  
  1390.  
  1391.  
  1392.  
  1393. TIME OUTPUT FORMATS
  1394. ===================
  1395. See also: the section on the /T (parm /A time override) parameter.
  1396.  
  1397. t1            9:05 am
  1398.               9:05 pm
  1399.  
  1400. tdos          9:05:10:10a     format used in DOS's TIME command 
  1401.               9:05:10:10p
  1402.  
  1403. HH:MM        09:05      24-hour time, hours:minutes
  1404.              21:05
  1405. HHMM         0905
  1406.              2105
  1407.  
  1408. HH:MM:SS     21:05:30   24-hour time, hours:minutes:seconds
  1409. HHMMSS       210530
  1410.  
  1411.  
  1412. BUSINESS JULIAN DATE OUTPUT FORMATS
  1413. ===================================
  1414.  
  1415. These are formats for "business julian" dates: dates expressed as the
  1416. number of days from the beginning of the year, when January 1 is day 1.
  1417.  
  1418. EXAMPLES:
  1419.  
  1420.       DATE      BUSINESS JULIAN DATE
  1421.   -----------   --------------------
  1422.   Jan  5, 1993  93005
  1423.   Dec 31, 1993  93365  [Dec 31 is 365th day of year 1993]
  1424.   Dec 31, 1996  96366  [Dec 31 is 366th day, because 1996 is a leap year]
  1425.  
  1426.  
  1427. FORMAT        EXAMPLES      DISCUSSION
  1428. ------        ---------     -----------------------------
  1429.  
  1430. ccyyjjj       1992027       Jan 27, 1992
  1431.   yyjjj         92027       "Business Julian" date expressed as number
  1432.     jjj           027       of days since January 1 of the same year.
  1433.     zzj            27       Note leading zero suppression in "zzj".
  1434.  
  1435.  
  1436. ABSOLUTE DATE/TIME OUTPUT FORMATS
  1437. =================================
  1438. See also: the section on the /T (parm /A time override) parameter.
  1439.  
  1440.  
  1441. month#          23927      "Absolute month": date expressed as number of
  1442.                            months since the beginning of the calendar. 
  1443.                            Returns "1" for any date in January, 0001, "2"
  1444.                            for any date in February, 0001, etc.
  1445.  
  1446. day#           727198      "Absolute date": date expressed as number of
  1447.                            days since the beginning of the calendar. 
  1448.                            Returns "1" for January 1, 0001, "2" for
  1449.                            January 2, 0001, etc.
  1450.  
  1451. minute#         33088       "Absolute minutes": time expressed as number
  1452.                             of minutes  since midnight, January 1, 1990.
  1453.  
  1454. second#        633088       "Absolute seconds": time expressed as number
  1455.                             of seconds  since midnight, January 1, 1990.
  1456.  
  1457.  
  1458. Running FDATE with /O parameter for an "absolute time" produces a
  1459. number based on the current time of day and the date in the /A parm.
  1460.  
  1461. If, on January 10, 1992 at 2 pm, you run FDATE this way:
  1462.        FDATE /Ff /Atoday /Ominute#
  1463. it will produce the absolute minute for January 10, 1992 at 2 pm.
  1464.  
  1465. If, on January 10, 1992 at 2 pm, you run FDATE this way:
  1466.        FDATE /Ff /A01-15-1992 /Imm-dd-ccyy  /Ominute#
  1467. it will produce the absolute minute for January 15, 1992 at 2 pm.
  1468.  
  1469.  
  1470. /T: TIME OVERRIDE PARAMETER
  1471. ===============================
  1472.  
  1473. You may override Fdate's use of the current time -- for the /A parameter
  1474. only -- by using the /T parameter.  The /T parameter specifies a time of
  1475. day in the 24-hour format hh:mm:ss (hours:minutes:seconds).  Leading zeros
  1476. in each of the three fields (hh, mm, ss) may be omitted.  The seconds field
  1477. may be omitted; if omitted, it defaults to "00".
  1478.  
  1479. Note that the /T parm overrides the time portion of the /A date, but it
  1480. does NOT override the time portion of the /B date.
  1481.  
  1482. If, on January 10, 1992 at 2 pm, you run FDATE this way:
  1483.        FDATE /Ff /A01-15-1992 /Imm-dd-ccyy  /Ominute#  /T5:12
  1484. it will produce the absolute minute for January 15, 1992 at 5:12 am.
  1485.  
  1486. The most frequent and important use of the /T parm is with the format
  1487. function (/Ff) to obtain the "absolute" minute of a specific date and time. 
  1488. Once we have the absolute minutes of two different date/times, we can
  1489. easily obtain the time between them (expressed in days, hours, and minutes)
  1490. by using Fdate's #dif, #idiv, and #mod functions.  (In the EXAMPLES
  1491. section, see the example that contains FORATIME.BAT.)
  1492.  
  1493. It is also possible to use /T in conjunction with the time compare function
  1494. (/Ftcomp).
  1495.  
  1496. @echo ON
  1497. cls
  1498. rem  Since both /A and /B default to the current date and time,
  1499. rem  and since /T parm overrides the time only for the /A parm ...
  1500.  
  1501. rem   ... during daytime hours, this will always return LT
  1502. Fdate /ftcomp /T00:00:00
  1503. rem   ... during daytime hours, this will always return GT
  1504. Fdate /ftcomp /T23:59:59
  1505.  
  1506.  
  1507. /J: JUSTIFYING OUTPUT
  1508. ==========================
  1509. Using the /J (justify) parameter it is possible to right, center, or left-
  1510. justify FDATE's output.  See the discussion of JUSTIFYING OUTPUT in the
  1511. section on string-handling functions.
  1512.  
  1513.  
  1514.  
  1515. HOW TO PUT FDATE OUTPUT INTO AN ENVIRONMENT VARIABLE
  1516. ====================================================
  1517.  
  1518.  
  1519. CALL A BATCH FILE
  1520. =================
  1521.  
  1522.   The most basic way to put FDATE's output into an environment variable,
  1523.   although not the most convenient, is to:
  1524.   *  use the /P (prefix string) feature to create a DOS "SET" statement,
  1525.   *  redirect the output to a batch file, and then
  1526.   *  CALL the batch file.  
  1527.  
  1528.   Since CALL first appeared in DOS 3.3, you will need DOS 3.3 or greater
  1529.   to use this technique.
  1530.  
  1531.        FDATE /Ff /Atoday /O"mn zd, ccyy" /P"@SET FDATE=" >JUNKTEMP.BAT
  1532.        call JUNKTEMP.BAT
  1533.        del  JUNKTEMP.BAT
  1534.  
  1535.  
  1536.  
  1537. USE AN ENVIRONMENT-MANIPULATION UTILITY
  1538. =======================================
  1539.  
  1540.   There are shareware and public domain utilities that are written
  1541.   specifically to manipulate environment variables, and do that job very
  1542.   well.  FDATE's output can be put into an environment variable by piping
  1543.   it to one of these utilities.  When piping FDATE output to a utility,
  1544.   you can prevent the output from being ECHOed to the screen by
  1545.   redirecting the output to NUL.
  1546.  
  1547.   Of these utilities, I can especially recommend Bob Stephan's GET
  1548.   (because it is very inexpensive and very powerful and flexible) and PC
  1549.   Magazine's STRINGS (free to ZiffNet members).  See the EXAMPLES section
  1550.   for examples of how to use STRINGS and GET to put FDATE's output into an
  1551.   environment variable.
  1552.  
  1553.      As of March 14, 1994, the current version of GET is 2.6.  On
  1554.      CompuServe, use IBMFF to look for GET25.ZIP (which contains version
  1555.      2.5 and the full documentation file) and GET26u.ZIP (the version 2.6
  1556.      update of GET, which contains version 2.6 of GET, but not the full
  1557.      documentation).  Look in CIS:IBMSYS, Library 1, or for GET.ZIP in
  1558.      ZNT:UTILFORUM, lib 16.  GET is also available from the Public Software
  1559.      Library in Houston.
  1560.  
  1561.      As of February 14, 1992, the current version of STRINGS is 1.3. On
  1562.      CompuServe, look for STRING.ZIP in the PC Magazine Utilities Lib of
  1563.      ZNT:UTILFORUM.  STRHYP.ZIP contains good hypertext documentation on
  1564.      STRINGS.
  1565.  
  1566. FDATE'S /V PARAMETER
  1567. ====================
  1568.  
  1569.   Manipulating the environment is an incredibly tricky business.  There
  1570.   are questions of the local versus master environment, the version of DOS
  1571.   you are running, and the environment under which you are running (DOS,
  1572.   Windows, QuarterDeck, Carousel).  In order to keep FDATE focussed on
  1573.   date-related issues, versions of Fdate prior to 6.1 did not attempt to
  1574.   put output directly into an environment variable.  Instead, FDATE's
  1575.   output was written to standard output, that is, it was displayed on the
  1576.   screen. Output could then be redirected to a batch file, or piped to a
  1577.   utility (such as STRINGS or GET), that would put the output into an
  1578.   environment variable.
  1579.  
  1580.   Starting with version 6.1, Fdate supports a /V (environment variable)
  1581.   parameter.  A user can use /V to tell Fdate to put its output directly
  1582.   into an environment variable in the "parent" environment.
  1583.  
  1584.   NOTE that due to the complexities of manipulating the environment, there
  1585.   may be circumstances where /V doesn't work.  These include running FDATE
  1586.   when you have shelled out to DOS from another program, have put the
  1587.   command processor in upper memory (UMB) (see below), are running under
  1588.   Carousel, etc.  In such cases, you may be able to use one of the more
  1589.   basic techniques described above.  For a list of environments in which
  1590.   the /V option has been reported as NOT working, see the next section.
  1591.  
  1592.  
  1593.  
  1594.   /Vevar tells Fdate to put output into an environmental variable whose
  1595.   name is "evar".  For example:
  1596.  
  1597.                 Fdate /Ff /Vdate1
  1598.  
  1599.   will set the environment variable DATE1 to the current date.  If you
  1600.   type SET at the DOS prompt, you should see something like:
  1601.  
  1602.                 DATE1=Friday February 14, 1992
  1603.  
  1604.   If you specify /V without an evar name, the evar name defaults to FDATE.
  1605.  
  1606.      Example :       Fdate /Ff /V
  1607.      produces:       FDATE=Friday February 14, 1992
  1608.  
  1609.   If you do not use /V, Fdate output is written to standard output, i.e.
  1610.   to the screen.
  1611.  
  1612. /V WHEN RUNNING UNDER MICROSOFT WINDOWS
  1613. =======================================
  1614.  
  1615. Starting with FDATE version 8.4 -- thanks to a Turbo Pascal routine from
  1616. the Turbo Professional library (see below) provided by Kim Kokkonen of
  1617. TurboPower Software -- FDATE's /V parameter works even in a Windows DOS
  1618. box, assuming you have enough environment space available.
  1619.  
  1620. The problem is that when you shell out to a DOS box under Windows, the size
  1621. of the DOS environment is normally limited to the amount actually in use by
  1622. DOS at the time when you first started Windows (rounded up to multiples of
  1623. 16).  In short, when you shell out to DOS under Windows, you have little or
  1624. no free environment space left. 
  1625.  
  1626. The trick to giving yourself a decent amount of environment space in a
  1627. Windows DOS box, is to edit SYSTEM.INI and put the following line in the
  1628. [NonWindowsApp] section:
  1629.  
  1630.             [NonWindowsApp]
  1631.             CommandEnvSize=1024
  1632.  
  1633. This tip is from Brian Livingston's "Windows 3.1 Secrets", p. 225. 
  1634. According to Livingston, "This command allocates 1,024 bytes of
  1635. conventional memory to the environment space of each DOS session you start.
  1636. (You can choose any value you want, but it should probably be a multiple of
  1637. 16 bytes...)"
  1638.  
  1639. It's a good idea to be generous here, because the default prompt for a
  1640. Windows DOS box (the one with the highlighted bar across the top of the
  1641. screen) consumes a lot more environment space than the simple "$p$g" of the
  1642. conventional DOS prompt.
  1643.  
  1644. An alternative technique, if you're running Windows 3.0 or earlier, is
  1645. always to start Windows from a batch file that contains the following line,
  1646. executed BEFORE you start Windows:
  1647.  
  1648.    SET DUMMY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  1649.  
  1650. This will reserve a chunk of environment space that will be copied into the
  1651. environment in the Windows DOS box.  Then, as one of the first statements
  1652. in any batch file that you run under Windows, put
  1653.  
  1654.    SET DUMMY=
  1655.  
  1656. This will free up the environment space used by all those "X"s.  
  1657.  
  1658. For a good treatment of running DOS apps under Windows, including a
  1659. discussion of the environment, I recommend Brian Livingston's WINDOWS 3.1
  1660. SECRETS, chapter 7.
  1661.  
  1662. Turbo Professional: "Highly Recommended"
  1663.  
  1664.   Thanks to a Turbo Pascal routine from the Turbo Professional library
  1665.   (provided by Kim Kokkonen of TurboPower Software)  FDATE's /V parameter
  1666.   works even in a Windows DOS box.
  1667.  
  1668.   If you do serious Turbo Pascal programming, you should have Turbo
  1669.   Professional or Object Professional library.  Turbo Professional is a
  1670.   library of about 600 routines to do all sorts of useful stuff in Turbo
  1671.   Pascal programs, including:
  1672.  
  1673.     CRT unit emulation, with many added features 
  1674.     Popup windows, virtual screens, and pulldown menu systems.
  1675.     Full screen data entry with formatting and data validation.
  1676.     Complete mouse support, keyboard macros, runtime error recovery.
  1677.     A context sensitive popup help unit.
  1678.     Units for picking from lists of items, including filenames.
  1679.     Easy and reliable ways to make your program memory resident.
  1680.     Interrupt service routine handlers, extended & expanded memory access.
  1681.     BCD arithmetic, including transcendental functions & the Form routine
  1682.     Sorting and searching.
  1683.     Extensive string manipulation & strings longer than 255 characters.
  1684.     Arrays larger than 64K (in RAM, EMS, or paged to disk)
  1685.  
  1686. For more information, call TurboPower at 1-800-333-4160 (9-5 Mountain
  1687. time), send CompuServe mail to 76004,2611, or visit the CompuServe
  1688. TurboPower forum in PCVENB section 6.
  1689.  
  1690. /V WHEN USING 4DOS, NDOS, AND UMB
  1691. =================================
  1692.     --------------------------------------------------------------
  1693.     I have received the following report from Aran Spence about
  1694.     circumstances in which FDATE /V will not set a variable
  1695.     in the master environment.  This report leads me to believe
  1696.     that FDATE /V may also fail to work with MS-DOS if you put
  1697.     the command processor or the environment in Upper Memory.
  1698.                     Note, however, that this behavior has not been tested
  1699.                     with FDATE 8.4's new environment-handling routines.
  1700.     --------------------------------------------------------------
  1701. Steve,
  1702.  
  1703. There are options with 4DOS and NDOS to load the environment and part
  1704. of the command processor into upper memory blocks.  When one of these
  1705. options is used, FDATE /V can't find the environment and produces the
  1706. message:
  1707.  
  1708.    ERROR
  1709.    @echo ERROR: Master environment not found
  1710.    @pause
  1711.  
  1712. If you have a 4DOS.INI file, it has to contain these lines for FDATE /V
  1713. to work:
  1714.  
  1715.    UMBEnvironment = No
  1716.    UMBLoad = No
  1717.  
  1718. If you have NDOS, the SHELL statement in CONFIG.SYS cannot contain
  1719. any reference to UMB loading via /U (which puts NDOS.COM in UMB), nor
  1720. can it contain a statement of the form:
  1721.                 /E:xxxU
  1722. (which puts xxx bytes of the environment in UMB via the "U" parameter).
  1723.  
  1724. Also, NSTART.BTM or 4START.BTM cannot contain
  1725.          SET NDSHELL=/e+xxxU /U
  1726. in which both U's represent UMB loading of the command processor and the
  1727. environment during secondary shells.
  1728.  
  1729. FDATE'S ERROR HANDLING
  1730. ======================
  1731.  
  1732.    If FDATE detects an error:
  1733.  
  1734.      (1) it will return an errorlevel of 1 (rather than 0), and
  1735.      (2) its output will be 3 lines:
  1736.        * the word ERROR
  1737.        * a DOS batch-file ECHO statement that displays an error message
  1738.        * a DOS batch-file PAUSE statement
  1739.  
  1740.    If Fdate output is displayed directly, or redirected to NUL,
  1741.    you can detect an error by testing the errorlevel for a value of 1.
  1742.  
  1743.    If Fdate output is piped to an environment manipulation utility such
  1744.    as STRINGS or GET, the environment variable will be set to ERROR.
  1745.    Errorlevel will be set by STRINGS/GET, and will probably be 0.
  1746.    In such a case, the only way to detect an error is to test the
  1747.    environment variable for the value ERROR.
  1748.  
  1749.    If FDATE output is redirected to a batch file, which is then
  1750.    CALLed to set an environment variable, the batch file will:
  1751.      * set the environment variable to ERROR,
  1752.      * ECHO the error message, and
  1753.      * pause.
  1754.    You can detect an error by testing errorlevel for the value 1
  1755.    either before or after you CALL the batch file, or 
  1756.    by testing the environment variable for the
  1757.    value ERROR, AFTER you have CALLed the batch file.
  1758.  
  1759. ----------------------------------------------------------------------
  1760.  
  1761.  EXAMPLE:
  1762.    rem use FDATE to check validity of year in parm %1
  1763.    Fdate /Fv /Imm-dd-ccyy /ATT-TT-%1 > nul
  1764.    if errorlevel 1 echo Year parm [%1] is not valid.
  1765.    if errorlevel 1 goto endit
  1766.  
  1767.  EXAMPLE:
  1768.    rem use GET with FDATE, to put FDATE output into into %year%
  1769.    Fdate /Ff /Imm-dd-ccyy /ATT-TT-%1 /Occyy | GET ZE /V%year% >nul
  1770.    if (%year%)==(ERROR) echo Year parm [%1] is not valid.
  1771.    if (%year%)==(ERROR) goto endit
  1772.  
  1773.  EXAMPLE:
  1774.    rem use a batch file with FDATE, to put FDATE output into %year%
  1775.    Fdate /Ff /Imm-dd-ccyy /ATT-TT-%1 /Occyy /P"@set year=">junktemp.bat
  1776.    call junktemp.bat
  1777.    del  junktemp.bat
  1778.    if errorlevel 1 echo Year parm [%1] is not valid.
  1779.    if errorlevel 1 goto endit
  1780.  
  1781. EXAMPLES OF HOW TO USE FDATE
  1782. ============================
  1783.  
  1784. :01 Display Fdate output on screen
  1785. :==================================================================
  1786. FDATE /Ff /At /Od1 /P"Today is "
  1787.  
  1788.  
  1789. :02 Redirect FDATE output to a file
  1790. :==================================================================
  1791. FDATE /Ff /At /Od1 /P"Today is " >FDATE.OUT
  1792.  
  1793.  
  1794. :03 Put FDATE output in an environment variable using a batch file
  1795. :==================================================================
  1796. FDATE /Ff /Atoday /O"mn zd, ccyy" /P"@SET DATE1=" >JUNKTEMP.BAT
  1797. call JUNKTEMP.BAT
  1798. del  JUNKTEMP.BAT
  1799.  
  1800.  
  1801. :04 Put FDATE output in an environment variable using /V parm
  1802. :==================================================================
  1803. FDATE /Ff /Atoday /O"mn zd, ccyy" /Vdate1
  1804.  
  1805.  
  1806. :05 Put FDATE output in an environment variable using STRINGS
  1807. :==================================================================
  1808. FDATE /Ff /Atoday /O"mn zd, ccyy" |STRINGS date1= ASK >NUL
  1809.  
  1810.  
  1811. :06 Put FDATE output in an environment variable using GET
  1812. :==================================================================
  1813. FDATE /Ff /Atoday /O"mn zd, ccyy" |GET ZE /Vdate1 >NUL
  1814.  
  1815.  
  1816. :07 Get user input
  1817. :==================================================================
  1818. @echo off
  1819. cls
  1820. echo Enter a date in mm-dd-ccyy format for validation
  1821.  
  1822. :: get user input
  1823. fdate /fget /vUserDate1
  1824.  
  1825. :: validate user input using /Fv (validate function)
  1826. fdate /fv /A%UserDate1% >nul
  1827. if errorlevel 1 echo Invalid date: %UserDate1%
  1828. if errorlevel 1 goto endit
  1829.  
  1830. :: put your batch file processing here ...
  1831. echo Processing date: %UserDate1%
  1832.  
  1833. :endit
  1834. :: cleanup
  1835. set UserDate1=
  1836.  
  1837.  
  1838. :08 Get a user menu selection
  1839. :==================================================================
  1840. @echo off
  1841. :start
  1842. cls
  1843. echo ===========================================================
  1844. echo             MAKE A MENU SELECTION
  1845. echo ===========================================================
  1846. echo   A   DIR *.*
  1847. echo   B   DIR *.BAT
  1848. echo.
  1849. echo Press ESC to exit
  1850. echo.
  1851. echo ===========================================================
  1852. FDATE /FgetK /Q"Press letter of your choice> " /KABx /V
  1853.  
  1854. if (%FDATE%)==(A) goto Choice_%FDATE%
  1855. if (%FDATE%)==(B) goto Choice_%FDATE%
  1856. if (%FDATE%)==(x) goto endit
  1857. echo Program logic error.   Invalid choice [%FDATE%]
  1858. pause
  1859. goto Start
  1860.  
  1861. :CHOICE_A
  1862.  cls
  1863.  echo Processing choice %FDATE% ...
  1864.  DIR *.* /W /P
  1865.  pause
  1866.  goto Start
  1867.  
  1868. :CHOICE_B
  1869.  echo Processing choice %FDATE% ...
  1870.  DIR *.BAT /W /P
  1871.  pause
  1872.  goto Start
  1873.  
  1874. :endit
  1875. set choice=
  1876. cls
  1877.  
  1878.  
  1879. :10 Change a date from one format into another
  1880. :==================================================================
  1881. :: change date from mm-dd-yy format to ccyymmdd format
  1882. FDATE /Ff /Imm-dd-yy /A05-08-92 /Occyymmdd
  1883.  
  1884.  
  1885.  
  1886. :11 Find the difference in days between two dates
  1887. :==================================================================
  1888. FDATE /Fdif /Imm-dd-ccyy /A%date1% /B%date2% /vdiff
  1889. echo The difference is %diff% days.
  1890.  
  1891.  
  1892. :12 Find the elapsed days/hours/minutes between two date/times.
  1893. :===================================================================
  1894. This batch file was developed in cooperation with Walter Ledge, a sysop for
  1895. CompuServe's CRFORUM.  In addition to being a good example of how to use
  1896. Fdate's /T parm and "#idiv" function, it should be useful for other
  1897. CompuServe sysops who need to submit the same reports that Walt does. 
  1898. Here's Walt's message that started the whole thing.
  1899.  
  1900.   As an assistant sysop on the CRFORUM, I have to submit reports to CIS on
  1901.   the number of messages that are posted on our forum in terms of time per
  1902.   1,000 messages -- i.e., say, I know that 1,000 messages were posted
  1903.   between the hours of 17:05 on July 5 and 3:03 on July 7.  I need to know
  1904.   how many hours and minutes it took for those 1000 messages to be posted. 
  1905.   So I would like some way to use FDATE to calculate the difference
  1906.   between those two times (which, of course, include the dates).
  1907.  
  1908. FORATIM2.BAT is an improvement of the original FORATIME.BAT batch file. 
  1909. FORATIM2.BAT uses the /Fget function, which first appeared in Fdate 8.3, to
  1910. get user input from the terminal, rather than requiring all parameters to
  1911. be entered at the command line as FORATIME.BAT did. 
  1912.  
  1913. @echo off
  1914. cls
  1915. :: ------------------------------------------------------
  1916. :: FORATIM2.BAT batch file
  1917. ::
  1918. :: FUNCTION
  1919. ::    Calculate the elapsed time (in days and minutes)
  1920. ::    between some "begin" date/time and some "end" date/time
  1921. ::
  1922. :: ------------------------------------------------------
  1923. ECHO --------------------------------------------------------------
  1924. ECHO     Calculate elapsed time between two date/times
  1925. ECHO --------------------------------------------------------------
  1926.  
  1927. :BegDate
  1928. Fdate /Fget /VBEGdate /Q"Enter BEGIN DATE (mm-dd-ccyy): "
  1929. if (%BegDate%)==() goto Cleanup
  1930.  
  1931. :BegTime
  1932. Fdate /Fget /VBEGtime /Q"Enter BEGIN TIME (hh:mm).....: "
  1933. if (%BegTime%)==() goto Cleanup
  1934.  
  1935. :: validate date & time
  1936. fdate /fv /A%BEGdate% /T%BEGtime% >nul
  1937. if errorlevel 1 echo Invalid date/time
  1938. if errorlevel 1 goto BegDate
  1939.  
  1940. :: get absolute minute of start date/time.
  1941. fdate /ff /ominute# /A%BEGdate% /T%BEGtime% /VABStime1
  1942. if errorlevel 1 goto BegTime
  1943. fdate /ff /ofull    /A%BEGdate% /T%BEGtime% /Vfull1
  1944. ::
  1945. echo.
  1946. :EndDate
  1947. Fdate /Fget /VENDdate /Q"Enter END.. DATE (mm-dd-ccyy): "
  1948. if (%EndDate%)==() goto Cleanup
  1949.  
  1950. :EndTime
  1951. Fdate /Fget /VENDtime /Q"Enter END.. TIME (hh:mm).....: "
  1952. if (%EndTime%)==() goto Cleanup
  1953.  
  1954. :: validate date & time
  1955. fdate /fv /A%ENDdate% /T%ENDtime% >nul
  1956. if errorlevel 1 echo Invalid date/time
  1957. if errorlevel 1 goto EndDate
  1958.  
  1959. :: get absolute minute of end date/time.
  1960. fdate /ff /ominute# /A%ENDdate% /T%ENDtime% /VABStime2
  1961. if errorlevel 1 goto EndTime
  1962. fdate /ff /ofull    /A%ENDdate% /T%ENDtime% /Vfull2
  1963.  
  1964. echo.
  1965. ECHO Calculating elapsed time...
  1966. :: calculate the difference between ABStime1 and ABStime2
  1967. fdate /f#dif  /A%ABStime1% /B%ABStime2% /VMinutes
  1968.  
  1969. :: calculate the number of hours in it took
  1970. fdate /f#Idiv  /A%minutes% /B60  /VHours
  1971.  
  1972. :: calculate the number of extra minutes it took
  1973. fdate /f#mod   /A%minutes% /B60  /VMins
  1974.  
  1975. echo.
  1976. echo   Between %full1%
  1977. echo       and %full2%
  1978. echo.
  1979. echo   Elapsed time was:
  1980. echo           %hours% hours and %mins% minutes
  1981.  
  1982. fdate /f#Idiv /A%minutes% /B1440 /Vday1
  1983. fdate /f#mod  /A%minutes% /B1440 /Vmin1
  1984. fdate /f#Idiv /A%min1%    /B60   /Vhour1
  1985. fdate /f#mod  /A%min1%    /B60   /Vmin2
  1986. echo   or
  1987. echo         %day1% day(s) %hour1% hour(s) and %min2% minute(s).
  1988. echo.
  1989. echo.
  1990. ::
  1991. :cleanup
  1992. set ENDdate=
  1993. set BEGdate=
  1994. set BEGtime=
  1995. set ENDtime=
  1996. set full1=
  1997. set full2=
  1998. set minutes=
  1999. set ABStime1=
  2000. set ABStime2=
  2001. set day1=
  2002. set hour1=
  2003. set min1=
  2004. set min2=
  2005. set mins=
  2006. set hours=
  2007. :endit
  2008. :13 Find the elapsed years/months/days between two dates.
  2009. :===================================================================
  2010. @echo off
  2011. :: illustrate Fdate's Month# output format
  2012. cls
  2013. echo --------------------------------------------------------------
  2014. echo    YMD_DIF.BAT Calculate elapsed time between two dates
  2015. echo --------------------------------------------------------------
  2016.  
  2017. :: --------------------------------------------------------------
  2018. :D1
  2019. Fdate /Fget /VD1 /Q"Enter date #1 (mm-dd-ccyy), or ENTER to quit: "
  2020. if (%D1%)==() goto Cleanup
  2021.  
  2022. :: validate date
  2023. Fdate /Fv /A%D1%       >nul
  2024. if errorlevel 1 echo Invalid date
  2025. if errorlevel 1 goto D1
  2026.  
  2027. :: translate date into various formats, including absolute month
  2028. Fdate /Ff /oMonth# /A%D1% /VAbsMonth1
  2029. Fdate /Ff /oday#   /A%D1% /VAbsDay1
  2030. Fdate /Ff /A%D1%   /VFull1
  2031. Fdate /Ff /odd     /A%D1% /VDd1
  2032.  
  2033. :: --------------------------------------------------------------
  2034. :D2
  2035. Fdate /Fget /VD2 /Q"Enter date #2 (mm-dd-ccyy), or ENTER to quit: "
  2036. echo.
  2037. if (%D2%)==() goto Cleanup
  2038.  
  2039. :: validate date
  2040. Fdate /Fv /A%D2% >nul
  2041. if errorlevel 1 echo Invalid date
  2042. if errorlevel 1 goto D2
  2043.  
  2044. :: translate date
  2045. Fdate /Ff /oMonth# /A%D2% /VAbsMonth2
  2046. Fdate /Ff /oday#   /A%D2% /VAbsDay2
  2047. Fdate /Ff /A%D2%   /VFull2
  2048. Fdate /Ff /odd     /A%D2% /VDd2
  2049.  
  2050. :: --------------------------------------------------------------
  2051. :: verify that D2 is later than D1
  2052. Fdate /Fcomp /A%D2% /B%D1% /v
  2053. if (%Fdate%)==(GT) goto EndIf1
  2054.    echo     D2 must be later than D1.        Please try again.
  2055.    echo.
  2056.    goto D1
  2057. :EndIf1
  2058.  
  2059. :: verify that D2 is in a later month than D1
  2060. Fdate /F#comp /A%AbsMonth2% /B%Absmonth1% /v
  2061. if (%Fdate%)==(GT) goto EndIf2
  2062.    :: they are in the same month
  2063.    Fdate /Fdif /A%D1% /B%D2% /P"Difference is " /S" days."
  2064.    echo.
  2065.    goto Cleanup
  2066. :EndIf2
  2067.  
  2068. :: --------------------------------------------------------------
  2069. :: get difference in months
  2070. Fdate /F#dif /A%AbsMonth2% /B%Absmonth1% /vMonthsDif
  2071.  
  2072. :: compare days of month
  2073. Fdate /F#comp /A%Dd2% /B%Dd1% /v
  2074. if not (%Fdate%)==(LT) goto EndIf3
  2075.    :: Dd2 is less than Dd1 ... subtract 1 from (add -1 to) MonthsDif
  2076.    Fdate /F#add  /A%MonthsDif% /B-1 /VMonthsDif
  2077. :EndIf3
  2078.  
  2079.  
  2080. :: do month arithmetic, to get a date (D3) that is
  2081. :: less than 1 month prior to D2
  2082. Fdate /Fm /A%D1% /N%MonthsDif% /Omm-dd-ccyy /VD3
  2083.  
  2084. :: find difference in days between D3 & D2
  2085. Fdate /Fdif /A%D3% /B%D2% /Vdaysdif
  2086.  
  2087. :: --------------------------------------------------------------
  2088. echo Between %Full1% & %Full2% ...
  2089. echo                 %MonthsDif% month(s) %DaysDif% day(s)
  2090.  
  2091. :: calculate the number of years, by dividing MonthsDif by 12
  2092. Fdate /F#Idiv  /A%Monthsdif% /B12  /VYearsDif
  2093.  
  2094. :: calculate the number of extra months
  2095. Fdate /F#mod   /A%MonthsDif% /B12  /VMonthsDif
  2096.  
  2097. echo  or   %YearsDif% year(s) %MonthsDif% month(s) %DaysDif% day(s)
  2098.  
  2099. :: --------------------------------------------------------------
  2100. :cleanup
  2101. echo.
  2102. echo.
  2103. set D1=
  2104. set D2=
  2105. set D3=
  2106. set AbsMonth1=
  2107. set AbsMonth2=
  2108. set AbsDay1=
  2109. set AbsDay2=
  2110. set Full1=
  2111. set Full2=
  2112. set Dd1=
  2113. set Dd2=
  2114. set YearsDif=
  2115. set MonthsDif=
  2116. set DaysDif=
  2117. set Fdate=
  2118. :endit
  2119.  
  2120.  
  2121. :14 Determine how long it took a program to run
  2122. :==================================================================
  2123.  
  2124. @echo off
  2125. cls
  2126. ECHO ─────────────────────────────────────────────────────────────────────
  2127. ECHO       DETERMINE HOW LONG IT TOOK A PROGRAM TO RUN
  2128. ECHO           The demo will run for 1 - 60 seconds.
  2129. ECHO ──────────────────────────────────────────────────────────────────────
  2130. PAUSE
  2131. cls
  2132. :: Get the time (in julian seconds) that the program began running
  2133. set PgmName=DemoFake_Pgm
  2134. FDATE /Ff /Osecond# /VBegS
  2135. FDATE /Ff /Ohh:mm:ss /P"%PgmName% execution begins at "
  2136.  
  2137. :: ───────── DEMO BEGIN ──────────────────────────────────────────
  2138. :: For purposes of this demo, we simulate execution of a
  2139. :: program by looping until the minute changes.  In your real
  2140. :: batch file, you would put your program statements here.
  2141. :: ───────────────────────────────────────────────────────────────
  2142. FDATE /Ff /Ohhmm /vBegM
  2143. :BegLoop
  2144.    rem  Since this is a demo, give the folks something to watch
  2145.    FDATE /Ff    /Osecond# /vSeconds
  2146.    FDATE /F#dif /A%Seconds% /B%BegS% /P".... elapsed time: " /S" seconds."
  2147.    FDATE /Ff  /Ohhmm     /vNowM
  2148. if (%NowM%)==(%BegM%) goto BegLoop
  2149. set BegM=
  2150. set NowM=
  2151. :: ───────── DEMO END   ──────────────────────────────────────────
  2152.  
  2153. :: Get the time (in julian seconds) that the program finished
  2154. FDATE /Ff  /Osecond# /vEndS
  2155. :: tell the user the time that the program finished
  2156. FDATE /Ff  /Ohh:mm:ss /P"%PgmName% execution ends at "
  2157.  
  2158. :: calculate run time (difference between start time and end time)
  2159. FDATE /F#dif /A%EndS% /B%BegS% /vSeconds
  2160. :: convert  seconds to  minutes + seconds  format
  2161. FDATE /F#idiv /A%Seconds% /B60 /vMinutes
  2162. FDATE /F#mod  /A%Seconds% /B60 /vMinSecs
  2163.  
  2164. :: tell the user how long the program took to run
  2165. echo Runtime: %Seconds% seconds (%Minutes% minutes %MinSecs% seconds)
  2166. :: cleanup            
  2167. set PgmName=
  2168. set BegS=
  2169. set EndS=
  2170. set Seconds=
  2171. set Minutes=
  2172. set MinSecs=
  2173.  
  2174. :15 Find years when a given date fell on a given day of the week
  2175. :==================================================================
  2176. [WHATDAY.BAT  This program has virtually no data validation, but if you are
  2177. careful to enter valid input data, it does the job.] 
  2178.  
  2179.  @echo off
  2180.  :: ----------------------------------------------------------------
  2181.  :: This program calculates the years (within a specified range) that a
  2182.  :: certain day of a certain month fell on a certain day of the week.
  2183.  ::
  2184.  :: Note that we calculate and test both the day of the week and the
  2185.  :: month.  This is because, for example, "February 29" of
  2186.  :: a non-leapyear (an invalid date)
  2187.  :: will be converted to the valid date of March 1.
  2188.  :: So we want to be sure that in a given year, February 29 not only
  2189.  :: occurred on the weekday in question, but also actually
  2190.  :: occurred in February.
  2191.  :: ----------------------------------------------------------------
  2192.  cls
  2193.  echo This program calculates the years (within a specified range) that a
  2194.  echo certain day of a certain month fell on a certain day of the week.
  2195.  echo.
  2196.  echo Please enter the day of the week that you want to search for.
  2197.  echo   1 = Sunday
  2198.  echo   2 = Monday
  2199.  echo   3 = Tuesday
  2200.  echo   4 = Wednesday
  2201.  echo   5 = Thursday
  2202.  echo   6 = Friday
  2203.  echo   7 = Saturday
  2204.  echo.
  2205.  fdate /fgetk /K1234567x /Q"Please press a number, or ESC to exit > " /vdow
  2206.  if (%Dow%)==(x) goto endit
  2207.  if (%Dow%)==(1) set DowName=Sunday
  2208.  if (%Dow%)==(2) set DowName=Monday
  2209.  if (%Dow%)==(3) set DowName=Tuesday
  2210.  if (%Dow%)==(4) set DowName=Wednesday
  2211.  if (%Dow%)==(5) set DowName=Thursday
  2212.  if (%Dow%)==(6) set DowName=Friday
  2213.  if (%Dow%)==(7) set DowName=Saturday
  2214.  echo You chose day of the week: %dowName%
  2215.  pause
  2216.  
  2217.  fdate /fget /Q"Please enter first year in year range > " /vBegYr
  2218.  fdate /fget /Q"Please enter last_ year in year range > " /vEndYr
  2219.  fdate /fget /Q"Please enter month number (1-12) > " /vMonNum
  2220.  fdate /fget /Q"Please enter day__ number (1-31) > " /vDayNum
  2221.  
  2222.  set Yr=%BegYr%
  2223.  fdate /fsubstr /a-2 /q00%MonNum% /vMonNum
  2224.  
  2225.  rem >whatday.txt
  2226.  cls
  2227.  echo Looking for %MonNum%/%DayNum% on %DowName%
  2228.  echo between %BegYr% and %EndYr%
  2229.  echo ----------------------------------------------
  2230.  echo Looking for %MonNum%/%DayNum% on %DowName% >>whatday.txt
  2231.  echo between %BegYr% and %EndYr% >>whatday.txt
  2232.  echo ---------------------------------------------- >>whatday.txt
  2233.  
  2234.  :LoopTop
  2235.    fdate /fsubstr /a-4 /q0000%yr% /vyr
  2236.    echo Testing %yr%
  2237.    fdate /ff /Idd-mm-ccyy /A%DayNum%-%MonNum%-%Yr% /v
  2238.    fdate /ff /Idd-mm-ccyy /A%DayNum%-%MonNum%-%Yr% /odow# /vdow#
  2239.    fdate /ff /Idd-mm-ccyy /A%DayNum%-%MonNum%-%Yr% /omm   /vmm
  2240.  
  2241.    if (%Dow#%)==(%Dow%) if (%MonNum%)==(%mm%) echo %fdate%
  2242.    if (%Dow#%)==(%Dow%) if (%MonNum%)==(%mm%) echo %fdate% >>Whatday.txt
  2243.  
  2244.    fdate /f#add  /A%yr% /B1 /vYr
  2245.    fdate /f#comp /A%yr% /B%EndYr% /v
  2246.    if (%fdate%)==(GT) goto LoopEnd
  2247.    goto LoopTop
  2248.  :LoopEnd
  2249.  
  2250.  cls
  2251.  type whatday.txt
  2252.  echo.
  2253.  echo This data has been written to file: Whatday.txt
  2254.  echo.
  2255.  :endit
  2256.  set Yr=
  2257.  set BegYr=
  2258.  set EndYr=
  2259.  set mm=
  2260.  set Dow=
  2261.  set Dow#=
  2262.  set DowName=
  2263.  set fdate=
  2264.  set MonNum=
  2265.  set DayNum=
  2266.  
  2267. :16 Find calendar date corresponding to a "business Julian" date
  2268. :==================================================================
  2269. rem business julian date is 1992:045.  Note input format CCYYjjj
  2270. FDATE /Ff /A1992045  /Iccyyjjj  /Od1
  2271.  
  2272. rem You don't need to left-zero-fill the day
  2273. FDATE /Ff /A199245  /Iccyyjjj  /Od1
  2274.  
  2275. rem You can assume the century, if you specify the YYjjj input format
  2276. FDATE /Ff /A9245  /Iyyjjj  /Od1
  2277.  
  2278. :17 Set your PC's date to a business julian date
  2279. :==================================================================
  2280. @echo off
  2281. goto enddoc
  2282. ---------------------------------------------------------------------
  2283. This batch file was created by Aran Spence [CIS: 70162,3044].  Its
  2284. function is to emulate the DOS DATE command, but allow the user to set
  2285. the date using a business julian date format (yyjjj) instead of
  2286. mm-dd-yy.
  2287.  
  2288. Note the format is YYjjj. This is the BUSINESS julian date: a date
  2289. expressed as the number of days from the beginning of the year,
  2290. when January 1 is day 1.
  2291.  
  2292.            date      BUSINESS julian date
  2293.        -----------   --------------------
  2294.        Jan 5, 1992       92005
  2295.        Jan 5, 1993       93005
  2296.        Dec 31, 1993      93365  [Dec 31 is 365th day of year 1993]
  2297.  
  2298. As Aran originally wrote it, the user-prompt was virtually identical to
  2299. that of the DATE command.  I have modified his original version, so it
  2300. now looks less like the DATE command but displays a bit more
  2301. information, and so it can operate from the command line.
  2302.  
  2303. If the user enters a business julian date as a command-line
  2304. parameter, JDATE resets the date to that julian date.
  2305.              EXAMPLE:  JDATE 92005
  2306. If there is no input parameter, /fget is used to prompt the user for a
  2307. date.
  2308.  
  2309. Note that the user must enter both of the year digits (yy),
  2310. but may enter an abbreviated set of day digits (jjj).  That is,
  2311. for julian day 92005, the user is permitted to enter 925.
  2312.  
  2313. One handy use for JDATE is simply to find out what the current
  2314. business julian date is.
  2315. ---------------------------------------------------------------------
  2316. :enddoc
  2317.  
  2318. SET NewJD=%1
  2319. if not (%NewJD%)==() goto GotDate
  2320.  
  2321. :ShowDate
  2322. Fdate /Ff /Od1    /P"Current Gregorian date: "
  2323. Fdate /Ff /Oyyjjj /P"'Business Julian' date: "
  2324.  
  2325. :GetDate
  2326. GET S "Enter new date (yyddd): " /VNewJD /L
  2327. if (%NewJD%)==() goto endit
  2328.  
  2329. :GotDate
  2330. Fdate /Ff /A%NewJD% /Omm-dd-yy /Iyyjjj /VNewGD
  2331. if errorlevel 1 echo Invalid date "%NewJD%"
  2332. if errorlevel 1 goto GetDate
  2333.  
  2334. ::   reset the date
  2335. DATE %NewGD%
  2336.  
  2337. echo SYSTEM DATE HAS BEEN RESET
  2338. Fdate /Ff /Od1    /P"Current Gregorian date: "
  2339. Fdate /Ff /Oyyjjj /P"'Business Julian' date: "
  2340.  
  2341. :endit
  2342. SET NewJD=
  2343. SET NewGD=
  2344. echo.
  2345.  
  2346. :18 Determine if parm %1 contains a valid date
  2347. :==================================================================
  2348. COMMENT
  2349.   Note that we throw away the FDATE output by redirecting it to NUL.  All
  2350.   we really want here is the errorlevel, which tells us whether or not the
  2351.   string in %1 is a valid year.
  2352.  
  2353. Fdate /Fv /Imm-dd-ccyy /A%1  >nul
  2354. if errorlevel 1 echo Parm 1 was not a valid date: %1
  2355. if errorlevel 1 goto endit
  2356.  
  2357. ::
  2358. :: Put the body of your batch file here.
  2359. ::
  2360.  
  2361. :endit
  2362.  
  2363.  
  2364.  
  2365. :19 "Roll your own" date format 
  2366. :==================================================================
  2367. @echo of
  2368. cls
  2369. :: EXAMPLE A: create a date in the format of the DOS "date" command
  2370. :: format, followed by the DOS "time" command format
  2371.  
  2372. :: get the three-character day-of-week name
  2373. Fdate /Ff /Odow3 /Vx
  2374.  
  2375. :: add mm-dd-ccyy to it
  2376. Fdate /Ff /Omm-dd-ccyy /p"%x% " /Vx
  2377.  
  2378. :: add the DOS "time" format (new output format in Fdate 8.6)
  2379. Fdate /Ff /Otdos       /p"%x% " /Vx
  2380. echo Date/time = %x%
  2381.  
  2382. :: EXAMPLE B: create a date in custom-made format: yymn3dd
  2383. Fdate /Ff /Oyy          /Vx
  2384. Fdate /Ff /Omn3 /P"%x%" /Vx
  2385. Fdate /Ff /Odd  /P"%x%" /Vx
  2386. echo Today is %x%
  2387.  
  2388. :: EXAMPLE C: create a date with day and month date-parts right justified
  2389. ::            and padded with spaces, such as " 1- 1-1995" for Jan 1, 1995
  2390. fdate /ff /ozd   /j"R 2" /vzd
  2391. fdate /ff /ozm   /j"R 2" /vzm
  2392. fdate /ff /occyy /p"%zd%-%zm%-"  /v
  2393. echo Today is [%fdate%]
  2394.  
  2395. :20 Find the 4th Thursday in November (Thanksgiving)
  2396. :==================================================================
  2397. Fdate /Fw /D5 /N4 /A11-01-%year% /Imm-dd-ccyy /Od1 /P"Thanksgiving: "
  2398.  
  2399.  
  2400. :22 On a date, show what anniversary it is for some event
  2401. :==================================================================
  2402. See HOLIDAYS.BAT demo batch file
  2403.  
  2404.  
  2405. :23 Show a list of holidays in a given year
  2406. :==================================================================
  2407. See HOLIDAYS.BAT demo batch file
  2408.  
  2409.  
  2410. :24 Show a list of Federal holidays in a given year
  2411. :==================================================================
  2412. See HOLIFEDS.BAT demo batch file
  2413.  
  2414. :25 Determine if a year is valid, and evenly divisible by 4
  2415. :==================================================================
  2416.  
  2417. @echo off
  2418. cls
  2419. echo FUNCTION: Accept a year parm (CCYY) as parameter 1.  Determine if
  2420. echo the year is an election or inauguration year in the United States.
  2421. echo ===================================================================
  2422.  
  2423. rem verify %1 is a valid year
  2424. Fdate /Fv /Imm-dd-ccyy /A01-01-%1 >nul
  2425. if errorlevel 1 echo Year parm [%1] is not valid.
  2426. if errorlevel 1 goto endit
  2427.  
  2428. Fdate /Ff /Imm-dd-ccyy /A01-01-%1 /p"@set year=">junktemp.bat
  2429. call junktemp.bat
  2430.  
  2431. Fdate /F#mod /A%1 /B4 /p"@set mod=">junktemp.bat
  2432. call junktemp.bat
  2433. if (%mod%)==(0) echo %1 is an American presidential election year.
  2434. if (%mod%)==(1) echo %1 is an American presidential inauguration year.
  2435. for %%v in (2 3) do if (%mod%)==(%%v) echo %1 is not an election year.
  2436. for %%v in (2 3) do if (%mod%)==(%%v) echo %1 is not an inauguration year.
  2437.  
  2438. set mod=
  2439. :endit
  2440. if exist junktemp.bat del  junktemp.bat
  2441.  
  2442.  
  2443.  
  2444.  
  2445. :30 Compare a file's date to today's date
  2446. :==================================================================
  2447. rem Compare today's date to the date on the filename in %1
  2448. Fdate /Fcomp /At /If /B%1 /Vcomp
  2449. if (%comp%)==(EQ) echo %1 was created or updated today
  2450. set comp=
  2451.  
  2452.  
  2453. :31 Compare two files' date/time using COMPARE-FUNCTION ERRORLEVELS
  2454. :==================================================================
  2455. COMMENT
  2456. There are many ways to check errorlevels.  This example shows 
  2457. several of them.
  2458.  
  2459. @echo off
  2460. cls
  2461. SET F1=FDATE.BAT
  2462. SET F2=FDATE.EXE
  2463. fdate /FTcomp /If /A%f1%  /B%F2% /P"%f1% is " /S" %f2%"
  2464.  
  2465. if errorlevel 101 if not errorlevel 103 echo %f1% is LT/EQ %f2%
  2466. if errorlevel 102                       echo %f1% is GT/EQ %f2%
  2467.  
  2468. if errorlevel 101 if not errorlevel 102 echo %f1% is older than %f2%
  2469. if errorlevel 102 if not errorlevel 103 echo %f1% is same age as %f2%
  2470. if errorlevel 103 if not errorlevel 104 echo %f1% is younger than %f2%
  2471.  
  2472. if errorlevel 101 if not errorlevel 103 echo %f1% at least as old as %f2%
  2473. if errorlevel 102                       echo %f1% is no older than %f2%
  2474.  
  2475. if errorlevel 101 if not errorlevel 102 echo errorlevel is 101
  2476. if errorlevel 102 if not errorlevel 103 echo errorlevel is 102
  2477. if errorlevel 103 if not errorlevel 104 echo errorlevel is 103
  2478. SET F1=
  2479. SET F2=
  2480. :endit
  2481.  
  2482.  
  2483.  
  2484. :32 Display a list of all files that were created/updated today. 
  2485. :==================================================================
  2486. @echo off
  2487. if (%1)==(SUBROUTINE) goto %2
  2488.  
  2489. CLS
  2490. ECHO FILES MEETING FILESPEC [%1] THAT WERE CREATED OR UPDATED TODAY
  2491. REM  The batch file calls itself: Its own name is in parm %0
  2492. for %%v in (%1) do  CALL %0 SUBROUTINE CHECKFILE %%v
  2493.  
  2494. set comp=
  2495. goto endit
  2496.  
  2497. :CHECKFILE
  2498. shift
  2499. shift
  2500.  
  2501. rem Compare today's date to the date on the %1 file
  2502. Fdate /Fcomp /If /A%1 /Vcomp  
  2503.  
  2504. rem echo the filename if the file was created/updated today
  2505. if (%comp%)==(EQ) echo %1
  2506. :endit
  2507.  
  2508. :33 Delete files more than X days old (use a batch-file subroutine)
  2509. :==================================================================
  2510. See the COMMENTARY that follows the text of the batch file.
  2511.  
  2512.  
  2513. @echo off
  2514. if (%1)==(SUBROUTINE) goto %2
  2515. cls
  2516.  
  2517. goto EndDoc
  2518. ----------------------------------------------------------------------
  2519. OLDFILES.BAT
  2520. This batch file shows how to do work on files that are older than
  2521. %NumDays%.  The PROCESS! subroutine can be modified to do any kind of
  2522. work you want.
  2523. ----------------------------------------------------------------------
  2524. :EndDoc
  2525.  
  2526. :: set the number of days in the past.   if this value is not passed
  2527. :: in via parameter %1, it defaults to 3 days
  2528. set NumDays=%1
  2529. if (%NumDays%)==() SET NumDays=3
  2530.  
  2531.  
  2532. echo ------------------------------------------------------------------
  2533. echo           PROCESSING FILES CREATED MORE THAN %NumDays% DAYS AGO
  2534. echo ------------------------------------------------------------------
  2535. for %%v in (*.*) do  CALL %0 SUBROUTINE PROCESS! %%v
  2536. echo ------------------------------------------------------------------
  2537. echo           END OF PROCESSING
  2538. echo ------------------------------------------------------------------
  2539.  
  2540. :: CLEANUP
  2541. set NumDays=
  2542. set DaysOld=
  2543. set Comparison=
  2544. GOTO ENDIT
  2545.  
  2546. :
  2547. :PROCESS!
  2548. shift
  2549. shift
  2550.  
  2551. :: get difference in days between filedate and today.
  2552. :: Note that /B parm (which is omitted) defaults to today's date.
  2553. fdate /fdif   /A%1        /IF          /VDaysOld
  2554.  
  2555. :: compare DaysOld to NumDays
  2556. fdate /f#comp /A%DaysOld% /B%NumDays%  /Vcomparison
  2557.  
  2558. :: the following line will DISPLAY THE NAME AND AGE OF
  2559. :: any file for which %DaysOld% is greater than %NumDays%
  2560. :: --------------------------------------------------------------
  2561. if (%comparison%)==(GT) echo %1 is %DaysOld% days old.
  2562.  
  2563. :: EXAMPLE (to activate this routine, remove the REM from column 1)
  2564. :: the following line will COPY TO AN ARCHIVE SUBDIRECTORY
  2565. :: any file for which %DaysOld% is greater than %NumDays%
  2566. :: -----------------------------------------------
  2567. REM if (%comparison%)==(GT) COPY %1 C:\ARCHIVE\*.*
  2568.  
  2569. :: EXAMPLE (to activate this routine, remove the REM from column 1)
  2570. :: the following line will DELETE
  2571. :: any file for which %DaysOld% is greater than %NumDays%
  2572. :: -----------------------------------------------
  2573. REM if (%comparison%)==(GT) DEL %1
  2574.  
  2575. :: fall through to endit
  2576.  
  2577. :endit
  2578.  
  2579.  ===============================================================
  2580.                         COMMENTARY BEGIN
  2581.  ===============================================================
  2582.  This batch file uses a crude, but effective, technique for giving a
  2583.  batch file the ability to call subroutines.  If you've never seen
  2584.  something like this before, it is sort of mind-blowing.  Here's some
  2585.  commentary on the more important lines involved in the technique.
  2586.  ===============================================================
  2587.  
  2588.  if (%1)==(SUBROUTINE) goto %2
  2589.  
  2590.     COMMENTARY:
  2591.     If the first parameter, %1, is "SUBROUTINE", then the batch file
  2592.     recognizes that it is being called for the purpose of executing
  2593.     one of its own subroutines.  In such a case, it does a GOTO to the
  2594.     start of the requested subroutine.  That is, it goes to the label
  2595.     whose name is in the second parameter.
  2596.  
  2597.     Explicitly specifying the name of the desired subroutine permits
  2598.     permits us to have multiple subroutines in the batch file,
  2599.     each with its own name.  (As it happens, in this batch file
  2600.     we have only one subroutine, named "PROCESS!")
  2601.  
  2602.     If the first parameter is not "SUBROUTINE", then we fall through
  2603.     and begin executing the main routine of the batch file.  In such a
  2604.     case, the first parameter (%1) may contain a number, indicating
  2605.     the number of days to use in determining which files to delete.
  2606.  
  2607.     Note that this technique will make the batch file malfunction
  2608.     if the user himself ever executes the batch file from the
  2609.     DOS command line with the word "SUBROUTINE" as the first
  2610.     parameter, the word "PROCESS!" as the second parameter, and a
  2611.     third parameter that is missing or not a valid filename.
  2612.     This is so unlikely, however, that it is reasonable
  2613.     to assume that it will never happen.
  2614.  
  2615.  ===============================================================
  2616.  
  2617.  for %%v in (*.*) do  CALL %0 SUBROUTINE PROCESS! %%v
  2618.  
  2619.     COMMENTARY:
  2620.     In a batch file, %0 contains the name by which the batch file was
  2621.     invoked.  We use this fact to allow a batch file to call itself,
  2622.     regardless of what name the user has given to it.
  2623.  
  2624.     The first parameter passed, when the batch file calls
  2625.     itself, is the string "SUBROUTINE".  This string allows the batch
  2626.     file to recognize when it is being called for the purpose of
  2627.     executing one of its own subroutines.
  2628.  
  2629.     The second parameter is the name of the subroutine that we want
  2630.     to call: in this case, "PROCESS!".
  2631.  
  2632.     The third parameter is what we would normally think of as the first
  2633.     parameter to the subroutine.  In this case, when the
  2634.     FOR statement is executed, and the substitution for %%v takes
  2635.     place, it will contain the name of the file to be processed.
  2636.     Note that we could, if we wished, pass additional parameters to
  2637.     the subroutine.  Note also that we can control the files that
  2638.     we process.  We do so via the filemask in the FOR statement.
  2639.     It we used, for example, "*.EXE", then we would process only
  2640.     executable files.
  2641.  
  2642.  ===============================================================
  2643.  
  2644.  GOTO ENDIT
  2645.  
  2646.    COMMENTARY:
  2647.    When the mainline of the batch file is finished executing, we
  2648.    goto the end of the batch file.  We MUST do this GOTO in order
  2649.    to avoid falling through into, and starting to execute, the first
  2650.    of the batch file's subroutines.
  2651.  
  2652.  ===============================================================
  2653.  
  2654.  :PROCESS!
  2655.  shift
  2656.  shift
  2657.  
  2658.    COMMENTARY:
  2659.    Note that when the batch file is called as a subroutine, and the
  2660.    batch file goes to the PROCESS! label, the values of the parms are:
  2661.            %0 = [the name of the batch file]
  2662.            %1 = SUBROUTINE
  2663.            %2 = PROCESS!
  2664.            %3 = [name of the file to be processed]
  2665.  
  2666.     We shift all the parameters to the left twice, to move the
  2667.     parameter(s) into what we think of as the
  2668.     proper places for parameters to the subroutine.
  2669.  
  2670.     After the first SHIFT command:
  2671.            %0 = SUBROUTINE
  2672.            %1 = PROCESS!
  2673.            %2 = [name of the file to be processed]
  2674.  
  2675.     After the second SHIFT command:
  2676.            %0 = PROCESS!
  2677.            %1 = [name of the file to be processed]
  2678.  
  2679.     Now %1 contains what we think of as the proper parameter(s)
  2680.     to the subroutine.  In this case, %1 contains the filename that
  2681.     we want the subroutine to process.
  2682.  
  2683.     At the end of every subroutine, there should be a GOTO ENDIT,
  2684.     which causes the batch file to go to its own end, and then
  2685.     end and return control to the statement in the program which called
  2686.     it.  (This is, of course, the CALL statement embedded in the
  2687.     FOR statement.)
  2688.  
  2689.     We can optimize the batch file a little by omitting the "goto endit"
  2690.     at the end of the last subroutine.  Instead, we simply allow the
  2691.     last subroutine to fall through to the end of the batch file.
  2692.  
  2693.  ===============================================================
  2694.                          COMMENTARY END
  2695.  ===============================================================
  2696.  
  2697. :34 Get date to tell PKZIP to compress files older than 30 days
  2698. :======================================================================
  2699. PKZIP (a popular file-compression utility) can be used to compress and
  2700. archive files that are older/younger than a given date.  To run PKZIP on
  2701. files that are, for example, older than 30 days, we need the date that was
  2702. 30 days before today's date.  To get it, we use Fdate to subtract 30 days
  2703. from today's date, and put that date out in PKZIP's "American" format
  2704. (MMDDYY). (Fdate also supports PKZIP's Japanese and European formats.)
  2705.  
  2706. To compress all files that were created before a date 30 days ago:
  2707.  
  2708.      Fdate /Fsub /N30 /Ommddyy /VArchiveDate
  2709.      pkzip test.zip -T%ArchiveDate%
  2710.  
  2711. For more information, see PKZIP's MANUAL.DOC file.
  2712.  
  2713. :40 Loop through an array of environment variables
  2714. :======================================================================
  2715. @echo off
  2716. cls
  2717. SET pct=%%%
  2718. SET prefix=Address
  2719.  
  2720. ECHO LOADING AN ARRAY
  2721. SET subscript=1
  2722. SET %prefix%.%subscript%=Stephen Ferg
  2723. SET subscript=2
  2724. SET %prefix%.%subscript%=5113 N. 8th Road
  2725. SET subscript=3
  2726. SET %prefix%.%subscript%=Arlington, VA 22205
  2727.  
  2728. ECHO UNLOADING AND DISPLAYING THE ARRAY
  2729. SET subscript=1
  2730. :LoopTop
  2731. REM do while subscript less than/equal 3
  2732. if %subscript%==4 goto LoopEnd
  2733.  
  2734.    REM put value of subscripted variable into tempvar
  2735.    ECHO SET tempvar=%pct%%prefix%.%subscript%%pct%>JUNKTEMP.BAT
  2736.    CALL JUNKTEMP.BAT
  2737.  
  2738.    REM display value of subscripted variable
  2739.    ECHO %prefix%.%subscript% is: %tempvar%
  2740.  
  2741.    REM delete subscripted variable
  2742.    SET %prefix%.%subscript%=
  2743.  
  2744.    REM increment the loop variable
  2745.    Fdate /F#add /A%subscript% /B1 /Vsubscript
  2746.    goto LoopTop
  2747. :LoopEnd
  2748.  
  2749. SET pct=
  2750. SET tempvar=
  2751. SET prefix=
  2752. SET subscript=
  2753. DEL JUNKTEMP.BAT
  2754.  
  2755. :44 Do something on the last day (or last Friday) of the month
  2756. :==================================================================
  2757. COMMENT
  2758. We often need batch files that do some special task on the last day of the
  2759. month: run a backup job, display a reminder message, etc.  This example
  2760. batch file, LASTDAY.BAT, simply displays a message -- you can modify it to
  2761. do whatever it is that YOU want to do.
  2762.  
  2763. If you plan to run LASTDAY.BAT at work, and you work Monday through Friday,
  2764. then checking for the last day of the month would be a poor strategy --
  2765. after you leave work on a Friday, the last day of the month might occur on
  2766. the following Saturday or Sunday.   So I've included a check to see if the
  2767. Friday is the last working day of the month.  If you don't want that
  2768. functionality, deleting the lines between the first and last occurrence of
  2769. the string "EndCheck" will remove it.
  2770. =======================================================================
  2771.  @echo off
  2772.  REM ---------------------------------------------------------------
  2773.  REM check to see if today is the last day of the month
  2774.  REM ---------------------------------------------------------------
  2775.  REM get today's month
  2776.  fdate /ff        /omm /vmmtoday
  2777.  
  2778.  REM get tomorrow's month
  2779.  fdate /fadd /n1 /omm  /vmmtomorrow
  2780.  
  2781.  REM if tomorrow occurs in a different month,
  2782.  REM then today is the last day of this month
  2783.  if not (%mmtoday%)==(%mmtomorrow%) echo LAST DAY OF THE MONTH
  2784.  if not (%mmtoday%)==(%mmtomorrow%) goto EndCheck
  2785.  
  2786.  REM -------------------------------------------------------------
  2787.  REM check to see if today is the last Friday of the month
  2788.  REM -------------------------------------------------------------
  2789.  rem get today's day of the week, to see if it is Friday
  2790.  fdate /ff /odow3 /vdow3
  2791.  if not (%dow3%)==(Fri) goto EndCheck
  2792.  
  2793.  REM today is Friday.  Get next Monday's month
  2794.  fdate /fadd /n3 /omm  /vmmMonday
  2795.  
  2796.  REM if next Monday occurs in a different month,
  2797.  REM then today is the last Friday of this month
  2798.  if not (%mmtoday%)==(%mmMonday%) echo LAST WORKING DAY OF THE MONTH
  2799.  
  2800.  :EndCheck
  2801.  
  2802.  REM cleanup
  2803.  set dow3=
  2804.  set mmtoday=
  2805.  set mmtomorrow=
  2806.  set mmMonday=
  2807.  
  2808. :45 Get information about the month prior to the current month
  2809. :==================================================================
  2810. COMMENT
  2811. When running a monthly backup job at the beginning of the month, one often
  2812. needs to identify the previous month, or the last day of the previous
  2813. month.  Here's how to use Fdate to obtain that sort of information. 
  2814. Basically, we subtract one day from the first day of the current month,
  2815. giving us the last day of the previous month.
  2816. =======================================================================
  2817. @echo off
  2818. cls
  2819. : The simplest way to get information about last month is to subtract
  2820. : 1 day from the first day of this month ...
  2821.  
  2822. fdate /fsub /n1 /att-01-tttt /omm   /p"Last month was.................: "
  2823. fdate /fsub /n1 /att-01-tttt /occyy /p"Last month occurred in the year: "
  2824. fdate /fsub /n1 /att-01-tttt /odd   /p"The last day of last month was : "
  2825. fdate /fsub /n1 /att-01-tttt /od1   /p"The last day of last month was : "
  2826.  
  2827. :50 Represent a date in 3 bytes of "extended hex" notation
  2828. :==================================================================
  2829.  
  2830. rem produce today's date as 3 bytes
  2831. fdate /ff /oxxx 
  2832.  
  2833. rem produce yesterday's date in xxx format
  2834. fdate /fsub /N1 /oxxx
  2835.  
  2836.  
  2837.  
  2838.  
  2839. :51 Represent a date in a short (4-byte) format (technique #1)
  2840. :==================================================================
  2841. COMMENT
  2842. A common use of Fdate is to format today's date and use it to rename a file
  2843. (typically a log file of some sort).  You may wish to store the date
  2844. information in as few characters as possible, in order to maximize the
  2845. number of other characters in the filename that you can use to store other
  2846. information.
  2847.  
  2848. In this example, and the next one, I illustrate two ways to store a date in
  2849. 4 bytes.
  2850.  
  2851.  
  2852. The simplest way is to represent today's date as a 4-digit number.
  2853. To do this, we first pick a base date:  I'll use January 1, 1990.
  2854. Then it is a simple matter to calculate the number of days between today
  2855. and the base date:
  2856.  
  2857.            FDATE /Fdif /at /b01-01-1990 
  2858.  
  2859. Starting in 1993, this will always generate a 4-digit number, and will
  2860. continue to do so for 20 years, until approximately the year 2003.  Dates
  2861. before 1993 may produce 1-, 2-, or 3-digit numbers, and dates after 2003
  2862. will begin to produce 5-digit numbers.  But this technique will work quite
  2863. nicely for most ordinary purposes for the next 20 years.  
  2864.  
  2865. If you're still using DOS in the year 2003, then in 2003 you can switch to
  2866. using January 1, 2000 as your base date and function quite nicely for the
  2867. next 20 years after that.
  2868.  
  2869. :52 Represent a date in a short (4-byte) format (technique #2)
  2870. :==================================================================
  2871. @echo off
  2872. cls
  2873. goto end-doc
  2874. ------------------------------------------------------------------
  2875. This batch file shows how to use Fdate's #2XX function to
  2876. obtain and represent today's date in 4 characters, YYMD, where:
  2877.  
  2878.   YY is the year (e.g. "93" for 1993)
  2879.    M is the month in extended hexadecimal (XX) notation
  2880.    D is the day-of-the-month in extended hexadecimal (XX) notation
  2881.  
  2882. You can also use Fdate's "XXX" output format to represent dates between
  2883. 1990 and 2024 in 3 bytes of extended hex notation.
  2884. ------------------------------------------------------------------
  2885. :end-doc
  2886.  
  2887. REM OBTAIN 1-CHARACTER REPRESENTATION FOR THE MONTH
  2888. Fdate /ff    /Omm   /Vmm
  2889. Fdate /f#2xx /A%mm% /Vmm
  2890. echo XX representation of this month's number      is %mm%
  2891.  
  2892. REM OBTAIN 1-CHARACTER REPRESENTATION FOR THE DAY
  2893. Fdate /ff    /Odd   /Vdd
  2894. Fdate /f#2xx /A%dd% /Vdd
  2895. echo XX representation of today's day of the month is %dd%
  2896.  
  2897. REM CONCATENATE THEM TO THE 2-CHARACTER REPRESENTATION FOR THE YEAR
  2898. Fdate /Ff /Oyy /S%mm%%dd% /Vdate
  2899. echo XX representation of today's full date        is %date%
  2900.  
  2901. REM CLEANUP
  2902. set mm=
  2903. set dd=
  2904. set date=
  2905. :endit
  2906.  
  2907.  
  2908.  
  2909. :53 Convert numbers to "extended hex" (XX) format
  2910. :==================================================================
  2911. @echo off
  2912. cls
  2913. SET decnum=0
  2914. :top
  2915.    if (%decnum%)==(37) goto endit
  2916.    fdate /f#2xx /A%decnum% /P"XX representation of %decnum% is "
  2917.    fdate /f#add /A%decnum% /b1 /Vdecnum
  2918. goto top
  2919.  
  2920. :endit
  2921.  
  2922. :54 Customize Fdate for a language of your choice
  2923. :==================================================================
  2924. @echo off
  2925. cls
  2926. goto end-doc
  2927. ------------------------------------------------------------------
  2928. You can use Fdate with a customized batch file to obtain the names of
  2929. the days of the week and the months in a language of your choice.  Or
  2930. you could use it to obtain names in uppercase, or the first 5
  2931. characters of the names (rather than the first three), or some other
  2932. customized formatting of your choice.)
  2933.  
  2934. I've invented a language called Fergian, which has its own names for
  2935. the days of the week, and the months.  In the following examples, I
  2936. invoke FERGIAN.BAT to make the translation.  The text of FERGIAN.BAT,
  2937. which does the real work here, is given in the next example.
  2938. ------------------------------------------------------------------
  2939. :end-doc
  2940.  
  2941. fdate /ff /omm /v
  2942. call Fergian mm- result %Fdate%
  2943. echo Month  is          %result%
  2944.  
  2945. fdate /ff  /omm /v
  2946. call Fergian mm3 result %Fdate%
  2947. echo Month3 is          %result%
  2948.  
  2949. fdate /ff /odow#  /v
  2950. call Fergian dw- result %Fdate%
  2951. echo Day of week  is    %result%
  2952.  
  2953. fdate /ff /odow#  /v
  2954. call Fergian dw3 result %Fdate%
  2955. echo Day of week3 is    %result%
  2956.  
  2957. REM cleanup
  2958. set Fdate=
  2959. set result=
  2960.  
  2961. :55 Fergian.BAT (used in the previous example)
  2962. :==================================================================
  2963. @echo off
  2964. set  %2=
  2965. goto %1
  2966.  
  2967. goto end-doc
  2968. --------------------------------------------------------------------
  2969. This batch file converts a month number, or day of the week number,
  2970. to a name in the FERGIAN language.
  2971. You can copy this batch file and customize it, to make it translate
  2972. into some other language of your choice.
  2973.  
  2974. This batch file expects the following parameters:
  2975.  
  2976. %1 contains the type of number you want to convert:
  2977.    MM- if you want the entire name of the month
  2978.    MM3 if you want the first 3 letters of the name of the month
  2979.  
  2980.    DW- if you want the entire name of the day of the week
  2981.    DW3 if you want the first 3 letters of the name of the day of the week
  2982.  
  2983. %2 contains the name of the environment variable that you
  2984.    want to use to hold the result
  2985.  
  2986. %3 contains the number that you want to convert
  2987. --------------------------------------------------------------------
  2988. :end-doc
  2989.  
  2990. :MM-
  2991. if (%3)==(01) set %2=Jaded
  2992. if (%3)==(02) set %2=Febrile
  2993. if (%3)==(03) set %2=Martial
  2994. if (%3)==(04) set %2=Abigail
  2995. if (%3)==(05) set %2=Maybelene
  2996. if (%3)==(06) set %2=Junkaroo
  2997. if (%3)==(07) set %2=Julia
  2998. if (%3)==(08) set %2=Augmentation
  2999. if (%3)==(09) set %2=Separation
  3000. if (%3)==(10) set %2=Ostentation
  3001. if (%3)==(11) set %2=Novelty
  3002. if (%3)==(12) set %2=Decadence
  3003. goto endit
  3004.  
  3005. :
  3006. :MM3
  3007. if (%3)==(01) set %2=Jad
  3008. if (%3)==(02) set %2=Feb
  3009. if (%3)==(03) set %2=Mar
  3010. if (%3)==(04) set %2=Abi
  3011. if (%3)==(05) set %2=May
  3012. if (%3)==(06) set %2=Jun
  3013. if (%3)==(07) set %2=Jul
  3014. if (%3)==(08) set %2=Aug
  3015. if (%3)==(09) set %2=Sep
  3016. if (%3)==(10) set %2=Ost
  3017. if (%3)==(11) set %2=Nov
  3018. if (%3)==(12) set %2=Dec
  3019. goto endit
  3020.  
  3021. :DW-
  3022. if (%3)==(1) set %2=SunDay
  3023. if (%3)==(2) set %2=MoonDay
  3024. if (%3)==(3) set %2=TwickasDay
  3025. if (%3)==(4) set %2=WodensDay
  3026. if (%3)==(5) set %2=ThorsDay
  3027. if (%3)==(6) set %2=FreyasDay
  3028. if (%3)==(7) set %2=SaturnDay
  3029. goto endit
  3030.  
  3031.  
  3032. :DW3
  3033. if (%3)==(1) set %2=Sun
  3034. if (%3)==(2) set %2=Moo
  3035. if (%3)==(3) set %2=Twi
  3036. if (%3)==(4) set %2=Wod
  3037. if (%3)==(5) set %2=Tho
  3038. if (%3)==(6) set %2=Fre
  3039. if (%3)==(7) set %2=Sat
  3040. goto endit
  3041.  
  3042. :endit
  3043.  
  3044. :61 DO-ONCE: Run apps when booting for the first time of the day
  3045. :===============================================================
  3046. COMMENT
  3047.   Put this code in AUTOEXEC.BAT.  Note that this batch code requires DOS
  3048.   3.3+, since it uses CALL.
  3049.  
  3050. if not exist C:\LASTRUN.BAT goto RunNow
  3051.  
  3052. rem call LASTRUN.BAT, which will set an environment variable, %LASTRUN%,
  3053. rem that will contain the date when this batch file was last run.
  3054. rem ------------------------------------------------------------------
  3055. call C:\LASTRUN.BAT
  3056.  
  3057. rem compare the date in %LASTRUN% to today's date
  3058. rem ------------------------------------------------------------------
  3059. Fdate /Fcomp /At /B%LastRun% /Vcomp
  3060.  
  3061. : Today's date may be less than %LASTRUN% if you reset the system clock
  3062. IF (%COMP%)==(LT) goto NoRun
  3063. : If %LASTRUN% was the same as today's date,
  3064. :   then this batch file has already been run once today
  3065. IF (%COMP%)==(EQ) goto NoRun
  3066.  
  3067. : Daily processing hasn't been run today. Run it.
  3068. : Here, you should put the batch-file body --
  3069. : the code to run the applications that you want to run once per day
  3070. :
  3071.  
  3072. : ------------------------------------------------------------------
  3073. : Save today's date in a new version of LastRun.BAT.  Note that
  3074. : this code will be executed only if daily processing runs to
  3075. : completion without hanging the machine or aborting the batch file.
  3076. : ------------------------------------------------------------------
  3077. Fdate /Ff /Omm-dd-ccyy /At /P"@set LastRun=">LastRun.BAT
  3078.  
  3079. :NoRun
  3080. set LastRun=
  3081. set COMP=
  3082.  
  3083. :62 Run specific software, depending on the day of the week
  3084. :==================================================================
  3085. COMMENT
  3086. This is a very common use for Fdate.  I use it to load an alarm-clock TSR
  3087. (Terminate and Stay Resident, "memory resident", program) that beeps at me
  3088. (at different times on different days of the week) to remind me that it is
  3089. time to attend a meeting that is regularly scheduled for that day of the
  3090. week.
  3091.  
  3092. Note that stuff for a given day of the week will be executed every time you
  3093. boot up on that day of the week.  If you want stuff (e.g. a backup job) to
  3094. be run only once (the first time you boot up) on a given day of the week,
  3095. then:
  3096.  
  3097. (1)  copy the code from DO-ONCE (the previous example) into your
  3098.      AUTOEXEC.BAT file, then
  3099.  
  3100. (2)  copy this code into the body of the DO-ONCE code that you copied into
  3101.      AUTOEXEC.BAT in the last step.  If you do that, then this code will be
  3102.      run only once per day, even if you boot up multiple times per day.
  3103.  
  3104. Remember that if you are executing other batch files from a batch file, 
  3105. you should invoke them with a CALL statement:
  3106.               CALL batchfilename parm1 parm2 ...
  3107. so control will return to the calling batch file when execution of the
  3108. called batch file is complete.      
  3109.  
  3110. Note that the string comparison is case sensitive.
  3111. ==================================================================
  3112.  
  3113. :: get 3-character day-of-week name and put it in DOW e-var
  3114. FDATE /ff /oDOW3 /vDOW
  3115.  
  3116. if (%DOW%)==(Mon) alarmTSR.exe 10:30 Time for Monday staff meeting
  3117.  
  3118. if (%DOW%)==(Fri) echo Running Friday backup.  Please wait...
  3119. if (%DOW%)==(Fri) CALL BACKUP C: 
  3120. if (%DOW%)==(Fri) CALL BACKUP D: 
  3121. set dow=
  3122.  
  3123.  
  3124.  
  3125. :63 Run a program at a specified time later in the day
  3126. :==================================================================
  3127. COMMENT
  3128.   This batch file involves a lot of disk activity because DOS re-reads the
  3129.   batch file from disk every time it does a GOTO LOOPTOP.  You can avoid
  3130.   all this disk activity by running the batch file from a RAM DISK.
  3131.  
  3132. REM GET CURRENT ABSOLUTE MINUTE AND PUT IN ENVIRONMENT VARIABLE RUNTIME
  3133. FDATE /Ff /At /Ominute#  |STRINGS RunTime= ASK >NUL
  3134.  
  3135. REM ADD 120 MINUTES (2 HOURS) TO ENVIRONMENT VARIABLE RUNTIME
  3136. FDATE /F#add /A%RunTime% /B120 |STRINGS RunTime= ASK >NUL
  3137.  
  3138. REM LOOP UNTIL NOWTIME HAS REACHED RUNTIME
  3139. :LoopTop
  3140.   FDATE /Ff /At  /Ominute#   |STRINGS NowTime=  ASK >NUL
  3141.   FDATE /F#comp  /A%NowTime% /B%RunTime% |STRINGS TimeComp= ASK >NUL
  3142.   if (%TimeComp%)==(LT) goto loopTop
  3143. :LoopEnd
  3144.  
  3145. echo STARTING EXECUTION OF APPLICATION: [program name]
  3146.  
  3147.  
  3148.  
  3149. :66 Change a filename to contain today's date in first 3 bytes
  3150. :==================================================================
  3151. FDATE /Ff /Oxxx /vXXX
  3152. ren  BACKUP.LOG  %XXX%-BACK.LOG
  3153. SET  XXX=
  3154.  
  3155.  
  3156.  
  3157. :67 Change a file's name to a name that contains today's date
  3158. :==================================================================
  3159. FDATE /Ff /At /Oyymmdd /vdate1
  3160. ren  BACKUP.LOG  BK%DATE1%.LOG
  3161. SET  DATE1=
  3162.  
  3163.  
  3164. :68 Change a file's name to a name containing an absolute minute 
  3165. :===============================================================
  3166. COMMENT
  3167.   This is a way to keep a complete series of files, such as log files,
  3168.   that are all created with the same name on the same day.  The only
  3169.   requirement is that they be created at least one minute apart.  You
  3170.   won't need to be able to decipher the absolute minute to figure out when
  3171.   the file was created; you can simply do a DIR on the file and look at
  3172.   its date/time stamp.  
  3173.  
  3174. FDATE /FF /At /Ominute# /VJulMin
  3175. REN online.log %JulMin%.log
  3176. SET JulMin=
  3177.  
  3178.  
  3179.  
  3180. :71 Extract the rightmost n characters of a string 
  3181. :===============================================================
  3182. rem extract the rightmost 6 characters of a string
  3183. FDATE /Fsubstr /a-6     /Q"1994 Jun 03"   ===> "Jun 03"     
  3184.  
  3185.  
  3186.  
  3187. :72 Left-pad a number with zeroes, or a string with spaces
  3188. :===============================================================
  3189. :: pad a number (stored in environment variable) STRING
  3190. :: to the left with zeroes, to make sure it is 4 bytes long
  3191. set STRING=1
  3192. Fdate /Fe  /P%STRING% /Jr04  /Vstring
  3193. echo STRING is [%string%]
  3194.  
  3195. :: pad a string (stored in environment variable) STRING
  3196. :: to the left with spaces, to make sure it is 4 bytes long
  3197. set STRING=aa
  3198. Fdate /Fe  /P%STRING% /J"r 4"  /Vstring
  3199. echo STRING is [%string%]
  3200.  
  3201. HOW FDATE THINKS ABOUT DATES
  3202. ============================
  3203.  
  3204. FDATE'S BUSINESS VIEW OF THE CALENDAR
  3205. =====================================
  3206.  
  3207.   FDATE is intended for business applications, not historical ones.  
  3208.  
  3209.   FDATE does not take into account historical changes in the calendar such
  3210.   as the ten days that were dropped from the British calendar when Britain
  3211.   moved from the Julian to the Gregorian calendar in the 18th century, or
  3212.   the 11 days that were dropped from the Russian calendar when Russia made
  3213.   the same move in the early 20th century.
  3214.  
  3215.   As far as FDATE is concerned, the calendar has followed the same
  3216.   pattern, unchanged, since January 1, 0001.
  3217.  
  3218.  
  3219. FDATE'S BASE DATE
  3220. =================
  3221.   Internally, Fdate's date manipulations are based on translating a
  3222.   calendar date into an "absolute" or "TRUE Julian" date:  a date
  3223.   expressed as the number of days from some day in the distant past.
  3224.  
  3225.   FDATE's base date is January 1, 0001 (i.e. day 1 of month 1 of year 1)
  3226.   FDATE's absolute date for January 1, 0001 is      1.
  3227.   FDATE's absolute date for January 1, 1992 is 727198.
  3228.  
  3229.  
  3230. FDATE'S LEAP YEAR ALGORITHM
  3231. ===========================
  3232.     Every year evenly divisible by 4 IS a leap year
  3233.       EXCEPT THAT
  3234.         Every year evenly divisible by 100 IS NOT a leap year
  3235.           EXCEPT THAT
  3236.             Every year evenly divisible by 400 IS a leap year
  3237.     .
  3238.     Using this algorithm
  3239.          1983  is not a leap year
  3240.          1984  is     a leap year
  3241.          1900  is not a leap year
  3242.          2000  is     a leap year
  3243.  
  3244.     See "A Machine Algorithm for Processing Calendar Dates", by
  3245.          Henry F. Fliegel (Georgetown University Observatory) and
  3246.          Thomas C. Van Flandern (U.S. Naval Observatory)
  3247.          COMMUNICATIONS OF THE ACM, Volume 11, Number 10, October 1968
  3248.  
  3249. There is supposedly a new adjustment to the leapyear algorithm,
  3250. which specifies the additional exception:
  3251.  
  3252.               EXCEPT THAT
  3253.                 Every year evenly divisible by 4000 IS a leap year
  3254.  
  3255. See "Bit By Bit" column, COMPUTER LANGUAGE, November 1989, p. 148.
  3256. This adjustment is not part of FDATE's leapyear algorithm.
  3257. Unless your application is working with dates 2,000 years in the
  3258. future, the lack of this exception will be irrelevant for you.
  3259.  
  3260. FDATE'S CENTURY-ASSUMPTION ALGORITHM
  3261. ====================================
  3262. If an input date is supplied in a format in which the year is
  3263. specified without a century -- that is, as YY rather than CCYY --
  3264. then Fdate does not automatically use the current century.
  3265. Instead,
  3266.  
  3267.    *  if YY is greater than 20,       then FDATE assumes CC = 19
  3268.    *  if YY is less than or equal 20, then FDATE assumes CC = 20
  3269.  
  3270. Examples:
  3271.          21    becomes  1921
  3272.          ...
  3273.          99    becomes  1999
  3274.          00    becomes  2000
  3275.          01    becomes  2001
  3276.          ...
  3277.          20    becomes  2020
  3278. but then (again)
  3279.          21    becomes  1921
  3280.  
  3281. To put it simply, FDATE makes what would be a reasonable assumption
  3282. about the century for someone operating in the 1990's: it looks back to
  3283. 1921 and forward to 2020.  If both I and FDATE are still alive in the
  3284. year 2000, I'll probably update FDATE's century-assumption algorithm to
  3285. shift it forward several decades.
  3286.  
  3287.  
  3288. FDATE'S IMPLEMENTATION LIMITS
  3289. ====================================
  3290. Internally, numbers in Fdate are stored in Turbo Pascal's LONGINT datatype,
  3291. which means that Fdate can accept numbers up to 9 digits long.
  3292.  
  3293. DISTRIBUTION ISSUES
  3294. ===================
  3295.  
  3296. USE, REGISTRATION, AND DISTRIBUTION OF FDATE
  3297. ============================================
  3298.  
  3299. FDATE is freeware, or what is known as "zero-cost shareware".  FDATE is not
  3300. what is technically called "public domain" software because the author
  3301. retains the copyright.  FDATE can, however, be copied, used, and
  3302. distributed freely as long as FDATE.EXE and its associated doc file
  3303. (FDATE.DOC) and demonstration batch files and doc files (HOLIDAYS.BAT,
  3304. HOLIFEDS.BAT, HOLIFEDS.DOC) are not altered and are distributed together.  
  3305.  
  3306. There is no requirement to register FDATE in any way.
  3307.  
  3308. FDATE can be included in shareware packages as long as both FDATE and
  3309. its related files are included in the shareware package.
  3310.  
  3311. If you have received FDATE as part of some larger shareware package,
  3312. please be aware that you may freely use, copy, and distribute FDATE
  3313. without paying a fee for, or registering, the larger package.
  3314.  
  3315. The author explicitly disavows any claim whatsoever about the
  3316. correctness or functionality of FDATE, its documentation, and its
  3317. demonstration batch files, and disclaims liability for anything and
  3318. everything bad that might happen in connection with, before, during, or
  3319. after using it.  I have tried to make FDATE work right, but everybody
  3320. makes mistakes, so you use FDATE at your own risk.
  3321.  
  3322. I don't know if people will find FDATE useful, and I'd like to find
  3323. out.  If you find FDATE useful and use it on a regular basis, I'd
  3324. appreciate it if you would drop me a short note via US mail or
  3325. CompuServe, telling me about how you are using FDATE.
  3326.  
  3327. If you need other input/output formats, please contact the author.
  3328.  
  3329.  
  3330. TECHNICAL SUPPORT FOR FDATE
  3331. ===============================================
  3332.  
  3333. Send me a message via CompuServe mail; I'll respond.  When sending your
  3334. message, please let me know what version of Fdate you're using.
  3335.  
  3336.  
  3337. WHERE TO FIND THE MOST CURRENT VERSION OF FDATE
  3338. ===============================================
  3339.  
  3340. You will always be able to find the most recent version of FDATE on
  3341. CompuServe.  The filename will be FDATE.ZIP, and it will be available in
  3342. the CIS:IBMSYS forum (library 1, the "DOS Utilities" library).
  3343.  
  3344. If you have problems finding it, try using cross-library searching, looking
  3345. for the filename FDATE.ZIP or the keyword FDATE.
  3346.  
  3347.  
  3348. UPLOADING FDATE TO ELECTRONIC BULLETIN BOARDS
  3349. ===============================================
  3350.  
  3351. Feel free to post copies of FDATE.ZIP on any BBS that you wish, but please
  3352. do not upload it to any CompuServe library.  As long as I am the only one
  3353. putting copies of FDATE onto CompuServe, we can keep confusion over
  3354. versions to a minimum.
  3355.  
  3356. I distribute all versions of FDATE in a files called FDATE.ZIP, rather than
  3357. embedding information about the version in the file name.  I think doing
  3358. this helps newer versions of FDATE to force older versions out of
  3359. circulation.  To give a BBS user information about the version, I always
  3360. identify the version of FDATE in the 1-line file description that most BBSs
  3361. support.  
  3362.  
  3363.  
  3364. CONTENTS OF THE FDATE.ZIP DISTRIBUTION FILE
  3365. ===========================================
  3366.  
  3367. The current distribution package (FDATE.ZIP) contains the following:
  3368.  
  3369.        FDATE.EXE         [the FDATE program]
  3370.        FDATE.DOC         [this file, documentation for FDATE]
  3371.        FDATEBEG.DOC      [FDATE beginners documentation]
  3372.  
  3373.   [demonstration batch files]
  3374.        HOLIDAYS.BAT
  3375.        HOLIFEDS.BAT and HOLIFEDS.DOC
  3376.  
  3377.   [documentation files for use in BBS distribution]
  3378.        FILE_ID.DIZ
  3379.        DESC.SDI  
  3380.  
  3381.  
  3382. RECENT FDATE REVISION HISTORY
  3383. =============================
  3384.  
  3385. Letters appended to version numbers indicate modifications to
  3386. the doc files, without any modification to the FDATE.EXE software.
  3387. Asterisks (*) indicate most important changes in the new version.
  3388.  
  3389. 7.0a   Nov 14, 1992
  3390.        Added #mod function
  3391.        Major reformatting of documentation to make it more user-friendly
  3392.    
  3393. 7.1a   Apr 15, 1993
  3394.        Added German language support.  Thanks for the request, and the
  3395.        necessary information, from Patrick Schmucki, via the Active-Net
  3396.        BBS in Rapperswil, Switzerland.
  3397.  
  3398. 8.0    July, 1993
  3399.        Added "V" (validate) and "m" (month addition/subtraction) functions
  3400.        Added math functions: #mult #div #idiv
  3401.        Added /T (time) parameter
  3402.  
  3403.        Added FORATIME.BAT example, which Walter Ledge (assistant sysop of
  3404.        CompuServe's CRFORUM) and I developed.  A big thanks to Walt for
  3405.        his feedback and help.
  3406.  
  3407. 8.1    July 27, 1993  BUG FIX
  3408.        An error-trapping routine that was added to version 7.9 contained a
  3409.        bug that caused Fdate's numeric math functions (#add, #dif, #mult,
  3410.        #div, #idiv, #mod, #comp, etc.) to return incorrect results. 
  3411.        
  3412. 8.2    August, 1993
  3413.        Removed FILEDATE.BAT from the distribution .ZIP file.
  3414.  
  3415.        Corrected the Spanish and French "full" and "d1" output formats. 
  3416.        Thanks for the information on Spanish and French date formats to
  3417.        Gene J. Raymond, of GJR Software Products.
  3418.  
  3419. 8.3a   Feb 24, 1994
  3420.  
  3421. *      Added the following string-handling functions:
  3422.        get    (get user input)
  3423.        getu   (get uppercase user input)
  3424.        upper  (uppercase a string)
  3425.        len    (length of a string)
  3426.        substr (substring)
  3427.  
  3428. *      Added /F#2xx (convert number to extended hex format) function. 
  3429.        Deleted SETXX.BAT, which has been made obsolete with the addition
  3430.        of this new function.  Modified second example of storing a 4-digit
  3431.        date to use #2xx instead of SETXX.BAT.
  3432.  
  3433. *      Added output formats "ddmmccyy" and "ddmmyy" at the request of
  3434.        several users.
  3435.  
  3436. *      Added output format "xxx" after several requests for advice on how
  3437.        to represent a large range of dates in a minimum number of bytes
  3438.        (usually for constructing filenames from today's date).
  3439.  
  3440. *      At the request of several users, enhanced the "compare" functions
  3441.        (comp, tcomp, #comp) so they set distinctive errorlevels for their
  3442.        different results.  See the table of contents ("COMPARE-FUNCTION
  3443.        ERRORLEVELS") and EXAMPLES.
  3444.  
  3445.        To discussion of /Fv parameter, added note about almost always
  3446.        redirecting output to NUL when using /Fv.
  3447.  
  3448.        Revised FORATIME.BAT example batch file to make error-correction a
  3449.        bit more robust and to add better documentation on how to use it.
  3450.  
  3451.        Added example batch files to use new functions, especially
  3452.        FORATIM2.BAT which uses new "get" function
  3453.  
  3454.        Removed FDATEX.BAT demonstration batch file from distribution
  3455.        package, to reduce its size.  The examples in this DOC file should
  3456.        make the examples in FDATEX.BAT unnecessary
  3457.  
  3458.  
  3459. 8.4a   March 20, 1994
  3460. *      Added GETK (get keypress) function
  3461.  
  3462. *      Added ability to use /V when running in a Windows DOS box, thanks
  3463.        to a Turbo Pascal routine from the Turbo Professional library
  3464.        provided by Kim Kokkonen of TurboPower Software.
  3465.  
  3466.        Fixed a bug in which the prompt string (/Q) for the GET and GETU
  3467.        functions was being written to redirectable output (StdOut).  The
  3468.        prompt string is now written directly to the screen, and will not
  3469.        appear in FDATE's output when the output is redirected to a file.
  3470.  
  3471.        Removed ALARM.BAT, ALARM.DOC, TIC.BAT and TIC.DOC from distribution
  3472.        package.  They were too esoteric to be generally helpful.
  3473.  
  3474.        Added FILE_ID.DIZ and DESC.SDI to distribution package.
  3475.  
  3476.        Corrected algorithm for Mardi Gras in HOLIDAYS.BAT.  Modified
  3477.        HOLIDAYS.BAT and HOLIFEDS.BAT to make them more interactive, using
  3478.        FDATE's new abilities to get user input.
  3479.  
  3480. *      Started ZIPing FDATE.ZIP with PKZIP 2.04g rather than version 1.1
  3481.  
  3482. 8.4b   April 2, 1994
  3483.        Revised example :08, to use /fgetK rather than /fgetU
  3484.        Fixed formatting of #dif function
  3485.        Reformatted examples to reduce number of printed pages
  3486.        Duplicate example :07 was renumbered 
  3487.        FORATIME.BAT (original version) removed as no longer interesting
  3488.        Modified JDATE.BAT to use new /Fget function
  3489.  
  3490. 8.4c   September 6, 1994
  3491.        Revised HOLIDAYS.BAT so it would not go into an infinite loop if
  3492.        run on a system where FDATE cannot manipulate the environment, and
  3493.        to pad the year to the left with zeroes, so years before 1000 will
  3494.        be accepted.
  3495.  
  3496.        Added example showing how to left-pad a number with zeroes.
  3497.  
  3498.        Rewrote example showing how to time execution of a program.
  3499.  
  3500.        Updated my home mailing address after moving.
  3501.  
  3502.        Corrected information on how to make sure you have enough
  3503.        environment space in a Windows DOS box.  Thanks for the feedback
  3504.        and on this issue from Ronny Richardson.
  3505.  
  3506.        Added WHATDAY.BAT (example :14).  Thanks for the request from Cal
  3507.        Pryluck, Radio-Television-Film, Temple University, Philadelphia
  3508.  
  3509. 8.5a   September 28, 1994
  3510.        Added output date format "mmddyy" (PKZIP's "American" date format),
  3511.        and an example showing how to use Fdate to get a date for use with
  3512.        PKZIP for archiving files.  Thanks for the tip on PKZIP's input
  3513.        formats from Dick Jensen.
  3514.  
  3515. 8.6a   October 27, 1994
  3516.        Corrected a bug in output format T1: HOUR value was being prefixed
  3517.        by a leading zero if MINUTE value was less than 10.
  3518.  
  3519. 8.7a   October 27, 1994
  3520.        Added output format TDOS, which mimics the format used in the DOS
  3521.        "time" command.  Added an example using it to the "roll your own"
  3522.        date format example (:19) as example (a).  Thanks for the request
  3523.        for this common time format from Roy Zider.
  3524.  
  3525. 8.8a   November 06, 1994
  3526.        Changed error action in cases in which the prefix parm /P was
  3527.        specified.  In case of an error, the first line generated will
  3528.        always be "ERROR".  If prefix parm was specified, then a second
  3529.        line will be generated with the prefix followed by "ERROR".  Thus,
  3530.        if output is being routed to a batch file, and the prefix is
  3531.        something like "@set fdate=", then that will continue to work.
  3532.  
  3533.        Removed the example of using /Fe to put equal-signs and redirection
  3534.        symbols into the environment.  I doubt if anyone found this example
  3535.        useful.
  3536.  
  3537.        Added ability to break out of HELP using the ESC key
  3538.  
  3539. *      Added justify parm (/J)
  3540.        Re-wrote HOLIDAYS.BAT to illustrate uses for /J.
  3541.  
  3542. 8.9a   1995 Feb 15
  3543. *      Added "absolute month" output format (/Omonth#)
  3544.        Added example YMD_DIF.BAT, which uses new /Omonth# facility
  3545.        Added FDATEBEG.DOC to the distribution .ZIP file
  3546.  
  3547. 9.0a   1995 Feb 20
  3548.        prefixed "@" to the "echo ERROR ... " and "pause" that are
  3549.        generated when Fdate detects an error.  This should make error
  3550.        messages a bit easier to decipher.
  3551.  
  3552. 9.1a   1995 May 15
  3553.        Corrected bug that gave runtime error when function was #mult and
  3554.        /A parm was 0.
  3555.  
  3556. 9.1b   1995 June 12
  3557.        Corrected example of Japanese date format in this DOC file.  Thanks
  3558.        to Christopher Clark for pointing out the typo.
  3559.  
  3560. 9.1c   1995 Oct 22
  3561.        Added a usage example to the discussion of the "file" input format
  3562.        (/If).  Thanks to Bob Stephan for the suggestion.
  3563.