FDATE                     Version 9.6a              1997 April 22
======================================================================
"Everything you'd ever want to do with dates in batch files"
======================================================================

AUTHOR:     Stephen Ferg             
            608 N. Harrison Street
            Arlington, VA 22203-1416
            USA

            Internet                  : Ferg_S@bls.gov
            CompuServe ID             : 73377,1157
            Internet                  : 73377.1157@compuserve.com
            telephone (voice, not FAX): (703) 525-2241

=======================================================================

If you are planning to use Fdate with Windows NT, please see the section
"/V WHEN RUNNING UNDER WINDOWS NT" (below), or read file FDATE_NT.TXT,
which contains the same material.


WHAT TO DO IF THIS DOCUMENTATION SEEMS TOO OVERWHELMING
========================================================

As Fdate has grown in functionality over the years, its documentation has
also grown.  Lately I've been getting feedback from people who encounter
Fdate for the first time, telling me that Fdate's documentation is so
massive that it is overwhelming: they have no idea where to start, or how
to use the documentation to help them figure out how to make Fdate do what
they need to do.

If that is the situation you're in right now, take heart!  There is hope!

To help you get started using Fdate, I've created a much shorter file
called FDATEBEG.TXT (FDATE beginners documentation), which shows how to use
Fdate to do the things most users want to do.

So if you're trying to use Fdate for the first time, and feeling
overwhelmed (or even if you're not feeling overwhelmed), I suggest that you
read FDATEBEG.TXT.

                             Table of Contents

Page numbers in the WordPerfect version of FDATE.TXT (which is not
distributed with FDATE) are lost in the conversion to ASCII format. 
Nevertheless, these page numbers give you a rough idea of the relative
locations of the different sections.

  WHAT TO DO IF THIS DOCUMENTATION SEEMS TOO OVERWHELMING. . . . . . . .  1
  WHAT IS FDATE? . . . . . . . . . . . . . . . . . . . . . . . . . . . .  5
     ANOTHER UTILITY NAMED "FDATE" . . . . . . . . . . . . . . . . . . .  6
     OVERVIEW OF PARAMETERS. . . . . . . . . . . . . . . . . . . . . . .  7
     OVERVIEW OF FUNCTIONS . . . . . . . . . . . . . . . . . . . . . . .  9
  FUNCTIONS: DETAILED DESCRIPTIONS . . . . . . . . . . . . . . . . . . . 11
     DATE FORMATTING FUNCTIONS . . . . . . . . . . . . . . . . . . . . . 11
     DATE ARITHMETIC FUNCTIONS . . . . . . . . . . . . . . . . . . . . . 12
     MONTH DATE ARITHMETIC FUNCTIONS . . . . . . . . . . . . . . . . . . 13
     WEEKDAY DATE ARITHMETIC FUNCTIONS . . . . . . . . . . . . . . . . . 14
     DATE/TIME COMPARISON FUNCTIONS. . . . . . . . . . . . . . . . . . . 16
     COMPARE-FUNCTION ERRORLEVELS. . . . . . . . . . . . . . . . . . . . 16
     NUMERIC ARITHMETIC FUNCTIONS. . . . . . . . . . . . . . . . . . . . 17
     DATE VALIDATION FUNCTION. . . . . . . . . . . . . . . . . . . . . . 19
  STRING FUNCTIONS . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
     GET and GETU (GET USER INPUT) FUNCTION. . . . . . . . . . . . . . . 20
     GETK (GET KEYPRESS) FUNCTION. . . . . . . . . . . . . . . . . . . . 21
       Specifying the Keymask. . . . . . . . . . . . . . . . . . . . . . 21
       GetK Results also in ERRORLEVEL . . . . . . . . . . . . . . . . . 22
       Modifying the Keymask . . . . . . . . . . . . . . . . . . . . . . 23
       Displaying a User Prompt With GETK. . . . . . . . . . . . . . . . 23
     SUBSTR (SUBSTRING) FUNCTION . . . . . . . . . . . . . . . . . . . . 24
     LEN (LENGTH) FUNCTION . . . . . . . . . . . . . . . . . . . . . . . 26
     UPPER FUNCTION. . . . . . . . . . . . . . . . . . . . . . . . . . . 26
     ECHO FUNCTION . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
     /J: JUSTIFYING OUTPUT . . . . . . . . . . . . . . . . . . . . . . . 27
  DATE FORMATS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
     SYMBOL CONVENTIONS. . . . . . . . . . . . . . . . . . . . . . . . . 29
     PSEUDODATES . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
  INPUT DATE FORMATS . . . . . . . . . . . . . . . . . . . . . . . . . . 31
     ABSOLUTE DATE INPUT FORMATS . . . . . . . . . . . . . . . . . . . . 31
     CALENDAR DATE INPUT FORMATS . . . . . . . . . . . . . . . . . . . . 32
     BUSINESS JULIAN DATE INPUT FORMATS. . . . . . . . . . . . . . . . . 33
     GETTING DATE/TIME A FILE WAS CREATED. . . . . . . . . . . . . . . . 34
  OUTPUT DATE FORMATS. . . . . . . . . . . . . . . . . . . . . . . . . . 35
     DAY-OF-WEEK AND MONTH OUTPUT FORMATS. . . . . . . . . . . . . . . . 37
     MISCELLANEOUS OUTPUT FORMATS. . . . . . . . . . . . . . . . . . . . 37
     LEAP-YEAR FLAG OUTPUT FORMAT. . . . . . . . . . . . . . . . . . . . 38
     TIME OUTPUT FORMATS . . . . . . . . . . . . . . . . . . . . . . . . 38
     BUSINESS JULIAN DATE OUTPUT FORMATS . . . . . . . . . . . . . . . . 39
     ABSOLUTE DATE/TIME OUTPUT FORMATS . . . . . . . . . . . . . . . . . 40
     /T: TIME OVERRIDE PARAMETER . . . . . . . . . . . . . . . . . . . . 41
     /J: JUSTIFYING OUTPUT . . . . . . . . . . . . . . . . . . . . . . . 41
  HOW TO PUT FDATE OUTPUT INTO AN ENVIRONMENT VARIABLE . . . . . . . . . 42
     CALL A BATCH FILE . . . . . . . . . . . . . . . . . . . . . . . . . 42
     USE AN ENVIRONMENT-MANIPULATION UTILITY . . . . . . . . . . . . . . 42
     FDATE'S /V PARAMETER. . . . . . . . . . . . . . . . . . . . . . . . 43
     /V WHEN RUNNING UNDER MICROSOFT WINDOWS . . . . . . . . . . . . . . 44
     /V WHEN RUNNING UNDER WINDOWS NT. . . . . . . . . . . . . . . . . . 45
       Turbo Professional: "Highly Recommended". . . . . . . . . . . . . 46
     /V WHEN USING 4DOS, NDOS, AND UMB . . . . . . . . . . . . . . . . . 47
  FDATE'S ERROR HANDLING . . . . . . . . . . . . . . . . . . . . . . . . 48
  EXAMPLES OF HOW TO USE FDATE . . . . . . . . . . . . . . . . . . . . . 49
     :01 Display Fdate output on screen. . . . . . . . . . . . . . . . . 49
     :02 Redirect FDATE output to a file . . . . . . . . . . . . . . . . 49
     :03 Put FDATE output in an environment variable using a batch file. 49
     :04 Put FDATE output in an environment variable using /V parm . . . 49
     :05 Put FDATE output in an environment variable using STRINGS . . . 49
     :06 Put FDATE output in an environment variable using GET . . . . . 49
     :07 Get user input. . . . . . . . . . . . . . . . . . . . . . . . . 50
     :08 Get a user menu selection . . . . . . . . . . . . . . . . . . . 51
     :09 Change a date from one format into another. . . . . . . . . . . 52
     :10 Find the difference in days between two dates . . . . . . . . . 52
     :11 Find the elapsed days/hours/minutes between two date/times. . . 53
     :13 Find the elapsed years/months/days between two dates. . . . . . 56
     :14 Determine how long it took a program to run . . . . . . . . . . 59
     :15 Find years when a given date fell on a given day of the week. . 60
     :16 Find calendar date corresponding to a "business Julian" date. . 62
     :17 Set your PC's date to a business julian date. . . . . . . . . . 63
     :18 Determine if parm %1 contains a valid date. . . . . . . . . . . 65
     :19 "Roll your own" date format . . . . . . . . . . . . . . . . . . 65
     :20 Find the 4th Thursday in November (Thanksgiving). . . . . . . . 66
     :22 On a date, show what anniversary it is for some event . . . . . 66
     :23 Show a list of holidays in a given year . . . . . . . . . . . . 66
     :24 Show a list of Federal holidays in a given year . . . . . . . . 66
     :25 Determine if a year is valid, and evenly divisible by 4 . . . . 67
     :30 Compare a file's date to today's date . . . . . . . . . . . . . 67
     :31 Compare two files' date/time  . . . . . . . . . . . . . . . . . 68
     :32 Display a list of all files that were created/updated today.  . 69
     :33 MIN_MATH.BAT -- "time arithmetic" in minutes. . . . . . . . . . 70
     :34 TIME_SET.BAT -- "time arithmetic" -- set TIME . . . . . . . . . 71
     :41 Delete files more than X days old (use a batch-file subroutine) 72
     :42 Get date to tell PKZIP to compress files older than 30 days . . 77
     :43 Loop through an array of environment variables. . . . . . . . . 78
     :44 Do something on the last day (or last Friday) of the month. . . 79
     :45 Get information about the month prior to the current month. . . 80
     :46 Show the last Monday (or any other weekday) in this month . . . 80
     :47 Show the last Monday in the month, for a series of months . . . 81
     :50 Represent a date in 3 bytes of "extended hex" notation. . . . . 82
     :51 Represent a date in a short (4-byte) format (technique #1). . . 82
     :52 Represent a date in a short (4-byte) format (technique #2). . . 83
     :53 Convert numbers to "extended hex" (XX) format . . . . . . . . . 83
     :54 Customize Fdate for a language of your choice . . . . . . . . . 84
     :55 Fergian.BAT (used in the previous example). . . . . . . . . . . 85
     :61 DO-ONCE: Run apps when booting for the first time of the day. . 87
     :62 Run specific software, depending on the day of the week . . . . 88
     :63 Run a program at a specified time later in the day. . . . . . . 88
     :66 Change a filename to contain today's date . . . . . . . . . . . 90
     :67 Change a file's name to a name that contains today's date . . . 90
     :68 Change a file's name to a name containing an absolute minute  . 90
     :71 Extract the rightmost n characters of a string  . . . . . . . . 90
     :72 Left-pad a number with zeroes, or a string with spaces. . . . . 90
  HOW FDATE THINKS ABOUT DATES . . . . . . . . . . . . . . . . . . . . . 92
     FDATE'S BUSINESS VIEW OF THE CALENDAR . . . . . . . . . . . . . . . 92
     FDATE'S BASE DATE . . . . . . . . . . . . . . . . . . . . . . . . . 92
     FDATE'S LEAP YEAR ALGORITHM . . . . . . . . . . . . . . . . . . . . 93
     FDATE'S CENTURY-ASSUMPTION ALGORITHM. . . . . . . . . . . . . . . . 94
     FDATE'S IMPLEMENTATION LIMITS . . . . . . . . . . . . . . . . . . . 94
  DISTRIBUTION ISSUES. . . . . . . . . . . . . . . . . . . . . . . . . . 95
     USE, REGISTRATION, AND DISTRIBUTION OF FDATE. . . . . . . . . . . . 95
     TECHNICAL SUPPORT FOR FDATE . . . . . . . . . . . . . . . . . . . . 96
     WHERE TO FIND THE MOST CURRENT VERSION OF FDATE . . . . . . . . . . 96
     UPLOADING FDATE TO ELECTRONIC BULLETIN BOARDS . . . . . . . . . . . 96
     CONTENTS OF THE FDATE.ZIP DISTRIBUTION FILE . . . . . . . . . . . . 96
     RECENT FDATE REVISION HISTORY . . . . . . . . . . . . . . . . . . . 97

WHAT IS FDATE?
==============
Fdate is a utility for doing date formatting and date arithmetic in DOS
batch files.  There are a number of different ways to put FDATE's output
into environment variables.  Once this has been done, the environment
variables can be used and manipulated in many ways in the batch file.

FDATE is freeware, or what is technically known as "zero-cost shareware". 
There is no requirement to register FDATE in any way.  For more details,
see the DISTRIBUTION ISSUES section.

Here are some of the things you can do with FDATE.

    accept user input from the keyboard

    retrieve today's date in a variety of formats
      place today's date into a file name

    reformat dates 
       Output formats include common American and European formats, or you
       can "roll your own" by manipulating environment variables.  Month
       and weekday names can be produced in several languages (English,
       French, German, Spanish).

    calculate when certain holidays occur in a given year

    do date arithmetic
      determine the date N days before/after a given date
      compare two dates to determine which is earlier
      compare two dates to determine how many days apart they are

    determine if a year is a leap year
    determine whether a year is evenly divisible by some number

    determine what day of the week a date falls on
      run certain software only on certain days of the week

    retrieve the date/time from the date/timestamp of a file
    do simple integer arithmetic (add, subtract, modulus)
    calculate the time a piece of software takes to run
    convert a calendar date to/from a "business julian" date

    extract a substring from an environment variable
    right, left, or center justify a string

ANOTHER UTILITY NAMED "FDATE"
=============================

There is another shareware utility named FDATE in circulation, written by
Garrett A. Wollman.  Mr. Wollman's FDATE is a kind of "touch" utility that
can be used to change a file's NAME (rather than its date/time stamp) to a
certain date.  The Public Software Library in Houston distributes it under
the name FDATE.ZIP.  PSL distributes my [Ferg's] FDATE under the name
FDATESF.ZIP.  

As of April 1997, you can reach PSL by telephone (voice) at (713) 524-6394,
by Compuserve at 74777,3465, or by the Web at www.pslweb.com.  

The most recent information I have is that Garrett Wollman can be reached
at:
     Garrett A. Wollman
     7 Worcester Street
     South Burlington, VT 05403
     USA

     ...uunet!mimsy!aplcen!jhunix!gwollman
     ...uunet!uvm-gen!tnl!gwollman   (summer)
     gwollman@jhunix.hcf.jhu.edu

Both FDATEs have been in circulation under the name FDATE.ZIP for too long
to make it practical to change the name of either one.  All that can be
done is to warn you of a potentially confusing situation.  If you see a
file named FDATE.ZIP, read the description of the file to determine which
FDATE it is.  Checking the version numbers may also help-- as of April
1996, Ferg's FDATE is in version 9.3; Mr. Wollman's FDATE is in version
1.2.

OVERVIEW OF PARAMETERS
======================

FDATE accepts the following parameters:

       /F /A /B /I /O /P /S /N /D /L /V /T /Q /J /K /X

If the /F parameter is not present, FDATE displays a help screen.  
     If you get FDATE's help screen when you don't expect it, you probably
     forgot to specify the /F parameter or mistyped it.

Parameters can be in any order and upper or lower case.
     Note that although function and format parms are not case sensitive,
     they are "text sensitive".  If any characters are missing, added, or
     mistyped, the parameter will be rejected.

What parameters are required (other than /F) depends on the function
requested with the /F parameter.  Unnecessary parameters are simply
ignored.



HERE IS A BRIEF SUMMARY OF WHAT EACH OF THE PARAMETERS MEANS
------------------------------------------------------------

/F   requests a particular FDATE function.  This is Fdate's most important
     parameter.  See the OVERVIEW OF FUNCTIONS section, and the detailed
     description of each Fdate function.

/A   For date functions, these two parameters are used to specify dates. 
/B   For the ordinary arithmetic functions, these parameters are used to
     specify numbers.  For date functions, if either of these parameters is
     omitted, it defaults to today's date.

/Dday-of-week number (used only with W function)

/Ispecifies format of input date(s)
  If the /I parameter is omitted, /Imm-dd-ccyy is assumed.

/J   specifies justification, length, and pad character
  If the /J parameter is omitted, no justification formatting is done.

/K   The GETK function takes a /K "keymask" parameter that tells it which
     keys to accept.

/L  specifies language of output.
     /Lus   US (American) English-language output
     /Lfr   French-language output
     /Lgr   German-language output
     /Lsp   Spanish-language output
     If the /L parameter is omitted, /Lus [American English] is assumed.

/Nnumber of days (always a number)

/Ospecifies format of output date
  If the /O parameter is omitted, /Od1 is assumed.

/Q   specifies a prompt string for a GET, GETU, or GETK function, or the
     input string for a string-handling function (SUBSTR, LEN, UPPER).

/P   specifies a prefix string for the output
/S   specifies a suffix string for the output
     These optional parameters may always be specified or omitted.
     They must be enclosed in single quotes, double quotes, or
                  square brackets

     Note that "whitespace" will be removed from these strings, so
     formatting of /P and /S strings cannot be controlled using spaces.  To
     format strings, use periods or ASCII 255 (hex'ff') as filler.

       EXAMPLES
          FDATE /Ff                /P"Today is "
          FDATE /Fdif /B12-25-TTTT /P"It is " /S" days until Christmas"

/T   For date functions, /T overrides the time portion of the date on the
     /A parm. (Note that it does NOT override the time portion of the date
     on the /B parm.)  

/V   specifies that output is to be placed in an environment variable
     rather than written to standard output.
     If /V is specified but not followed by the name of an environment
     variable, then /Vfdate is assumed, and output is placed in the FDATE
     environment variable.

/X   Used only with the weekday arithmetic function (/Fw).  By default, if
     if the date specified on the /A parm falls on the day of the week
     specified on the /D parm, then the /A date is considered to be the
     first date meeting the day-of-week criterion.  If the /X parm is
     specified, then the /A date will NOT be considered to meet the
     day-of-week criterion.  See the detailed discussion of weekday
     arithmetic, below.

OVERVIEW OF FUNCTIONS
=====================

Fdate's most important parameter is the function parameter, /F.  Here is a
brief summary of the functions that may be specified on the /F parm, for
example: /Fadd.  Detailed descriptions of each of the functions can be
found on the next few pages.

If the /F parameter is omitted, it defaults to the null string, which
causes Fdate to display its HELP screens.

f         Format the date in the /A parm into format specified in /O parm

add       Add the number of days in the /N parm to the date in the /A parm

sub       Subtract the number of days in the /N parm from the date in the
          /A parm

dif       Return the number of days between dates in the /A and /B parms

w         Do date arithmetic in terms of weeks rather than days.  Using the
          date in the /A parm, a number specified in the /N parm, and a
          day-of-the-week number specified in the /D parm, return the date
          of the /Nth /Day-of-the-week before (or after) /Adate.  

m         Do date arithmetic in terms of months rather than days.  Add the
          number of months in the /N parm to the date in the /A parm.  /N
          may be a negative number.

STRING-HANDLING FUNCTIONS

get       get user input from the keyboard, and produce it as output
          Optionally, display a prompt string.

getu      same as get, but produce output converted to upper case

getk      get a keypress and produce it (converted to upper case)

len       produce the length of a string in the /Q parm

upper     convert the string in the /Q parm to upper case

e         Echo the strings on the /P and /S parameters.

substr    Extract a substring from the /Q parm, starting in column
          specified on /A parm, for a length specified on /B parm.

DATE/TIME COMPARISON FUNCTIONS

comp      Compare the dates in the /A and /B parms. Return LT, EQ, or GT.

tcomp     Compare the times specified on the /A and /B parms.


ORDINARY (AS OPPOSED TO DATE) ARITHMETIC FUNCTIONS

          Functions whose names begin with "#" do ordinary arithmetic, i.e.
          arithmetic on numbers rather than dates.

#add      Add the integers specified on the /A and /B parms.  To do
          subtraction, add a negative number to a positive number.

#dif      returns the difference between the integers specified on the /A
          and /B parms. 

#comp     Compare the integers specified on the /A and /B parms.  Return
          LT, EQ, or GT.

#mod      Modulus.  Divide the integer on the /A parm by the integer on the
          /B parm, and return the remainder.  

#random   Random number.  Returns a random number between zero and the
          number (an integer) specified on the /A parm.  

#mult     Multiply the integer on the /A parm by the integer on the /B
          parm, and return the result.

#div      Divide the integer on the /A parm by the integer on the /B parm,
          and return the result as a decimal number with two decimal
          places.

#idiv     Integer division. Divide the integer on the /A parm by the
          integer on the /B parm, and return the result as an integer.

#2xx      Convert an integer in the range of 0-35 to "extended hex" (XX)
          notation.

FUNCTIONS: DETAILED DESCRIPTIONS
================================


DATE FORMATTING FUNCTIONS
=========================

FUNCTION  FDATE /Ffunc /Adate /Iformat /Oformat
--------  -------------------------------------------
format    this is a synonym for function "f"

f         returns /Adate in format specified by /Oformat
          Since /Aformat and /Oformat can be different, the FORMAT
          function is used to change a date from one format to another.
          Because of the wide variety of output formats, the FORMAT
          function can also be used to determine the day of week of the
          date, whether the date is in a normal or leap year, etc.

EXAMPLES
          FDATE /Ff /A19920101 /Iccyymmdd /O"mn zd, ccyy"
          FDATE /Ff       /Atoday         /Od1
          FDATE /Fformat  /Atoday         /Od1
          FDATE /Ff /If /Afdate.exe /P"FDATE.EXE last updated: " /Ofull

DATE ARITHMETIC FUNCTIONS
=========================

Internally, numbers in Fdate are stored in Turbo Pascal's LONGINT datatype,
which means that Fdate can accept numbers up to 9 digits long.

FUNCTION  FDATE /Ffunc /Nnumdays /Adate /Iformat /Oformat
--------  -------------------------------------------
add       Adds      /Ndays to   /Adate, produces date in /Oformat format
sub       Subtracts /Ndays from /Adate, produces date in /Oformat format

          EXAMPLES
          FDATE /Fadd /N90 /A01-01-1992 /Imm-dd-ccyy /Od1
          FDATE /Fsub /N90 /A01-01-1992 /Imm-dd-ccyy /Od1
          FDATE /Fadd /N90 /Atoday                   /Od1

dif       Returns number of days between /Adate and /Bdate
          Order of the two dates is not significant.

          NOTE THAT:
          For DIF, both dates must be in the SAME format, the input format
          specified in /Iformat.  If the two dates are not in the same
          format, you must first reformat one of the dates using the /Ff
          function, then use DIF to get their difference.

          EXAMPLES
          FDATE /Fdif /A01-01-1992 /B11-11-1992  /Imm-dd-ccyy
          FDATE /Fdif /A11-11-1992 /B01-01-1992  /Imm-dd-ccyy
          FDATE /Fdif /Atoday      /B01-01-1992  /Imm-dd-ccyy

MONTH DATE ARITHMETIC FUNCTIONS
===============================

FUNCTION  FDATE /Ffunc /Nnumdays /Adate /Iformat /Oformat
--------  -------------------------------------------
m         [month arithmetic]

          This function adds /N months to /Adate, and produces a date in
          /Oformat format.  It can be used to do monthly subtraction by
          making the number in the /N parameter a negative number.

          EXAMPLES

          FDATE /Fm /N1  /A03-15-1992 /Imm-dd-ccyy /Omm-dd-ccyy
                  produces:   04-15-1992

          FDATE /Fm /N-1 /A03-30-1991 /Imm-dd-ccyy /Omm-dd-ccyy
                  produces:   02-28-1991

          FDATE /Fm /N-1 /A03-30-1992 /Imm-dd-ccyy /Omm-dd-ccyy
                  produces:   02-29-1992


          Note that a too-simple algorithm for month arithmetic can produce
          non-existent dates.  Subtracting a month from March 30, 1991 (as
          in the second example) could produce a result of February 30,
          1991, a date which cannot exist.  

          Fdate's month arithmetic is more sophisticated than that.  If
          Fdate finds that a simple month-arithmetic operation produces an
          invalid date, it subtracts the minimum number of days required to
          produce a valid date.  

          Thus, in the second example, it produces February 28, 1991, the
          last date in February, 1991.  In the third example, it produces
          February 29, 1992 because 1992 is a leap year.  


Note that telling Fdate to add 12 months to February 29, 1992 produces a
result of February 28, 1993, since 1993 is not a leap year.  See Peter G.
Neumann's INSIDE RISKS column in COMMUNICATIONS OF THE ACM, June 1992 (Vol.
35, No. 6), entitled "Leap-Year Problems":

  Prime Computer's MAGSAV failed at midnight [on Feb 29, 1992]...  G. M.
  Lack noted that MAGSAV probably failed on leap-day because it tried to
  increment the year by one to set a tape label expiration date, and the
  resulting nonexistent date of Feb 29, 1993 threw it for a loop.

WEEKDAY DATE ARITHMETIC FUNCTIONS
=================================

FUNCTION  FDATE /Ffunc /Adate /Iformat /Oformat /Ddow#  /Ndow-count
--------  -----------------------------------------------------------
 w[week arithmetic]
          This function provides a way of doing date arithmetic in terms of
          weeks rather than days.

          This function accepts a date specification in parm /A and
          returns the date of the /Nth /Day-of-the-week
          before or after /Adate.  For example:

          If    /A specifies November 14, 1992
                /D specifies the number for Thursday (i.e., 5)
                /N specifies a week count of 3
          then /Fw returns the date of the third Thursday after
          November 14, 1992. (See full example, below)

          Note that /N may be negative.  If, in the above example, /N
          is specified as -3, then Fdate returns the date of the third
          Thursday BEFORE November 14, 1992.

          The acceptable values for /N (number of weeks) is in
          the range of 99..-99.  A value of zero (i.e. /N0) is invalid.

   A BIT OF TRICKINESS WITH WEEKDAY ARITHMETIC
     There is a small dilemma inherent in the notion of weekday arithmetic. 
     If the date specified on the /A parm falls on the same day of the week
     (say, Thursday) as the day of the week that was specified on the /D
     parm, should (or should not) the /A date be considered the first date
     that meets the day-of-week criterion?  For example, if day X is a
     Thursday, and we specify that we want the first Thursday ("/N1 /D5")
     from day X, should we get day X itself, or the Thursday that is 7 days
     after day X? 

     Depending on what you're trying to do, one or the other kind of
     behavior will be preferable.  Starting with version 9.2, FDATE
     supports both kind of processing.  When using the weekday arithmetic
     function (/Fw), you can determine the kind of processing that takes
     place by specifying (or omitting) the /X (exclude) parm.  That is, if
     the date specified on the /A parm falls on the day of the week
     specified on the /D parm, then...

     IF THE /X PARM IS NOT PRESENT ...
     then the /A date will be considered to be the first date meeting the
     day-of-week criterion.  For example, suppose that /D specified
     Thursday and /A specified Thursday, November 14, 1992.  If /N was 1 or
     -1, then the output date would be the same as the input date, i.e.
     Thursday November 14, 1992.

     IF THE /X PARM IS PRESENT ...
     then the /A date will be EXCLUDED from consideration when looking for
     the first day to meet the day-of-week criterion.  For example, suppose
     that /D specified Thursday and /A specified Thursday November 14,
     1992.  If /N was 1, then the output date would be the following
     Thursday, November 21, 1992.  If /N was -1, then the output date would
     be the preceding Thursday, November 7, 1992.


EXAMPLES
     find date of Thanksgiving (4th Thursday in November) in 1992
         FDATE /Fw /A11-01-1992 /Imm-dd-ccyy /D5 /N4 /Od1
     returns: Thursday November 26, 1992

     find the beginning of the work-week (Monday, 2nd day of week)
     AFTER Thanksgiving, 1992
         FDATE /Fw /A11-26-1992 /Imm-dd-ccyy /D2 /N1 /Od1

     find the beginning of the work-week (Monday, 2nd day of week)
     BEFORE Thanksgiving, 1992
         FDATE /Fw /A11-26-1992 /Imm-dd-ccyy /D2 /N-1 /Od1

     find last Friday's date (even if today is Friday)
        FDATE /Fw /At /D6 /N-1 /X  /P"Last Friday was: "

DATE/TIME COMPARISON FUNCTIONS
==============================

FUNCTION  FDATE /Ffunc /Adate /Bdate /Iformat
--------  -------------------------------------------
comp      compares the dates (time granularity = 1 day)
          specified on the /A and /B parms.
          returns         when
            LT            /A  is less than    (earlier than) /B
            EQ            /A  is equal to     (same as)      /B
            GT            /A  is greater than (later than)   /B

          In addition, the errorlevel is set to a special value:
            LT = 101     EQ = 102     GT = 103



tcomp     compares the times (time granularity = 1 second)
          specified on the /A and /B parms.
          This is useful when input format /If (file) is specified.
          It can be used to compare the timestamps of two files and
          determine which is older.
              EXAMPLE: Fdate /Ftcomp /If /Amyfile.1 /Byourfile.1

          returns         when
            LT            /A  is less than    (earlier than) /B
            EQ            /A  is equal to     (same as)      /B
            GT            /A  is greater than (later than)   /B

          In addition, the errorlevel is set to a special value:
            LT = 101     EQ = 102     GT = 103



COMPARE-FUNCTION ERRORLEVELS
============================

Starting with version 8.3, Fdate's "comparison" functions (comp, tcomp,
#comp) return distinct errorlevels as well as distinct output strings:

          returns         errorlevel
            LT            101
            EQ            102
            GT            103

NUMERIC ARITHMETIC FUNCTIONS
============================

Note that all of Fdate's arithmetic functions operate on integers.  A
decimal number on an input parameter will be rejected, and an error message
will be displayed.

FUNCTION  FDATE /Ffunc /Anum  /Bnum
--------  -------------------------------------------

#add      returns the sum of the integers specified
          on the /A and /B parms.  Can be used to calculate the
          "absolute" minute(second, date) in the future from a given
          "absolute" minute(second, date).   Also useful in generating
          sequences of numbers and looping (see EXAMPLES).

#sub      (not supported)
          Fdate does not provide a numeric subtraction operation as such. 
          To do subtraction, add two numbers, one of which is a negative
          number.  For example, to subtract 3 from 2:
              FDATE /F#add /A2 /B-3          [ returns: -1 ]

#dif      returns the difference between the integers specified on the /A
          and /B parms.  #dif is the same as subtraction in which the
          smaller number is subtracted from the larger number; it will
          never return a negative number.  It can be used to calculate the 
          number of minutes(seconds, days) between two "Absolute"
          minutes(seconds, dates).

#comp     compares the integers specified on the /A and /B parms.
          returns         when
            LT            /A  is less    than /B
            EQ            /A  is equal   to   /B
            GT            /A  is greater than /B

          In addition, the errorlevel is set to a special value:
            LT = 101     EQ = 102     GT = 103

#mod      divides the integer on the /A parm by the integer on the /B parm,
          and returns the remainder.  

          This is useful for determining whether a number is evenly
          divisible by some other number.  If the remainder is 0, then /A
          is evenly divisible by /B.  If a year is evenly divisible by 4,
          for example, then it is an American election year.  If it is
          evenly divisible by 100, then it is a century year, etc.


#mult     multiplies the integer on the /A parm by the integer on the /B
          parm, and returns the result.

#div      (division) divides the integer on the /A parm by the integer on
          the /B parm, and returns the result as a decimal number, with two
          digits to the right of the decimal.

          This is useful for dividing a number (representing the number of
          minutes in some period) by 60 to get the length of the period
          expressed in terms of hours, or by 1440 to get the length of the
          period expressed in terms of days.  Or you could divide a number
          of days by 7 to get the number of weeks, etc.


#idiv     (integer division) divides the integer on the /A parm by the
          integer on the /B parm, and returns the result as an integer.

          This is useful, especially in conjunction with the #mod function,
          for converting a number of minutes into a number of hours and
          minutes, or days and hours and minutes.  See the EXAMPLES
          section, below.

#2xx      (convert number to "extended hex" format)
          "Extended hexadecimal" (XX) notation uses all of the digits, and
          all of the letters of the alphabet, to express numbers in the
          range of 0 to 35 as a single character.  

          This function takes a number supplied on parameter /A, and
          returns a single character in extended hex notation.  The input
          number should be in the range of 0-35.  A number of less than 0
          or larger than 35 is rejected as an error (returns "ERROR" and
          errorlevel of 1).

          EXAMPLE: Fdate /F#2xx /A35    =====> returns the letter Z
 
DATE VALIDATION FUNCTION
========================

v    If the date specified on the /A parm is valid, produces "" (the null
     string).  Otherwise, produces "ERROR" and a non-zero errorlevel by
     triggering Fdate's error-handling function.  (See the section on
     FDATE'S ERROR HANDLING, later in this documentation.)

     When using the /Fv parameter, you will almost always want to check
     success of the date validation by checking the errorlevel, and to
     redirect Fdate's output to NUL (so that when it writes the null
     string, it does not produce a blank line on your screen).

     When processing an input date, Fdate does not reject all invalid
     dates: specifically, it is very forgiving about the number in the day-
     of-the-month part of input dates.  It will accept, for example,
     19931144 (November 44, 1993 in CCYYMMDD format) and process it quite
     happily (as December 14, 1993).  This is not a bug, it is a feature. 
     This feature provides one way (admittedly a crude one) of doing date
     arithmetic.  The date part (JJJ) of a Business Julian input date can
     be used in the same way.  

     This feature can be a drawback, however, if you want to be sure that
     some date (say a date that a user entered as an input parameter) is
     valid.  The /Fv function provides a way of completely checking a date
     for validity.  It will, for example, reject November 44, 1993 as
     invalid. 


STRING FUNCTIONS
================================

GET and GETU (GET USER INPUT) FUNCTIONS
=======================================

get  get user input
getu get user input (uppercase)

     These functions wait for the user to enter an input string, terminated
     by a press of the ENTER key.  Then Fdate simply produces that same
     input string (or in the case of GETU, that input string in all upper
     case) as its output.  

     If the /Q prompt-string parameter is specified, then the prompt string
     is displayed, but a NEWLINE is not written to the screen before
     waiting for the user's input.

     As with Fdate's other forms of output, this output can be displayed,
     redirected to a file, or (if your environment supports Fdate's /V
     parameter) placed into an environment variable.

     This "get" function provides no edit mask for input -- Fdate will
     accept anything.  The situation is helped by the fact that Fdate also
     provides a validate function (/Fv) which can be used to validate the
     user input, so that one can:

          1.   use /Fget to get user input and place it in an environment
               variable 
          2.   use /Fv to validate the date in the Evar
          3.   use the rest of the batch file to process the user input

     See examples: "Get user input" and FORATIM2.BAT

     For a program that provides more sophisticated functions for getting
     user input in batch files (type checking, edit masks, etc.), I
     recommend Bob Stephan's shareware program GET, which is described
     elsewhere in this documentation.

GETK (GET KEYPRESS) FUNCTION
=======================================
getK get keypress 

     This function waits for the user to press an acceptable key, then
     produces the key as its output.  If the key pressed is a letter, then
     the letter is returned IN UPPER CASE.  This feature is designed to
     support simple "pick a menu selection" processing in batch files.

     The GETK function takes a /K "keymask" parameter that tells it which
     keys to accept.  If the user presses an unacceptable key (i.e. one
     that is not in the keymask), the keypress is ignored.

     If no /K parm is specified, the default keymask is:
             ABCDEFGHIJKLMNOPQRSTUVWXYZx
     That is, the default keymask will accept letters and the ESCAPE key.

  Specifying the Keymask

     NOTE THAT THE VALUES SPECIFIED ON THE /K PARM ARE CASE-SENSITIVE.  

     The keymask may contain numbers, uppercase letters, and any of the
     other printable characters on the keyboard.  

     There is no way to tell FDATE to accept "special" keypresses such as
     function keys, ALT or CONTROL keys, arrow keys, etc.

     If the keymask contains an uppercase letter (e.g. "A"), and the user
     presses the corresponding unshifted letter (e.g. "a"), then the
     keypress will be accepted and the uppercase letter will be returned.

     The keymask may contain the following lowercase letters, which have
     special meanings:

       x  represents the ESCAPE key
       e  represents the ENTER (RETURN) key
       z  [a place-holder character]

            Lowercase "z" will be ignored when FDATE decides which
            keypresses are acceptable.  Its presence in the keymask will
            affect the positions of other characters in the keymask, and
            hence the ERRORLEVEL that FDATE returns when the user presses
            an acceptable key.  (For the uses of "z", see "GetK Results
            also in ERRORLEVEL" and "Modifying the Keymask", below.)

     All other lowercase letters are reserved for possible future use.  In
     the current release of FDATE, they are treated like lowercase "z".

     EXAMPLE:  If a keymask of "/kXx" was specified, then if the user
               pressed the (shifted or unshifted) "X" key, then uppercase
               "X" would be returned.  If he pressed the ESCAPE key, then
               lowercase "x" would be returned.

  GetK Results also in ERRORLEVEL

     When the GETK function returns a key, it sets the DOS errorlevel to a
     value corresponding to the position of that key in the keymask.  For
     example, with keymask of "/kABx", if the user presses:

          "A": value returned will be "A", errorlevel will be 1
          "B": value returned will be "B", errorlevel will be 2
       ESCAPE: value returned will be "x", errorlevel will be 3

     If the user presses CONTROL+BREAK, FDATE will abort and return
     errorlevel 255.

     Here is an example batch file:
     ==================================================================
  @echo off
  cls
  echo Demonstration of FDATE's GETK (get keypress) function
  echo Press CONTROL+BREAK to end
  :top
  echo.
  fdate /fGetK /P"You pressed: " /Q"Press a key: "  /K"12ABxe "
  if errorlevel 1  if not errorlevel 2  echo errorlevel : 1
  if errorlevel 2  if not errorlevel 3  echo errorlevel : 2
  if errorlevel 3  if not errorlevel 4  echo errorlevel : 3
  if errorlevel 4  if not errorlevel 5  echo errorlevel : 4
  if errorlevel 5  if not errorlevel 6  echo errorlevel : 5
  if errorlevel 6  if not errorlevel 7  echo errorlevel : 6
  if errorlevel 7  if not errorlevel 8  echo errorlevel : 7
  if errorlevel 255 echo ERRORLEVEL 255
  if errorlevel 255 goto endit
  goto top
  :endit
     ==================================================================

     Note that the keymask may contain blanks if the keymask is enclosed in
     quotes (as in this example batch file).  But remember that Fdate
     eliminates redundant spaces when obtaining its parameter input, so you
     should never include more than one blank in your keymask.

  Modifying the Keymask

     It is often necessary to make program modifications during the life of
     a batch file.  If you are using the GETK function and testing the
     errorlevel rather than the environment, then the insertion or deletion
     of characters into the existing keymask will change the errorlevels
     returned by the following characters in the keymask.  This will force
     you to re-write the errorlevel tests, which may be a big job if the
     keymask is long.

     Here are some tips on how to avoid this work:

         When ADDING a character to the keymask, always add it at the END
          of the keymask.

         When DELETING a character from the keymask, do not actually
          delete it.  Instead, replace it by a lowercase "z".



  Displaying a User Prompt With GETK

     The /Q (user prompt) parameter is especially handy when used in
     conjunction with the GETK function.  If the /Q prompt-string parameter
     is specified (as in the example batch file, above), then the prompt
     string is displayed, but a NEWLINE is not written to the screen before
     waiting for the user's keypress.

     For a program that provides more sophisticated "get key" functions for
     batch files, I recommend Bob Stephan's shareware program GET, which is
     described elsewhere in this documentation.

SUBSTR (SUBSTRING) FUNCTION
===============================

substr
     This function returns a substring of the string supplied in the /Q
     parm, starting in the column supplied in the /A parm, for a length
     supplied in the /B parm.  

     The start column specified in the /A parm may be a negative number; if
     it is, then the start column is calculated from the end of the string
     rather than from the beginning.  This feature makes it easy to extract
     the rightmost characters of a string.  

               Specifically, when the ParmA is negative, the start position
               is calculated using the following formula:

                      StartColumn = length(ParmQ) + 1 + ParmA

             Example:   Fdate /Fsubstr  /A-2 /Qabcd
                      StartColumn = length(ParmQ) + 1 + ParmA
                      StartColumn =      4        + 1 + (-2)     = 3  

  If /Q is omitted, Fdate reports an error.

  If /A is zero, Fdate reports an error.
  If /A is omitted, it defaults to 1 (that is, the start of the string).
  If /A is negative,  and longer than the length of the string, then the
                      start column is 1 (the start of the string)

     If /B (length) is so great that it exceed the length of the /Q input
     string, then only the remainder of the string is returned.

  If /B is zero, Fdate returns a null string.
  If /B is omitted, it defaults to 999.

     EXAMPLES:
          Fdate /Fsubstr /A7 /B2 /Q"STEVE FERG"   ===> "FE"
           Fdate /Fsubstr /A7     /Q"STEVE FERG"   ===> "FERG"
           Fdate /Fsubstr     /B5 /Q"STEVE FERG"   ===> "STEVE"
 
     EXAMPLES using a negative start position:
          Fdate /Fsubstr /a-6 /B3 /Q"1994 Jun 03"   ===> "Jun                   

          rem extract the rightmost 6 characters of a string
           Fdate /Fsubstr /a-6     /Q"1994 Jun 03"   ===> "Jun 03"

  rem pad YEAR environment variable to the left with zeroes, 
  rem to make sure it is 4 bytes long
  Fdate /Fsubstr /A-4 /q0000%year% /vyear


     REMEMBER that Fdate eliminates redundant spaces when obtaining its
     parameter input:

           Fdate /Fsubstr /A7     /Q"STEVE FERG"      ===> "FERG"
           Fdate /Fsubstr /A7     /Q"STEVE  FERG"     ===> "FERG"
           Fdate /Fsubstr /A7     /Q"STEVE    FERG"   ===> "FERG"

LEN (LENGTH) FUNCTION
=====================

len       Produces a number that is the length of the string on the /Q
          parm.


UPPER FUNCTION
===============

upper     Produces the string on the /Q parm, converted to upper case.



ECHO FUNCTION
=============

e    Produces only the strings specified using the /Q, /P, and /S
     parameters.  Justification, if specified using the /J parm, is applied
     only to the string, if any, supplied on the /Q parm.

You can use /Fe for situations in which you want Fdate to produce output
that doesn't include any sort of date.  In these cases, Fdate functions
just like the DOS "echo" command.  

The /Fe function is especially useful in conjunction with the /J (justify)
parm (see below).

One nifty feature of /Fe (although one that will be of interest only to
extreme batch-file power users) is its ability, when used in conjunction
with /V, to put a character into an environment variable that the SET
command would not accept: characters such as an equal-sign "=" , the
redirection symbol ">", and the pipe symbol "|".

/J: JUSTIFYING OUTPUT
==========================
Using the /J (justify) parameter, it is possible to right, center, or left-
justify FDATE's output, truncate it, or pad it with a certain character.   

Note that /J is not a function, but a parameter.  The /J parameter may be
used in conjunction with any of FDATE's functions.  (It is discussed here,
with the string-handling functions, because that's where it seemed most at
home.)

Justification takes place AFTER the strings specified on the /P (prefix)
and /S (suffix) parms have been added to the output.

  The format of the /J parm is:  /J"tp##"         where

  t is a single character indicating the type of justification desired:
   Rright
   Lleft
   Ccentered

  p  is a single character specifying the character to be used to pad the
     output out to the desired length.  The most common values for this
     character will be the period (".") and the blank.  In order for a
     blank to be recognized as a pad character (and not to be taken as the
     terminator of the /J-parm value), the /J-parm value must be enclosed
     in single or double quotes, e.g.:   /J"C 79"

##   is a number that specifies the length of the field within which
     justification should take place.  This must be a number between 1 and
     240.

     If ## is less than the length of the un-justified output string, then
     the un-justified output string will be truncated to ## characters,
     starting at the point specified by the justification type (i.e. at the
     right, left, or center of the un-justified output string).


 SOME USES FOR THE /J PARM

  (Most of these uses are illustrated in HOLIDAYS.BAT, which is included
  in the FDATE distribution ZIP file.)

  In conjunction with the "echo" function (/Fe), the /J parm can be used
  to justify any value that you wish, not just output dates created by
  Fdate.  Put the value to be justified in the /Q parm.  Put a title, for
  example, as the value of the /Q parm, and specify center justification,
  padded with spaces, to a length of 79 characters (/J"c 79").  This will
  display the title, centered on the screen.

  If you use the "echo" function and the /J parm, and specify the /Q parm
  but do not specify a value for it, then only the pad character will be
  displayed. (That is, the null string will be padded with the pad
  character to the desired length.) 

  EXAMPLE:  This is a handy way to draw horizontal lines of dashes,
            dots, or any other desired character.
                    FDATE /FE  /Q  /JC-79 

  The /J parm can be used to left-pad a number with zeroes.

  EXAMPLE:  Many of Fdate's input formats require the year to be in
            complete 4-digit CCYY format.  If your batch file obtains a
            value for YEAR from the user, the user might enter a YEAR
            that is less than 1000.  You can add leading zeroes to YEAR
            by right justifying it, padded it with '0' to a length of 4. 
            
  FDATE  /Fe  /Q%year%  /JR04  /vyear

  Because /J can be used to truncate a string to a specified length, it
  can be used to extract the rightmost, leftmost, or centermost ##
  characters of a string. 


EXAMPLES

  Fdate /Fe /J"C 79" /Q"SCREEN TITLE"
     Fdate's output is not put into an environment variable, so it will be
     displayed on the screen.  This command will echo the string "SCREEN
     TITLE" to the screen, centered in a field 79 characters long (that is,
     centered on the screen), and padded to the left and right with blanks.

  Fdate /Fe /J"L.40" /Q"Next report due date" /Vtitle
  Fdate /fadd /N60  /Od1 /Q"%title% "
     The first command left-justifies "Next report due date" in a string 40
     characters wide, padded to the right with periods, and puts it into
     the TITLE environment variable.  In the second step, the TITLE
     environment variable is used as the label for a date 60 days in the
     future.  In the second step, note the space between the end of %title%
     and the trailing double-quote.  This leaves a nice space between the
     dot leader and the date.

  For more examples, see HOLIDAYS.BAT.

DATE FORMATS
============

SYMBOL CONVENTIONS
==================

The following symbols are used in specifying date formats:

SYMBOL  EXAMPLE   MEANING
------  -------   -------------------------------------
cc        19      century
yy        93      year
mm        02      month
zm         2      month without leading zero
dd        08      day
zd         8      day   without leading zero
mn       February month name
mn3      Feb      month name, first 3 characters only
dow      Tuesday  day of week
dow3     Tue      day of week, first 3 characters only
dow#      3       day of week as a number (Sunday=1, Monday = 2, etc.)
today             is a "pseudodate" representing the current date
t                 is an alias for the "today" pseudodate
hh:mm    09:05    hours and minutes
hhmm     0905     hours and minutes
ss        13      seconds



PSEUDODATES
===========

t (or today)
          can be used with either /A or /B, e.g. /Atoday or /At.
          This is the default for both /A and /B.  That is, if /A is not
          specified, /At is assumed, and the same for /B.

          NOTE THAT
          "Today" as a date specification operates independently of any
          input format.  You need to specify an input format (either
          explicitly via the /I parameter, or implicitly by accepting the
          default value of /I) only for input dates that are supplied to
          Fdate in some other way than via the "today" pseudodate: as a
          date literal, a filename, etc.

EXAMPLES:
          rem Get the date that is 90 days from today
          FDATE /Fadd /N90 /Atoday /Omm-dd-ccyy
          FDATE /Fadd /N90 /At     /Omm-dd-ccyy

          rem determine if this year is a leapyear
          FDATE /Ff /At /OLY




tttt      When used in place of a 4-digit CCYY string, "tttt"
          will cause Fdate to use today's 4-digit year (CCYY).

tt        When used in place of a 2-digit DD, MM, or YY string,
          "tt" will cause Fdate to use today's day-of-the-month,
          month, or 2-digit year, respectively.

          Note that "tt" can NOT be used for the YY portion of a CCYY
          input year.  The following, for example, is NOT valid:
               FDATE /Ff /Imm-dd-ccyy /A01-01-19tt /Od1

EXAMPLES:

     FDATE /Ff /Imm-dd-ccyy /A01-01-tttt
     FDATE /Ff /Imm-dd-yy   /A01-01-tt 

     rem report the 15th day of this month, this year
     FDATE /Ff /Imm-dd-ccyy /Att-15-tttt

     rem Show the first Monday in the second quarter of this year
     FDATE /Fw /Iccyymmdd /Atttt0401 /D2 /N1  /P"First Monday in QTR#2: "

     rem Show the last Friday on/before the 15th of this month.
     FDATE /Fw /Iccyymmdd /Atttttt15 /D6 /N-1 /P"Friday before the 15th: "


INPUT DATE FORMATS
==================


ABSOLUTE DATE INPUT FORMATS
===========================

day#           727198      "Absolute date": date expressed as number of
                           days since the beginning of the calendar.  "1"
                           for January 1, 0001, "2" for January 2, 0001,
                           etc.

minute#         33088       "Absolute minutes": time expressed as number
                            of minutes  since midnight, January 1, 1990.

CALENDAR DATE INPUT FORMATS
===========================

FORMAT      EXAMPLES      DISCUSSION
------      ---------     -----------------------------
 ccyymmdd    19922002


On the /I (input format) parm, the separator character of the following
input formats must be a dash.  This simply tells Fdate that the input
date will contain SOME separator character.  The separator character that
actually occurs in dates in the /A and /B parms is ignored, and may be
any non-numeric character: a slash "/", a dash "-", a dot ".", etc.

In specifications that begin with "mm-dd" or "dd-mm", leading zeros need
not be present in the "mm" and "dd" part of the date.

ccyy-mm-dd  1992-02-20    Leading zeros MUST be present, since the
            1992/02/20    date does not begin with dd-mm or mm-dd.    
            1992.02.20    


mm-dd-ccyy  02-20-1992    
            02/20/1992    The dash represents ANY non-numeric character.

             2-5-1992     Leading zeros need not be present.
             2/5/1992

mm-dd-yy    02-05-92      February 5, 1992.  See discussion of
             2/5/92       FDATE'S CENTURY ASSUMPTION ALGORITHM, below

                          ---------------------------------------
                          In the following formats, days
                          precede months  (European style)
                          ---------------------------------------

dd-mm-ccyy  05-02-1992 
            05/02/1992 

             5-2-1992     Leading zeros need not be present.
             5/2/1992

dd-mm-yy    05-02-92      February 5, 1992.  See discussion of
             5/2/92       FDATE'S CENTURY ASSUMPTION ALGORITHM, below

BUSINESS JULIAN DATE INPUT FORMATS
==================================

These are formats for "business julian" dates: dates expressed as the
number of days from the beginning of the year, when January 1 is day 1.

EXAMPLES:

      date      BUSINESS JULIAN DATE
  -----------   --------------------
  Jan  5, 1992  92005
  Jan  5, 1993  93005
  Dec 31, 1993  93365  [Dec 31 is 365th day of year 1993]
  Dec 31, 1996  96366  [Dec 31 is 366th day, because 1996 is a leap year]

-----------------------------------------------------------------------
NOTE:   * JJJ can be 1 - 5 digits
        * may include a prefix of a plus or minus ( + or - ) sign
-----------------------------------------------------------------------

FORMAT      EXAMPLES      DISCUSSION
------      ---------     -----------------------------
ccyyjjj     1992003       Third day of 1992, i.e. Jan 3, 1992
            19923         Third day of 1992
            tttt003       Third day of this year
            tttt3         Third day of this year

  yyjjj       92003       Third day of 1992
              923         Third day of 1992
              tt003       Third day of this year
              tt3         Third day of this year
              01003       Third day of 2001           See
                          FDATE'S CENTURY ASSUMPTION ALGORITHM, below

NOTE THAT FDATE WILL ACCEPT "JJJ" OF LESS THAN 1 & MORE THAN 366.
-----------------------------------------------------------------

  yyjjj       tt1000      the 1000th day from beginning of this year
              tt0         last day of last year
              tt-1        next-to-last day of last year

FDATE /Ff /Iccyyjjj /Od1 /A1992-1  produces... Monday December 30, 1991
FDATE /Ff /Iccyyjjj /Od1 /A19920   produces... Tuesday December 31, 1991
FDATE /Ff /Iccyyjjj /Od1 /A1992+1  produces... Wednesday January 1, 1992

FDATE /Ff /Iccyyjjj /Od1 /A1992366 produces... Thursday December 31, 1992
FDATE /Ff /Iccyyjjj /Od1 /A1992367 produces... Friday January 1, 1993

This feature allows limited date arithmetic with ordinary business
Julian days.  For example, 90 days from tt300 can be shown by:

                  FDATE /Ff /Iyyjjj /Att390

GETTING DATE/TIME A FILE WAS CREATED
====================================

FORMAT      EXAMPLES      DISCUSSION
------      ---------     -----------------------------
f           MYFILE.1      Input format F (file) tells Fdate that
                          /A and /B will specify filenames, and that
                          Fdate should pick up the input date and time
                          from the date/time stamp on a file.

Example: FDATE /Ff /If /Afdate.exe /P"FDATE.EXE last updated: " /Ofull

     Note that if you specify /If, then both /A and /B will be interpreted
     as filenames.
 
     Because the input format applies to both /A and /B parms, it is not
     possible to put a filename in /A and a date literal in /B, and then
     (say) use the "comp" or "dif" function to compare them.  You must
     first extract the file's date into an environment variable, and then
     compare that environment variable to the date literal.

          The only exception to this rule is the pseudodate "t" (i.e. /At
          or /Bt) which will pick up the current date and time from the
          system clock.  This feature will allow you, for example, to
          compare the date of a file to today's date (see EXAMPLES).

     A filename may (but need not) be fully qualified: i.e. "MYFILE.1" and
     "C:\DBASE\WORKDIR\MYFILE.1" are both acceptable.

     A filename may contain wildcards.  If it does, the date/time stamp
     will be retrieved from the first file that FDATE finds that meets the
     filespec.  Giving FDATE a filespec containing a wildcard is pretty
     useless, but FDATE will not reject it.

OUTPUT DATE FORMATS
===================

FORMAT        EXAMPLES      COMMENTS
------        ---------     -----------------------------
dd-mn3-yy     08-Feb-92     CompuServe-style date
  yy            93          2-digit year number
ccyy          1993          4-digit year number (includes century)
ccyymm        199302        useful for triggering monthly processing
ccyymmdd      19930208      useful for putting current date in filename
  yymmdd        930208      PKZIP's Japanese date format
    mmdd          0208
     mmddyy      020892    PKZIP's American date format
     mmddccyy   02081992 
      mm            02      2-digit month number
      zm             2      month number, no leading zeros
      dd            08      2-digit day-of-month number
      zd             8      day-of-month number, no leading zeros

In the following formats, months precede days (American style)
------------------------------------------------------------------
mm/dd/ccyy    02/08/1993
mm-dd-ccyy    02-08-1993
mm.dd.ccyy    02.08.1993    British-style dates

zm/zd/ccyy     2/8/1993     no leading zeros in day or month
zm-zd-ccyy     2-8-1993     no leading zeros in day or month
zm.zd.ccyy     2.8.1993     British-style dates

mm/dd/yy      02/08/92
mm-dd-yy      02-08-92
mm.dd.yy      02.08.92      British-style dates

zm/zd/yy       2/8/92       no leading zeros in day or month
zm-zd-yy       2-8-92       no leading zeros in day or month
zm.zd.yy       2.8.92       no leading zeros in day or month


In the following formats, days precede months  (European style)
------------------------------------------------------------------

ddmmccyy      02081993
   ddmmyy        020893PKZIP's European date format

dd/mm/ccyy    02/08/1993
dd-mm-ccyy    02-08-1993
dd.mm.ccyy    02.08.1993    British-style dates

zd/zm/ccyy     2/8/1993     no leading zeros in day or month
zd-zm-ccyy     2-8-1993     no leading zeros in day or month
zd.zm.ccyy     2.8.1993     British-style dates

dd/mm/yy      02/08/93
dd-mm-yy      02-08-93
dd.mm.yy      02.08.93      British-style dates

zd/zm/yy       2/8/93       no leading zeros in day or month
zd-zm-yy       2-8-93       no leading zeros in day or month
zd.zm.yy       2.8.93       British-style dates

DAY-OF-WEEK AND MONTH OUTPUT FORMATS
====================================

dow#           5            Sunday=1, Monday=2 .... Saturday=7.

dow            Thursday     name of day of week
               jeudi        if /Lfr specified
               Donnerstag   if /Lgr specified

dow3           Thu          first 3 characters of name of day of week
               jeu          if /Lfr specified
               Don          if /Lgr specified

mn             February     name of month
               fevrier      if /Lfr specified
               Februar      if /Lgr specified

mn3            Feb          first 3 characters of name of month
               fev          if /Lfr specified
               Feb          if /Lgr specified



MISCELLANEOUS OUTPUT FORMATS
============================

full      9:05 pm on Wednesday February 5, 1992
          9:05 pm, mercredi le 5 fevrier 1992  [/Lfr specified]
          9:05 pm, mircoles el 5 de febrero de 1992 [/Lsp specified]
          Mittwoch, 5. Februar 1992, 21:05     [/Lgr specified]

d1        Saturday, February 5, 1992
          samedi le 5 fevrier 1992      [/Lfr specified]
          Mittwoch, 5. Februar 1992     [/Lgr specified]

ddmn3yy   05Feb92

xxx       2CP  (...Dec 25, 1992)
          This format represents dates for the years 1990-2024 in 3
          characters of "extended hex" ("XX") notation.  For more on XX
          notation, see the discussion of the #2XX function.

          The first character is the XX representation of the number of
          years since 1990 (1990 = 0, 1991 = 1, etc.).  If you attempt to
          output a date outside of the 1990-2024 range in XXX format, Fdate
          will report an error (i.e. return "ERROR" and errorlevel of 1).

          The second and third characters contain the XX representation of
          the month-number and day-of-month-number, respectively.

          EXAMPLE: "1993 Feb  1"  is represented as  "321"
          EXAMPLE: "2000 Dec 25"  is represented as  "ACP".

-----------------------------------------------------------------------
NOTE that the following formats contain embedded spaces.  Consequently
they must be enclosed in double quotes. EXAMPLE: /O"mn zd, ccyy".
-----------------------------------------------------------------------
"zd mn ccyy"      5 February 1992
"zd mn, ccyy"     5 February, 1992
"zd. mn ccyy"     5. February 1992   [German-style date format]
"zd. mn3 ccyy"    5. Feb 1992        [German-style date format]
"mn3 dd ccyy"     Feb 05 1992
"mn3 dd, ccyy"    Feb 05, 1992
"mn zd, ccyy"     February 5, 1992



LEAP-YEAR FLAG OUTPUT FORMAT
============================

LY              0     "1" if date occurs in a leapyear, otherwise "0".

                 365 + this number gives total number of days in the year.
                  28 + this number gives total number of days in February.




TIME OUTPUT FORMATS
===================
See also: the section on the /T (parm /A time override) parameter.

t1            9:05 am
              9:05 pm

tdos          9:05:10:10a     format used in DOS's TIME command 
              9:05:10:10p

HH:MM        09:05      24-hour time, hours:minutes
             21:05
HHMM         0905
             2105

HH:MM:SS     21:05:30   24-hour time, hours:minutes:seconds
HHMMSS       210530

HH:MM:SS:CC  21:05:30:09   24-hour time, in
HHMMSSCC     21053009      hours:minutes:seconds:hundredths of seconds


BUSINESS JULIAN DATE OUTPUT FORMATS
===================================

These are formats for "business julian" dates: dates expressed as the
number of days from the beginning of the year, when January 1 is day 1.

EXAMPLES:

      DATE      BUSINESS JULIAN DATE
  -----------   --------------------
  Jan  5, 1993  93005
  Dec 31, 1993  93365  [Dec 31 is 365th day of year 1993]
  Dec 31, 1996  96366  [Dec 31 is 366th day, because 1996 is a leap year]


FORMAT        EXAMPLES      DISCUSSION
------        ---------     -----------------------------

ccyyjjj       1992027       Jan 27, 1992
  yyjjj         92027       "Business Julian" date expressed as number
    jjj           027       of days since January 1 of the same year.
    zzj            27       Note leading zero suppression in "zzj".


ABSOLUTE DATE/TIME OUTPUT FORMATS
=================================
See also: the section on the /T (parm /A time override) parameter.


month#          23927      "Absolute month": date expressed as number of
                           months since the beginning of the calendar. 
                           Returns "1" for any date in January, 0001, "2"
                           for any date in February, 0001, etc.

day#           727198      "Absolute date": date expressed as number of
                           days since the beginning of the calendar. 
                           Returns "1" for January 1, 0001, "2" for
                           January 2, 0001, etc.

minute#         33088       "Absolute minutes": time expressed as number
                            of minutes  since midnight, January 1, 1990.

second#        633088       "Absolute seconds": time expressed as number
                            of seconds  since midnight, January 1, 1990.


Running FDATE with /O parameter for an "absolute time" produces a
number based on the current time of day and the date in the /A parm.

If, on January 10, 1992 at 2 pm, you run FDATE this way:
       FDATE /Ff /Atoday /Ominute#
it will produce the absolute minute for January 10, 1992 at 2 pm.

If, on January 10, 1992 at 2 pm, you run FDATE this way:
       FDATE /Ff /A01-15-1992 /Imm-dd-ccyy  /Ominute#
it will produce the absolute minute for January 15, 1992 at 2 pm.


/T: TIME OVERRIDE PARAMETER
===============================

You may override Fdate's use of the current time -- for the /A parameter
only -- by using the /T parameter.  The /T parameter specifies a time of
day in the 24-hour format hh:mm:ss (hours:minutes:seconds).  Leading zeros
in each of the three fields (hh, mm, ss) may be omitted.  The seconds field
may be omitted; if omitted, it defaults to "00".

Note that the /T parm overrides the time portion of the /A date, but it
does NOT override the time portion of the /B date.

If, on January 10, 1992 at 2 pm, you run FDATE this way:
       FDATE /Ff /A01-15-1992 /Imm-dd-ccyy  /Ominute#  /T5:12
it will produce the absolute minute for January 15, 1992 at 5:12 am.

The most frequent and important use of the /T parm is with the format
function (/Ff) to obtain the "absolute" minute of a specific date and time. 
Once we have the absolute minutes of two different date/times, we can
easily obtain the time between them (expressed in days, hours, and minutes)
by using Fdate's #dif, #idiv, and #mod functions.  (In the EXAMPLES
section, see the example that contains FORATIME.BAT.)

It is also possible to use /T in conjunction with the time compare function
(/Ftcomp).

@echo ON
cls
rem  Since both /A and /B default to the current date and time,
rem  and since /T parm overrides the time only for the /A parm ...

rem   ... during daytime hours, this will always return LT
Fdate /ftcomp /T00:00:00
rem   ... during daytime hours, this will always return GT
Fdate /ftcomp /T23:59:59


/J: JUSTIFYING OUTPUT
==========================
Using the /J (justify) parameter it is possible to right, center, or left-
justify FDATE's output.  See the discussion of JUSTIFYING OUTPUT in the
section on string-handling functions.



HOW TO PUT FDATE OUTPUT INTO AN ENVIRONMENT VARIABLE
====================================================


CALL A BATCH FILE
=================

  The most basic way to put FDATE's output into an environment variable,
  although not the most convenient, is to:
  *  use the /P (prefix string) feature to create a DOS "SET" statement,
  *  redirect the output to a batch file, and then
  *  CALL the batch file.  

  Since CALL first appeared in DOS 3.3, you will need DOS 3.3 or greater
  to use this technique.

       FDATE /Ff /Atoday /O"mn zd, ccyy" /P"@SET FDATE=" >JUNKTEMP.BAT
       call JUNKTEMP.BAT
       del  JUNKTEMP.BAT



USE AN ENVIRONMENT-MANIPULATION UTILITY
=======================================

  There are shareware and public domain utilities that are written
  specifically to manipulate environment variables, and do that job very
  well.  FDATE's output can be put into an environment variable by piping
  it to one of these utilities.  When piping FDATE output to a utility,
  you can prevent the output from being ECHOed to the screen by
  redirecting the output to NUL.

  Of these utilities, I can especially recommend Bob Stephan's GET
  (because it is very inexpensive and very powerful and flexible) and PC
  Magazine's STRINGS (free to ZiffNet members).  See the EXAMPLES section
  for examples of how to use STRINGS and GET to put FDATE's output into an
  environment variable.

     As of March 14, 1994, the current version of GET is 2.6.  On
     CompuServe, use IBMFF to look for GET25.ZIP (which contains version
     2.5 and the full documentation file) and GET26u.ZIP (the version 2.6
     update of GET, which contains version 2.6 of GET, but not the full
     documentation).  Look in CIS:IBMSYS, Library 1, or for GET.ZIP in
     ZNT:UTILFORUM, lib 16.  GET is also available from the Public Software
     Library in Houston.

     As of February 14, 1992, the current version of STRINGS is 1.3. On
     CompuServe, look for STRING.ZIP in the PC Magazine Utilities Lib of
     ZNT:UTILFORUM.  STRHYP.ZIP contains good hypertext documentation on
     STRINGS.

FDATE'S /V PARAMETER
====================

  Manipulating the environment is an incredibly tricky business.  There
  are questions of the local versus master environment, the version of DOS
  you are running, and the environment under which you are running (DOS,
  Windows, QuarterDeck, Carousel).  In order to keep FDATE focussed on
  date-related issues, versions of Fdate prior to 6.1 did not attempt to
  put output directly into an environment variable.  Instead, FDATE's
  output was written to standard output, that is, it was displayed on the
  screen. Output could then be redirected to a batch file, or piped to a
  utility (such as STRINGS or GET), that would put the output into an
  environment variable.

  Starting with version 6.1, Fdate supports a /V (environment variable)
  parameter.  A user can use /V to tell Fdate to put its output directly
  into an environment variable in the "parent" environment.

  NOTE that due to the complexities of manipulating the environment, there
  may be circumstances where /V doesn't work.  These include running FDATE
  when you have shelled out to DOS from another program, have put the
  command processor in upper memory (UMB) (see below), are running under
  Carousel, etc.  In such cases, you may be able to use one of the more
  basic techniques described above.  For a list of environments in which
  the /V option has been reported as NOT working, see the next section.



  /Vevar tells Fdate to put output into an environmental variable whose
  name is "evar".  For example:

                Fdate /Ff /Vdate1

  will set the environment variable DATE1 to the current date.  If you
  type SET at the DOS prompt, you should see something like:

                DATE1=Friday February 14, 1992

  If you specify /V without an evar name, the evar name defaults to FDATE.

     Example :       Fdate /Ff /V
     produces:       FDATE=Friday February 14, 1992

  If you do not use /V, Fdate output is written to standard output, i.e.
  to the screen.

/V WHEN RUNNING UNDER MICROSOFT WINDOWS
=======================================

Starting with FDATE version 8.4 -- thanks to a Turbo Pascal routine from
the Turbo Professional library (see below) provided by Kim Kokkonen of
TurboPower Software -- FDATE's /V parameter works even in a Windows DOS
box, assuming you have enough environment space available.

The problem is that when you shell out to a DOS box under Windows, the size
of the DOS environment is normally limited to the amount actually in use by
DOS at the time when you first started Windows (rounded up to multiples of
16).  In short, when you shell out to DOS under Windows, you have little or
no free environment space left. 

The trick to giving yourself a decent amount of environment space in a
Windows DOS box, is to edit SYSTEM.INI and put the following line in the
[NonWindowsApp] section:

  [NonWindowsApp]
  CommandEnvSize=1024

This tip is from Brian Livingston's "Windows 3.1 Secrets", p. 225. 
According to Livingston, "This command allocates 1,024 bytes of
conventional memory to the environment space of each DOS session you start.
(You can choose any value you want, but it should probably be a multiple of
16 bytes...)"

It's a good idea to be generous here, because the default prompt for a
Windows DOS box (the one with the highlighted bar across the top of the
screen) consumes a lot more environment space than the simple "$p$g" of the
conventional DOS prompt.

An alternative technique, if you're running Windows 3.0 or earlier, is
always to start Windows from a batch file that contains the following line,
executed BEFORE you start Windows:

   SET DUMMY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

This will reserve a chunk of environment space that will be copied into the
environment in the Windows DOS box.  Then, as one of the first statements
in any batch file that you run under Windows, put

   SET DUMMY=

This will free up the environment space used by all those "X"s.  

For a good treatment of running DOS apps under Windows, including a
discussion of the environment, I recommend Brian Livingston's WINDOWS 3.1
SECRETS, chapter 7.


/V WHEN RUNNING UNDER WINDOWS NT
=======================================

Early in 1996, reports began trickling in of users having difficulty with
Fdate's /V feature (setting the value of an environment variable) when
running under Windows NT.  To make a long story short, in many cases,
Fdate's /V feature doesn't work under Windows NT.  Unfortunately, this
situation cannot be corrected.  Microsoft has never made it easy to access
the environment programmatically, and the situation has become worse in
Windows 95 and Windows NT.  The situation has become so difficult that
TurboPower Software, which markets add-on utilities, has withdrawn support
for utilities that change environment variables. Since Fdate uses these
utiltities, it is virtually certain that I will ever be able to make
Fdate's /V feature work under NT, in cases where it does not now work. 

This does not mean, however, that Fdate can't be used with NT.  What it
means is that, when running Fdate under NT, we have to fall back on a more
basic method of setting an environment variable.  This involves creating a
temporary batch file that sets the variable, then running and deleting the
batch file.  It's primitive, but it works.

This technique is described elsewhere in this documentation, but I will
repeat it here for convenience's sake.

CALL A BATCH FILE
=================

The most basic way to put FDATE's output into an environment variable is
to:

  *  use the /P (prefix string) feature to create a DOS "SET" statement and
  *  redirect the output to a temporary batch file, and then
  *  CALL the batch file, and then  
  *  delete the batch file (clean up after the operation). 

EXAMPLE:

       FDATE /Ff /At /Occyymmdd /P"@SET FDATE=" >JUNKTEMP.BAT
       call JUNKTEMP.BAT
       del  JUNKTEMP.BAT

In this example, the result will be that the FDATE environment variable is
set to today's date, in ccyymmdd format.

Turbo Professional: "Highly Recommended"

  Thanks to a Turbo Pascal routine from the Turbo Professional library
  (provided by Kim Kokkonen of TurboPower Software)  FDATE's /V parameter
  works even in a Windows DOS box.

  If you do serious Turbo Pascal programming, you should have Turbo
  Professional or Object Professional library.  Turbo Professional is a
  library of about 600 routines to do all sorts of useful stuff in Turbo
  Pascal programs, including:

     CRT unit emulation, with many added features
    Popup windows, virtual screens, and pulldown menu systems.
    Full screen data entry with formatting and data validation.
    Complete mouse support, keyboard macros, runtime error recovery.
    A context sensitive popup help unit.
    Units for picking from lists of items, including filenames.
    Easy and reliable ways to make your program memory resident.
    Interrupt service routine handlers, extended & expanded memory access.
    BCD arithmetic, including transcendental functions & the Form routine
    Sorting and searching.
    Extensive string manipulation & strings longer than 255 characters.
    Arrays larger than 64K (in RAM, EMS, or paged to disk)

For more information, call TurboPower at 1-800-333-4160 (9-5 Mountain
time), send CompuServe mail to 76004,2611, or visit the CompuServe
TurboPower forum in PCVENB section 6.

/V WHEN USING 4DOS, NDOS, AND UMB
=================================
    --------------------------------------------------------------
    I have received the following report from Aran Spence about
    circumstances in which FDATE /V will not set a variable
    in the master environment.  This report leads me to believe
    that FDATE /V may also fail to work with MS-DOS if you put
    the command processor or the environment in Upper Memory.
                    Note, however, that this behavior has not been tested
                    with FDATE 8.4's new environment-handling routines.
    --------------------------------------------------------------
Steve,

There are options with 4DOS and NDOS to load the environment and part
of the command processor into upper memory blocks.  When one of these
options is used, FDATE /V can't find the environment and produces the
message:

   ERROR
   @echo ERROR: Master environment not found
   @pause

If you have a 4DOS.INI file, it has to contain these lines for FDATE /V
to work:

   UMBEnvironment = No
   UMBLoad = No

If you have NDOS, the SHELL statement in CONFIG.SYS cannot contain
any reference to UMB loading via /U (which puts NDOS.COM in UMB), nor
can it contain a statement of the form:
                /E:xxxU
(which puts xxx bytes of the environment in UMB via the "U" parameter).

Also, NSTART.BTM or 4START.BTM cannot contain
         SET NDSHELL=/e+xxxU /U
in which both U's represent UMB loading of the command processor and the
environment during secondary shells.

FDATE'S ERROR HANDLING
======================

   If FDATE detects an error:

     (1) it will return an errorlevel of 1 (rather than 0), and
     (2) its output will be 3 lines:
       * the word ERROR
       * a DOS batch-file ECHO statement that displays an error message
       * a DOS batch-file PAUSE statement

   If Fdate output is displayed directly, or redirected to NUL,
   you can detect an error by testing the errorlevel for a value of 1.

   If Fdate output is piped to an environment manipulation utility such
   as STRINGS or GET, the environment variable will be set to ERROR.
   Errorlevel will be set by STRINGS/GET, and will probably be 0.
   In such a case, the only way to detect an error is to test the
   environment variable for the value ERROR.

   If FDATE output is redirected to a batch file, which is then
   CALLed to set an environment variable, the batch file will:
     * set the environment variable to ERROR,
     * ECHO the error message, and
     * pause.
   You can detect an error by testing errorlevel for the value 1
   either before or after you CALL the batch file, or 
   by testing the environment variable for the
   value ERROR, AFTER you have CALLed the batch file.

----------------------------------------------------------------------

 EXAMPLE:
   rem use FDATE to check validity of year in parm %1
   Fdate /Fv /Imm-dd-ccyy /ATT-TT-%1 > nul
   if errorlevel 1 echo Year parm [%1] is not valid.
   if errorlevel 1 goto endit

 EXAMPLE:
   rem use GET with FDATE, to put FDATE output into %year%
   Fdate /Ff /Imm-dd-ccyy /ATT-TT-%1 /Occyy | GET ZE /V%year% >nul
   if (%year%)==(ERROR) echo Year parm [%1] is not valid.
   if (%year%)==(ERROR) goto endit

 EXAMPLE:
   rem use a batch file with FDATE, to put FDATE output into %year%
   Fdate /Ff /Imm-dd-ccyy /ATT-TT-%1 /Occyy /P"@set year=">junktemp.bat
   call junktemp.bat
   del  junktemp.bat
   if errorlevel 1 echo Year parm [%1] is not valid.
   if errorlevel 1 goto endit

EXAMPLES OF HOW TO USE FDATE
============================

:01 Display Fdate output on screen
:==================================================================
FDATE /Ff /At /Od1 /P"Today is "


:02 Redirect FDATE output to a file
:==================================================================
FDATE /Ff /At /Od1 /P"Today is " >FDATE.OUT


:03 Put FDATE output in an environment variable using a batch file
:==================================================================
FDATE /Ff /Atoday /O"mn zd, ccyy" /P"@SET DATE1=" >JUNKTEMP.BAT
call JUNKTEMP.BAT
del  JUNKTEMP.BAT


:04 Put FDATE output in an environment variable using /V parm
:==================================================================
FDATE /Ff /Atoday /O"mn zd, ccyy" /Vdate1


:05 Put FDATE output in an environment variable using STRINGS
:==================================================================
FDATE /Ff /Atoday /O"mn zd, ccyy" |STRINGS date1= ASK >NUL


:06 Put FDATE output in an environment variable using GET
:==================================================================
FDATE /Ff /Atoday /O"mn zd, ccyy" |GET ZE /Vdate1 >NUL


:07 Get user input
:==================================================================
@echo off
cls
echo Enter a date in mm-dd-ccyy format for validation

:: get user input
fdate /fget /vUserDate1

:: validate user input using /Fv (validate function)
fdate /fv /A%UserDate1% >nul
if errorlevel 1 echo Invalid date: %UserDate1%
if errorlevel 1 goto endit

:: put your batch file processing here ...
echo Processing date: %UserDate1%

:endit
:: cleanup
set UserDate1=


:08 Get a user menu selection
:==================================================================
@echo off
:start
cls
echo ===========================================================
echo             MAKE A MENU SELECTION
echo ===========================================================
echo   A   DIR *.*
echo   B   DIR *.BAT
echo.
echo Press ESC to exit
echo.
echo ===========================================================
FDATE /FgetK /Q"Press letter of your choice> " /KABx /V

if (%FDATE%)==(A) goto Choice_%FDATE%
if (%FDATE%)==(B) goto Choice_%FDATE%
if (%FDATE%)==(x) goto endit
echo Program logic error.   Invalid choice [%FDATE%]
pause
goto Start

:CHOICE_A
 cls
 echo Processing choice %FDATE% ...
 DIR *.* /W /P
 pause
 goto Start

:CHOICE_B
 echo Processing choice %FDATE% ...
 DIR *.BAT /W /P
 pause
 goto Start

:endit
set choice=
cls


:09 Change a date from one format into another
:==================================================================
:: change date from mm-dd-yy format to ccyymmdd format
FDATE /Ff /Imm-dd-yy /A05-08-92 /Occyymmdd



:10 Find the difference in days between two dates
:==================================================================
FDATE /Fdif /Imm-dd-ccyy /A%date1% /B%date2% /vdiff
echo The difference is %diff% days.


:11 Find the elapsed days/hours/minutes between two date/times.
:===================================================================
This batch file was developed in cooperation with Walter Ledge, a sysop for
CompuServe's CRFORUM.  In addition to being a good example of how to use
Fdate's /T parm and "#idiv" function, it should be useful for other
CompuServe sysops who need to submit the same reports that Walt does. 
Here's Walt's message that started the whole thing.

  As an assistant sysop on the CRFORUM, I have to submit reports to CIS on
  the number of messages that are posted on our forum in terms of time per
  1,000 messages -- i.e., say, I know that 1,000 messages were posted
  between the hours of 17:05 on July 5 and 3:03 on July 7.  I need to know
  how many hours and minutes it took for those 1000 messages to be posted. 
  So I would like some way to use FDATE to calculate the difference
  between those two times (which, of course, include the dates).

FORATIM2.BAT is an improvement of the original FORATIME.BAT batch file. 
FORATIM2.BAT uses the /Fget function, which first appeared in Fdate 8.3, to
get user input from the terminal, rather than requiring all parameters to
be entered at the command line as FORATIME.BAT did. 

@echo off
cls
:: ------------------------------------------------------
:: FORATIM2.BAT batch file
::
:: FUNCTION
::    Calculate the elapsed time (in days and minutes)
::    between some "begin" date/time and some "end" date/time
::
:: ------------------------------------------------------
ECHO --------------------------------------------------------------
ECHO     Calculate elapsed time between two date/times
ECHO --------------------------------------------------------------

:BegDate
Fdate /Fget /VBEGdate /Q"Enter BEGIN DATE (mm-dd-ccyy): "
if (%BegDate%)==() goto Cleanup

:BegTime
Fdate /Fget /VBEGtime /Q"Enter BEGIN TIME (hh:mm).....: "
if (%BegTime%)==() goto Cleanup

:: validate date & time
fdate /fv /A%BEGdate% /T%BEGtime% >nul
if errorlevel 1 echo Invalid date/time
if errorlevel 1 goto BegDate

:: get absolute minute of start date/time.
fdate /ff /ominute# /A%BEGdate% /T%BEGtime% /VABStime1
if errorlevel 1 goto BegTime
fdate /ff /ofull    /A%BEGdate% /T%BEGtime% /Vfull1
::
echo.
:EndDate
Fdate /Fget /VENDdate /Q"Enter END.. DATE (mm-dd-ccyy): "
if (%EndDate%)==() goto Cleanup

:EndTime
Fdate /Fget /VENDtime /Q"Enter END.. TIME (hh:mm).....: "
if (%EndTime%)==() goto Cleanup

:: validate date & time
fdate /fv /A%ENDdate% /T%ENDtime% >nul
if errorlevel 1 echo Invalid date/time
if errorlevel 1 goto EndDate

:: get absolute minute of end date/time.
fdate /ff /ominute# /A%ENDdate% /T%ENDtime% /VABStime2
if errorlevel 1 goto EndTime
fdate /ff /ofull    /A%ENDdate% /T%ENDtime% /Vfull2

echo.
ECHO Calculating elapsed time...
:: calculate the difference between ABStime1 and ABStime2
fdate /f#dif  /A%ABStime1% /B%ABStime2% /VMinutes

:: calculate the number of hours in it took
fdate /f#Idiv  /A%minutes% /B60  /VHours

:: calculate the number of extra minutes it took
fdate /f#mod   /A%minutes% /B60  /VMins

echo.
echo   Between %full1%
echo       and %full2%
echo.
echo   Elapsed time was:
echo           %hours% hours and %mins% minutes

fdate /f#Idiv /A%minutes% /B1440 /Vday1
fdate /f#mod  /A%minutes% /B1440 /Vmin1
fdate /f#Idiv /A%min1%    /B60   /Vhour1
fdate /f#mod  /A%min1%    /B60   /Vmin2
echo   or
echo         %day1% day(s) %hour1% hour(s) and %min2% minute(s).
echo.
echo.
::
:cleanup
set ENDdate=
set BEGdate=
set BEGtime=
set ENDtime=
set full1=
set full2=
set minutes=
set ABStime1=
set ABStime2=
set day1=
set hour1=
set min1=
set min2=
set mins=
set hours=
:endit
:13 Find the elapsed years/months/days between two dates.
:===================================================================
@echo off
:: illustrate Fdate's Month# output format
cls
echo --------------------------------------------------------------
echo    YMD_DIF.BAT Calculate elapsed time between two dates
echo --------------------------------------------------------------

:: --------------------------------------------------------------
:D1
Fdate /Fget /VD1 /Q"Enter date #1 (mm-dd-ccyy), or ENTER to quit: "
if (%D1%)==() goto Cleanup

:: validate date
Fdate /Fv /A%D1%       >nul
if errorlevel 1 echo Invalid date
if errorlevel 1 goto D1

:: translate date into various formats, including absolute month
Fdate /Ff /oMonth# /A%D1% /VAbsMonth1
Fdate /Ff /oday#   /A%D1% /VAbsDay1
Fdate /Ff /A%D1%   /VFull1
Fdate /Ff /odd     /A%D1% /VDd1

:: --------------------------------------------------------------
:D2
Fdate /Fget /VD2 /Q"Enter date #2 (mm-dd-ccyy), or ENTER to quit: "
echo.
if (%D2%)==() goto Cleanup

:: validate date
Fdate /Fv /A%D2% >nul
if errorlevel 1 echo Invalid date
if errorlevel 1 goto D2

:: translate date
Fdate /Ff /oMonth# /A%D2% /VAbsMonth2
Fdate /Ff /oday#   /A%D2% /VAbsDay2
Fdate /Ff /A%D2%   /VFull2
Fdate /Ff /odd     /A%D2% /VDd2

:: --------------------------------------------------------------
:: verify that D2 is later than D1
Fdate /Fcomp /A%D2% /B%D1% /v
if (%Fdate%)==(GT) goto EndIf1
   echo     D2 must be later than D1.        Please try again.
   echo.
   goto D1
:EndIf1

:: verify that D2 is in a later month than D1
Fdate /F#comp /A%AbsMonth2% /B%Absmonth1% /v
if (%Fdate%)==(GT) goto EndIf2
   :: they are in the same month
   Fdate /Fdif /A%D1% /B%D2% /P"Difference is " /S" days."
   echo.
   goto Cleanup
:EndIf2

:: --------------------------------------------------------------
:: get difference in months
Fdate /F#dif /A%AbsMonth2% /B%Absmonth1% /vMonthsDif

:: compare days of month
Fdate /F#comp /A%Dd2% /B%Dd1% /v
if not (%Fdate%)==(LT) goto EndIf3
   :: Dd2 is less than Dd1 ... subtract 1 from (add -1 to) MonthsDif
   Fdate /F#add  /A%MonthsDif% /B-1 /VMonthsDif
:EndIf3


:: do month arithmetic, to get a date (D3) that is
:: less than 1 month prior to D2
Fdate /Fm /A%D1% /N%MonthsDif% /Omm-dd-ccyy /VD3

:: find difference in days between D3 & D2
Fdate /Fdif /A%D3% /B%D2% /Vdaysdif

:: --------------------------------------------------------------
echo Between %Full1% & %Full2% ...
echo                 %MonthsDif% month(s) %DaysDif% day(s)

:: calculate the number of years, by dividing MonthsDif by 12
Fdate /F#Idiv  /A%Monthsdif% /B12  /VYearsDif

:: calculate the number of extra months
Fdate /F#mod   /A%MonthsDif% /B12  /VMonthsDif

echo  or   %YearsDif% year(s) %MonthsDif% month(s) %DaysDif% day(s)

:: --------------------------------------------------------------
:cleanup
echo.
echo.
set D1=
set D2=
set D3=
set AbsMonth1=
set AbsMonth2=
set AbsDay1=
set AbsDay2=
set Full1=
set Full2=
set Dd1=
set Dd2=
set YearsDif=
set MonthsDif=
set DaysDif=
set Fdate=
:endit


:14 Determine how long it took a program to run
:==================================================================

@echo off
cls
ECHO 
ECHO       DETERMINE HOW LONG IT TOOK A PROGRAM TO RUN
ECHO           The demo will run for 1 - 60 seconds.
ECHO 
PAUSE
cls
:: Get the time (in julian seconds) that the program began running
set PgmName=DemoFake_Pgm
FDATE /Ff /Osecond# /VBegS
FDATE /Ff /Ohh:mm:ss /P"%PgmName% execution begins at "

::  DEMO BEGIN 
:: For purposes of this demo, we simulate execution of a
:: program by looping until the minute changes.  In your real
:: batch file, you would put your program statements here.
:: 
FDATE /Ff /Ohhmm /vBegM
:BegLoop
   rem  Since this is a demo, give the folks something to watch
   FDATE /Ff    /Osecond# /vSeconds
   FDATE /F#dif /A%Seconds% /B%BegS% /P".... elapsed time: " /S" seconds."
   FDATE /Ff  /Ohhmm     /vNowM
if (%NowM%)==(%BegM%) goto BegLoop
set BegM=
set NowM=
::  DEMO END   

:: Get the time (in julian seconds) that the program finished
FDATE /Ff  /Osecond# /vEndS
:: tell the user the time that the program finished
FDATE /Ff  /Ohh:mm:ss /P"%PgmName% execution ends at "

:: calculate run time (difference between start time and end time)
FDATE /F#dif /A%EndS% /B%BegS% /vSeconds
:: convert  seconds to  minutes + seconds  format
FDATE /F#idiv /A%Seconds% /B60 /vMinutes
FDATE /F#mod  /A%Seconds% /B60 /vMinSecs

:: tell the user how long the program took to run
echo Runtime: %Seconds% seconds (%Minutes% minutes %MinSecs% seconds)
:: cleanup            
set PgmName=
set BegS=
set EndS=
set Seconds=
set Minutes=
set MinSecs=

:15 Find years when a given date fell on a given day of the week
:==================================================================
[WHATDAY.BAT  This program has virtually no data validation, but if you are
careful to enter valid input data, it does the job.] 

 @echo off
 :: ----------------------------------------------------------------
 :: This program calculates the years (within a specified range) that a
 :: certain day of a certain month fell on a certain day of the week.
 ::
 :: Note that we calculate and test both the day of the week and the
 :: month.  This is because, for example, "February 29" of
 :: a non-leapyear (an invalid date)
 :: will be converted to the valid date of March 1.
 :: So we want to be sure that in a given year, February 29 not only
 :: occurred on the weekday in question, but also actually
 :: occurred in February.
 :: ----------------------------------------------------------------
 cls
 echo This program calculates the years (within a specified range) that a
 echo certain day of a certain month fell on a certain day of the week.
 echo.
 echo Please enter the day of the week that you want to search for.
 echo   1 = Sunday
 echo   2 = Monday
 echo   3 = Tuesday
 echo   4 = Wednesday
 echo   5 = Thursday
 echo   6 = Friday
 echo   7 = Saturday
 echo.
 fdate /fgetk /K1234567x /Q"Please press a number, or ESC to exit > " /vdow
 if (%Dow%)==(x) goto endit
 if (%Dow%)==(1) set DowName=Sunday
 if (%Dow%)==(2) set DowName=Monday
 if (%Dow%)==(3) set DowName=Tuesday
 if (%Dow%)==(4) set DowName=Wednesday
 if (%Dow%)==(5) set DowName=Thursday
 if (%Dow%)==(6) set DowName=Friday
 if (%Dow%)==(7) set DowName=Saturday
 echo You chose day of the week: %dowName%
 pause

 fdate /fget /Q"Please enter first year in year range > " /vBegYr
 fdate /fget /Q"Please enter last_ year in year range > " /vEndYr
 fdate /fget /Q"Please enter month number (1-12) > " /vMonNum
 fdate /fget /Q"Please enter day__ number (1-31) > " /vDayNum

 set Yr=%BegYr%
 fdate /fsubstr /a-2 /q00%MonNum% /vMonNum

 rem >whatday.txt
 cls
 echo Looking for %MonNum%/%DayNum% on %DowName%
 echo between %BegYr% and %EndYr%
 echo ----------------------------------------------
 echo Looking for %MonNum%/%DayNum% on %DowName% >>whatday.txt
 echo between %BegYr% and %EndYr% >>whatday.txt
 echo ---------------------------------------------- >>whatday.txt

 :LoopTop
   fdate /fsubstr /a-4 /q0000%yr% /vyr
   echo Testing %yr%
   fdate /ff /Idd-mm-ccyy /A%DayNum%-%MonNum%-%Yr% /v
   fdate /ff /Idd-mm-ccyy /A%DayNum%-%MonNum%-%Yr% /odow# /vdow#
   fdate /ff /Idd-mm-ccyy /A%DayNum%-%MonNum%-%Yr% /omm   /vmm

   if (%Dow#%)==(%Dow%) if (%MonNum%)==(%mm%) echo %fdate%
   if (%Dow#%)==(%Dow%) if (%MonNum%)==(%mm%) echo %fdate% >>Whatday.txt

   fdate /f#add  /A%yr% /B1 /vYr
   fdate /f#comp /A%yr% /B%EndYr% /v
   if (%fdate%)==(GT) goto LoopEnd
   goto LoopTop
 :LoopEnd

 cls
 type whatday.txt
 echo.
 echo This data has been written to file: Whatday.txt
 echo.
 :endit
 set Yr=
 set BegYr=
 set EndYr=
 set mm=
 set Dow=
 set Dow#=
 set DowName=
 set fdate=
 set MonNum=
 set DayNum=

:16 Find calendar date corresponding to a "business Julian" date
:==================================================================
rem business julian date is 1992:045.  Note input format CCYYjjj
FDATE /Ff /A1992045  /Iccyyjjj  /Od1

rem You don't need to left-zero-fill the day
FDATE /Ff /A199245  /Iccyyjjj  /Od1

rem You can assume the century, if you specify the YYjjj input format
FDATE /Ff /A9245  /Iyyjjj  /Od1

:17 Set your PC's date to a business julian date
:==================================================================
@echo off
goto enddoc
---------------------------------------------------------------------
This batch file was created by Aran Spence [CIS: 70162,3044].  Its
function is to emulate the DOS DATE command, but allow the user to set
the date using a business julian date format (yyjjj) instead of
mm-dd-yy.

Note the format is YYjjj. This is the BUSINESS julian date: a date
expressed as the number of days from the beginning of the year,
when January 1 is day 1.

           date      BUSINESS julian date
       -----------   --------------------
       Jan 5, 1992       92005
       Jan 5, 1993       93005
       Dec 31, 1993      93365  [Dec 31 is 365th day of year 1993]

As Aran originally wrote it, the user-prompt was virtually identical to
that of the DATE command.  I have modified his original version, so it
now looks less like the DATE command but displays a bit more
information, and so it can operate from the command line.

If the user enters a business julian date as a command-line
parameter, JDATE resets the date to that julian date.
             EXAMPLE:  JDATE 92005
If there is no input parameter, /fget is used to prompt the user for a
date.

Note that the user must enter both of the year digits (yy),
but may enter an abbreviated set of day digits (jjj).  That is,
for julian day 92005, the user is permitted to enter 925.

One handy use for JDATE is simply to find out what the current
business julian date is.
---------------------------------------------------------------------
:enddoc

SET NewJD=%1
if not (%NewJD%)==() goto GotDate

:ShowDate
Fdate /Ff /Od1    /P"Current Gregorian date: "
Fdate /Ff /Oyyjjj /P"'Business Julian' date: "

:GetDate
GET S "Enter new date (yyddd): " /VNewJD /L
if (%NewJD%)==() goto endit

:GotDate
Fdate /Ff /A%NewJD% /Omm-dd-yy /Iyyjjj /VNewGD
if errorlevel 1 echo Invalid date "%NewJD%"
if errorlevel 1 goto GetDate

::   reset the date
DATE %NewGD%

echo SYSTEM DATE HAS BEEN RESET
Fdate /Ff /Od1    /P"Current Gregorian date: "
Fdate /Ff /Oyyjjj /P"'Business Julian' date: "

:endit
SET NewJD=
SET NewGD=
echo.

:18 Determine if parm %1 contains a valid date
:==================================================================
COMMENT
  Note that we throw away the FDATE output by redirecting it to NUL.  All
  we really want here is the errorlevel, which tells us whether or not the
  string in %1 is a valid year.

Fdate /Fv /Imm-dd-ccyy /A%1  >nul
if errorlevel 1 echo Parm 1 was not a valid date: %1
if errorlevel 1 goto endit

::
:: Put the body of your batch file here.
::

:endit



:19 "Roll your own" date format 
:==================================================================
@echo of
cls
:: EXAMPLE A: create a date in the format of the DOS "date" command
:: format, followed by the DOS "time" command format

:: get the three-character day-of-week name
Fdate /Ff /Odow3 /Vx

:: add mm-dd-ccyy to it
Fdate /Ff /Omm-dd-ccyy /p"%x% " /Vx

:: add the DOS "time" format (new output format in Fdate 8.6)
Fdate /Ff /Otdos       /p"%x% " /Vx
echo Date/time = %x%

:: EXAMPLE B: create a date in custom-made format: yymn3dd
Fdate /Ff /Oyy          /Vx
Fdate /Ff /Omn3 /P"%x%" /Vx
Fdate /Ff /Odd  /P"%x%" /Vx
echo Today is %x%

:: EXAMPLE C: create a date with day and month date-parts right justified
::            and padded with spaces, such as " 1- 1-1995" for Jan 1, 1995
fdate /ff /ozd   /j"R 2" /vzd
fdate /ff /ozm   /j"R 2" /vzm
fdate /ff /occyy /p"%zd%-%zm%-"  /v
echo Today is [%fdate%]

:20 Find the 4th Thursday in November (Thanksgiving)
:==================================================================
Fdate /Fw /D5 /N4 /A11-01-%year% /Imm-dd-ccyy /Od1 /P"Thanksgiving: "


:22 On a date, show what anniversary it is for some event
:==================================================================
See HOLIDAYS.BAT demo batch file


:23 Show a list of holidays in a given year
:==================================================================
See HOLIDAYS.BAT demo batch file


:24 Show a list of Federal holidays in a given year
:==================================================================
See HOLIFEDS.BAT demo batch file

:25 Determine if a year is valid, and evenly divisible by 4
:==================================================================

@echo off
cls
echo FUNCTION: Accept a year parm (CCYY) as parameter 1.  Determine if
echo the year is an election or inauguration year in the United States.
echo ===================================================================

rem verify %1 is a valid year
Fdate /Fv /Imm-dd-ccyy /A01-01-%1 >nul
if errorlevel 1 echo Year parm [%1] is not valid.
if errorlevel 1 goto endit

Fdate /Ff /Imm-dd-ccyy /A01-01-%1 /p"@set year=">junktemp.bat
call junktemp.bat

Fdate /F#mod /A%1 /B4 /p"@set mod=">junktemp.bat
call junktemp.bat
if (%mod%)==(0) echo %1 is an American presidential election year.
if (%mod%)==(1) echo %1 is an American presidential inauguration year.
for %%v in (2 3) do if (%mod%)==(%%v) echo %1 is not an election year.
for %%v in (2 3) do if (%mod%)==(%%v) echo %1 is not an inauguration year.

set mod=
:endit
if exist junktemp.bat del  junktemp.bat




:30 Compare a file's date to today's date
:==================================================================
rem Compare today's date to the date on the filename in %1
Fdate /Fcomp /At /If /B%1 /Vcomp
if (%comp%)==(EQ) echo %1 was created or updated today
set comp=


:31 Compare two files' date/time using COMPARE-FUNCTION ERRORLEVELS
:==================================================================
COMMENT
There are many ways to check errorlevels.  This example shows 
several of them.

@echo off
cls
SET F1=FDATE.BAT
SET F2=FDATE.EXE
fdate /FTcomp /If /A%f1%  /B%F2% /P"%f1% is " /S" %f2%"

if errorlevel 101 if not errorlevel 103 echo %f1% is LT/EQ %f2%
if errorlevel 102                       echo %f1% is GT/EQ %f2%

if errorlevel 101 if not errorlevel 102 echo %f1% is older than %f2%
if errorlevel 102 if not errorlevel 103 echo %f1% is same age as %f2%
if errorlevel 103 if not errorlevel 104 echo %f1% is younger than %f2%

if errorlevel 101 if not errorlevel 103 echo %f1% at least as old as %f2%
if errorlevel 102                       echo %f1% is no older than %f2%

if errorlevel 101 if not errorlevel 102 echo errorlevel is 101
if errorlevel 102 if not errorlevel 103 echo errorlevel is 102
if errorlevel 103 if not errorlevel 104 echo errorlevel is 103
SET F1=
SET F2=
:endit



:32 Display a list of all files that were created/updated today. 
:==================================================================
@echo off
if (%1)==(SUBROUTINE) goto %2

CLS
ECHO FILES MEETING FILESPEC [%1] THAT WERE CREATED OR UPDATED TODAY
REM  The batch file calls itself: Its own name is in parm %0
for %%v in (%1) do  CALL %0 SUBROUTINE CHECKFILE %%v

set comp=
goto endit

:CHECKFILE
shift
shift

rem Compare today's date to the date on the %1 file
 Fdate /Fcomp /If /A%1 /Vcomp

rem echo the filename if the file was created/updated today
if (%comp%)==(EQ) echo %1
:endit
:33 MIN_MATH.BAT -- "time arithmetic" in minutes
:===================================================================
@echo off
cls
:: MIN_MATH.BAT -- Add or subtract time, in minutes, from the present

:: Get number of minutes from parm1, if present.  otherwise, use 4 minutes
:: not that Minutes can contain a negative number, if we wish to subtract
:: some minutes

set Minutes=4
if not (%1)==() set Minutes=%1

:: get the absolute minute NOW 
:: Alternatively, you can use the /A parm and the /T parm
:: to start from the date and time of your choice.
fdate /ff /ominute# /vAbsMin

:: add a certain number of minutes
fdate /f#add /a%AbsMin% /b%Minutes% /VNewMin

:: display the results
fdate /ff /iminute# /ofull /a%AbsMin% /p"We add %Minutes% minutes to "
fdate /ff /iminute# /ofull /a%NewMin% /p"producing: "

set Minutes=
set AbsMin=
set NewMin=

echo.
:endit
:34 TIME_SET.BAT -- "time arithmetic" -- set TIME
:===================================================================
@echo off
:: advance the time by 3 hours, then set it back again
set Minutes=180
cls

FDATE /FF /Ofull /P"It is now "

:: get the absolute minutes now
fdate /ff /ominute# /vAbsMin

:: add a certain number of minutes
fdate /f#add /a%AbsMin% /b%Minutes% /VNewMin

:: reset the time and date
fdate /ff /a%NewMin% /Iminute# /omm-dd-yy /vdate
fdate /ff /a%NewMin% /Iminute# /ohh:mm    /vtime
time %time%
date %date%

echo %Minutes% minutes added...
FDATE /FF /Ofull /P"It is now "

ECHO.
ECHO DOING SOME WORK ...
ECHO.

FDATE /FF /Ofull /P"It is now "

:: get the absolute minutes now
fdate /ff /ominute# /vAbsMin

:: subtract (add negative) a certain number of minutes
fdate /f#add /a%AbsMin% /b-%Minutes% /VNewMin

:: reset the time and date
fdate /ff /a%NewMin% /Iminute# /omm-dd-yy /vdate
fdate /ff /a%NewMin% /Iminute# /ohh:mm    /vtime
time %time%
date %date%

echo %Minutes% minutes subtracted ...
FDATE /FF /Ofull /P"It is now "

set Minutes=
set AbsMin=
set NewMin=
set time=
set date=
echo.
:endit

:41 Delete files more than X days old (use a batch-file subroutine)
:==================================================================
See the COMMENTARY that follows the text of the batch file.
 

@echo off
if (%1)==(SUBROUTINE) goto %2
cls

goto EndDoc
----------------------------------------------------------------------
OLDFILES.BAT
This batch file shows how to do work on files that are older than
%NumDays%.  The PROCESS! subroutine can be modified to do any kind of
work you want.
----------------------------------------------------------------------
:EndDoc

:: set the number of days in the past.   if this value is not passed
:: in via parameter %1, it defaults to 3 days
set NumDays=%1
if (%NumDays%)==() SET NumDays=3


echo ------------------------------------------------------------------
echo           PROCESSING FILES CREATED MORE THAN %NumDays% DAYS AGO
echo ------------------------------------------------------------------
for %%v in (*.*) do  CALL %0 SUBROUTINE PROCESS! %%v
echo ------------------------------------------------------------------
echo           END OF PROCESSING
echo ------------------------------------------------------------------

:: CLEANUP
set NumDays=
set DaysOld=
set Comparison=
GOTO ENDIT

:
:PROCESS!
shift
shift

:: get difference in days between filedate and today.
:: Note that /B parm (which is omitted) defaults to today's date.
fdate /fdif   /A%1        /IF          /VDaysOld

:: compare DaysOld to NumDays
fdate /f#comp /A%DaysOld% /B%NumDays%  /Vcomparison

:: the following line will DISPLAY THE NAME AND AGE OF
:: any file for which %DaysOld% is greater than %NumDays%
:: --------------------------------------------------------------
if (%comparison%)==(GT) echo %1 is %DaysOld% days old.

:: EXAMPLE (to activate this routine, remove the REM from column 1)
:: the following line will COPY TO AN ARCHIVE SUBDIRECTORY
:: any file for which %DaysOld% is greater than %NumDays%
:: -----------------------------------------------
REM if (%comparison%)==(GT) COPY %1 C:\ARCHIVE\*.*

:: EXAMPLE (to activate this routine, remove the REM from column 1)
:: the following line will DELETE
:: any file for which %DaysOld% is greater than %NumDays%
:: -----------------------------------------------
REM if (%comparison%)==(GT) DEL %1

:: fall through to endit

:endit

 ===============================================================
                        COMMENTARY BEGIN
 ===============================================================
 This batch file uses a crude, but effective, technique for giving a
 batch file the ability to call subroutines.  If you've never seen
 something like this before, it is sort of mind-blowing.  Here's some
 commentary on the more important lines involved in the technique.
 ===============================================================

 if (%1)==(SUBROUTINE) goto %2

    COMMENTARY:
    If the first parameter, %1, is "SUBROUTINE", then the batch file
    recognizes that it is being called for the purpose of executing
    one of its own subroutines.  In such a case, it does a GOTO to the
    start of the requested subroutine.  That is, it goes to the label
    whose name is in the second parameter.

    Explicitly specifying the name of the desired subroutine permits
    permits us to have multiple subroutines in the batch file,
    each with its own name.  (As it happens, in this batch file
    we have only one subroutine, named "PROCESS!")

    If the first parameter is not "SUBROUTINE", then we fall through
    and begin executing the main routine of the batch file.  In such a
    case, the first parameter (%1) may contain a number, indicating
    the number of days to use in determining which files to delete.

    Note that this technique will make the batch file malfunction
    if the user himself ever executes the batch file from the
    DOS command line with the word "SUBROUTINE" as the first
    parameter, the word "PROCESS!" as the second parameter, and a
    third parameter that is missing or not a valid filename.
    This is so unlikely, however, that it is reasonable
    to assume that it will never happen.

 ===============================================================

 for %%v in (*.*) do  CALL %0 SUBROUTINE PROCESS! %%v

    COMMENTARY:
    In a batch file, %0 contains the name by which the batch file was
    invoked.  We use this fact to allow a batch file to call itself,
    regardless of what name the user has given to it.

    The first parameter passed, when the batch file calls
    itself, is the string "SUBROUTINE".  This string allows the batch
    file to recognize when it is being called for the purpose of
    executing one of its own subroutines.

    The second parameter is the name of the subroutine that we want
    to call: in this case, "PROCESS!".

    The third parameter is what we would normally think of as the first
    parameter to the subroutine.  In this case, when the
    FOR statement is executed, and the substitution for %%v takes
    place, it will contain the name of the file to be processed.
    Note that we could, if we wished, pass additional parameters to
    the subroutine.  Note also that we can control the files that
    we process.  We do so via the filemask in the FOR statement.
    It we used, for example, "*.EXE", then we would process only
    executable files.

 ===============================================================

 GOTO ENDIT

   COMMENTARY:
   When the mainline of the batch file is finished executing, we
   goto the end of the batch file.  We MUST do this GOTO in order
   to avoid falling through into, and starting to execute, the first
   of the batch file's subroutines.

 ===============================================================

 :PROCESS!
 shift
 shift

   COMMENTARY:
   Note that when the batch file is called as a subroutine, and the
   batch file goes to the PROCESS! label, the values of the parms are:
           %0 = [the name of the batch file]
           %1 = SUBROUTINE
           %2 = PROCESS!
           %3 = [name of the file to be processed]

    We shift all the parameters to the left twice, to move the
    parameter(s) into what we think of as the
    proper places for parameters to the subroutine.

    After the first SHIFT command:
           %0 = SUBROUTINE
           %1 = PROCESS!
           %2 = [name of the file to be processed]

    After the second SHIFT command:
           %0 = PROCESS!
           %1 = [name of the file to be processed]

    Now %1 contains what we think of as the proper parameter(s)
    to the subroutine.  In this case, %1 contains the filename that
    we want the subroutine to process.

    At the end of every subroutine, there should be a GOTO ENDIT,
    which causes the batch file to go to its own end, and then
    end and return control to the statement in the program which called
    it.  (This is, of course, the CALL statement embedded in the
    FOR statement.)

    We can optimize the batch file a little by omitting the "goto endit"
    at the end of the last subroutine.  Instead, we simply allow the
    last subroutine to fall through to the end of the batch file.

 ===============================================================
                         COMMENTARY END
 ===============================================================

:42 Get date to tell PKZIP to compress files older than 30 days
:======================================================================
PKZIP (a popular file-compression utility) can be used to compress and
archive files that are older/younger than a given date.  To run PKZIP on
files that are, for example, older than 30 days, we need the date that was
30 days before today's date.  To get it, we use Fdate to subtract 30 days
from today's date, and put that date out in PKZIP's "American" format
(MMDDYY). (Fdate also supports PKZIP's Japanese and European formats.)

To compress all files that were created before a date 30 days ago:

     Fdate /Fsub /N30 /Ommddyy /VArchiveDate
     pkzip test.zip -T%ArchiveDate%

For more information, see PKZIP's MANUAL.DOC file.

:43 Loop through an array of environment variables
:======================================================================
@echo off
cls
SET pct=%%%
SET prefix=Address

ECHO LOADING AN ARRAY
SET subscript=1
SET %prefix%.%subscript%=Stephen Ferg
SET subscript=2
SET %prefix%.%subscript%=5113 N. 8th Road
SET subscript=3
SET %prefix%.%subscript%=Arlington, VA 22205

ECHO UNLOADING AND DISPLAYING THE ARRAY
SET subscript=1
:LoopTop
REM do while subscript less than/equal 3
if %subscript%==4 goto LoopEnd

   REM put value of subscripted variable into tempvar
   ECHO SET tempvar=%pct%%prefix%.%subscript%%pct%>JUNKTEMP.BAT
   CALL JUNKTEMP.BAT

   REM display value of subscripted variable
   ECHO %prefix%.%subscript% is: %tempvar%

   REM delete subscripted variable
   SET %prefix%.%subscript%=

   REM increment the loop variable
   Fdate /F#add /A%subscript% /B1 /Vsubscript
   goto LoopTop
:LoopEnd

SET pct=
SET tempvar=
SET prefix=
SET subscript=
DEL JUNKTEMP.BAT

:44 Do something on the last day (or last Friday) of the month
:==================================================================
COMMENT
We often need batch files that do some special task on the last day of the
month: run a backup job, display a reminder message, etc.  This example
batch file, LASTDAY.BAT, simply displays a message -- you can modify it to
do whatever it is that YOU want to do.

If you plan to run LASTDAY.BAT at work, and you work Monday through Friday,
then checking for the last day of the month would be a poor strategy --
after you leave work on a Friday, the last day of the month might occur on
the following Saturday or Sunday.   So I've included a check to see if the
Friday is the last working day of the month.  If you don't want that
functionality, deleting the lines between the first and last occurrence of
the string "EndCheck" will remove it.
=======================================================================
 @echo off
 REM ---------------------------------------------------------------
 REM check to see if today is the last day of the month
 REM ---------------------------------------------------------------
 REM get today's month
 fdate /ff        /omm /vmmtoday

 REM get tomorrow's month
 fdate /fadd /n1 /omm  /vmmtomorrow

 REM if tomorrow occurs in a different month,
 REM then today is the last day of this month
 if not (%mmtoday%)==(%mmtomorrow%) echo LAST DAY OF THE MONTH
 if not (%mmtoday%)==(%mmtomorrow%) goto EndCheck

 REM -------------------------------------------------------------
 REM check to see if today is the last Friday of the month
 REM -------------------------------------------------------------
 rem get today's day of the week, to see if it is Friday
 fdate /ff /odow3 /vdow3
 if not (%dow3%)==(Fri) goto EndCheck

 REM today is Friday.  Get next Monday's month
 fdate /fadd /n3 /omm  /vmmMonday

 REM if next Monday occurs in a different month,
 REM then today is the last Friday of this month
 if not (%mmtoday%)==(%mmMonday%) echo LAST WORKING DAY OF THE MONTH

 :EndCheck

 REM cleanup
 set dow3=
 set mmtoday=
 set mmtomorrow=
 set mmMonday=

:45 Get information about the month prior to the current month
:==================================================================
COMMENT
When running a monthly backup job at the beginning of the month, one often
needs to identify the previous month, or the last day of the previous
month.  Here's how to use Fdate to obtain that sort of information. 
Basically, we subtract one day from the first day of the current month,
giving us the last day of the previous month.
=======================================================================
@echo off
cls
: The simplest way to get information about last month is to subtract
: 1 day from the first day of this month ...

fdate /fsub /n1 /att-01-tttt /omm   /p"Last month was.................: "
fdate /fsub /n1 /att-01-tttt /occyy /p"Last month occurred in the year: "
fdate /fsub /n1 /att-01-tttt /odd   /p"The last day of last month was : "
fdate /fsub /n1 /att-01-tttt /od1   /p"The last day of last month was : "



:46 Show the last Monday (or any other weekday) in this month
:==================================================================
@echo off
cls
:: Use monthly arithmetic to get first day of next month
fdate /fm /n1 /att-01-tttt /omm-dd-ccyy   /v

:: get the preceding Monday, i.e. the last Monday in this month
fdate /fw /d2 /n-1 /x /a%fdate%

:47 Show the last Monday in the month, for a series of months
:==================================================================
@echo off
cls
:: initialize constants
set StartDate=01-01-1996
set MONTHS=15

echo Show the last Mondays in the month,
echo for the %months% months starting %StartDate%
echo ==============================================================

set COUNT=1
:LOOPTOP
  :: compare COUNT to MONTHS, exit loop if COUNT exceeds MONTHS
  FDATE /F#comp /A%COUNT% /B%MONTHS% /vCOMP
  if (%COMP%)==(GT) goto ENDLOOP

  :: Use monthly arithmetic to get first day of next month
  FDATE /Fm /N%COUNT% /A%StartDate% /Omm-dd-ccyy   /Vfdate

  :: get the preceding Monday (/D2) -- the last Monday in this month
  FDATE /Fw /D2 /N-1 /X /A%fdate% /P"%count% "

  :: increment COUNT
  FDATE /F#add /A%COUNT% /B1 /Vcount
  GOTO LOOPTOP
:ENDLOOP
echo.

:endit
set StartDate=
set MONTHS=
set COUNT=
set COMP=
set FDATE=

:50 Represent a date in 3 bytes of "extended hex" notation
:==================================================================

rem produce today's date as 3 bytes
fdate /ff /oxxx 
 
rem produce yesterday's date in xxx format
fdate /fsub /N1 /oxxx




:51 Represent a date in a short (4-byte) format (technique #1)
:==================================================================
COMMENT
A common use of Fdate is to format today's date and use it to rename a file
(typically a log file of some sort).  You may wish to store the date
information in as few characters as possible, in order to maximize the
number of other characters in the filename that you can use to store other
information.

In this example, and the next one, I illustrate two ways to store a date in
4 bytes.


The simplest way is to represent today's date as a 4-digit number.
To do this, we first pick a base date:  I'll use January 1, 1990.
Then it is a simple matter to calculate the number of days between today
and the base date:

           FDATE /Fdif /at /b01-01-1990 

Starting in 1993, this will always generate a 4-digit number, and will
continue to do so for 20 years, until approximately the year 2003.  Dates
before 1993 may produce 1-, 2-, or 3-digit numbers, and dates after 2003
will begin to produce 5-digit numbers.  But this technique will work quite
nicely for most ordinary purposes for the next 20 years.  

If you're still using DOS in the year 2003, then in 2003 you can switch to
using January 1, 2000 as your base date and function quite nicely for the
next 20 years after that.

:52 Represent a date in a short (4-byte) format (technique #2)
:==================================================================
@echo off
cls
goto end-doc
------------------------------------------------------------------
This batch file shows how to use Fdate's #2XX function to
obtain and represent today's date in 4 characters, YYMD, where:

  YY is the year (e.g. "93" for 1993)
   M is the month in extended hexadecimal (XX) notation
   D is the day-of-the-month in extended hexadecimal (XX) notation

You can also use Fdate's "XXX" output format to represent dates between
1990 and 2024 in 3 bytes of extended hex notation.
------------------------------------------------------------------
:end-doc

REM OBTAIN 1-CHARACTER REPRESENTATION FOR THE MONTH
Fdate /ff    /Omm   /Vmm
Fdate /f#2xx /A%mm% /Vmm
echo XX representation of this month's number      is %mm%

REM OBTAIN 1-CHARACTER REPRESENTATION FOR THE DAY
Fdate /ff    /Odd   /Vdd
Fdate /f#2xx /A%dd% /Vdd
echo XX representation of today's day of the month is %dd%

REM CONCATENATE THEM TO THE 2-CHARACTER REPRESENTATION FOR THE YEAR
Fdate /Ff /Oyy /S%mm%%dd% /Vdate
echo XX representation of today's full date        is %date%

REM CLEANUP
set mm=
set dd=
set date=
:endit



:53 Convert numbers to "extended hex" (XX) format
:==================================================================
@echo off
cls
SET decnum=0
:top
   if (%decnum%)==(37) goto endit
   fdate /f#2xx /A%decnum% /P"XX representation of %decnum% is "
   fdate /f#add /A%decnum% /b1 /Vdecnum
goto top

:endit

:54 Customize Fdate for a language of your choice
:==================================================================
@echo off
cls
goto end-doc
------------------------------------------------------------------
You can use Fdate with a customized batch file to obtain the names of
the days of the week and the months in a language of your choice.  Or
you could use it to obtain names in uppercase, or the first 5
characters of the names (rather than the first three), or some other
customized formatting of your choice.)

I've invented a language called Fergian, which has its own names for
the days of the week, and the months.  In the following examples, I
invoke FERGIAN.BAT to make the translation.  The text of FERGIAN.BAT,
which does the real work here, is given in the next example.
------------------------------------------------------------------
:end-doc

fdate /ff /omm /v
call Fergian mm- result %Fdate%
echo Month  is          %result%

fdate /ff  /omm /v
call Fergian mm3 result %Fdate%
echo Month3 is          %result%

fdate /ff /odow#  /v
call Fergian dw- result %Fdate%
echo Day of week  is    %result%

fdate /ff /odow#  /v
call Fergian dw3 result %Fdate%
echo Day of week3 is    %result%

REM cleanup
set Fdate=
set result=

:55 Fergian.BAT (used in the previous example)
:==================================================================
@echo off
set  %2=
goto %1

goto end-doc
--------------------------------------------------------------------
This batch file converts a month number, or day of the week number,
to a name in the FERGIAN language.
You can copy this batch file and customize it, to make it translate
into some other language of your choice.

This batch file expects the following parameters:

%1 contains the type of number you want to convert:
   MM- if you want the entire name of the month
   MM3 if you want the first 3 letters of the name of the month

   DW- if you want the entire name of the day of the week
   DW3 if you want the first 3 letters of the name of the day of the week

%2 contains the name of the environment variable that you
   want to use to hold the result

%3 contains the number that you want to convert
--------------------------------------------------------------------
:end-doc

:MM-
if (%3)==(01) set %2=Jaded
if (%3)==(02) set %2=Febrile
if (%3)==(03) set %2=Martial
if (%3)==(04) set %2=Abigail
if (%3)==(05) set %2=Maybelene
if (%3)==(06) set %2=Junkaroo
if (%3)==(07) set %2=Julia
if (%3)==(08) set %2=Augmentation
if (%3)==(09) set %2=Separation
if (%3)==(10) set %2=Ostentation
if (%3)==(11) set %2=Novelty
if (%3)==(12) set %2=Decadence
goto endit

:
:MM3
if (%3)==(01) set %2=Jad
if (%3)==(02) set %2=Feb
if (%3)==(03) set %2=Mar
if (%3)==(04) set %2=Abi
if (%3)==(05) set %2=May
if (%3)==(06) set %2=Jun
if (%3)==(07) set %2=Jul
if (%3)==(08) set %2=Aug
if (%3)==(09) set %2=Sep
if (%3)==(10) set %2=Ost
if (%3)==(11) set %2=Nov
if (%3)==(12) set %2=Dec
goto endit

:DW-
if (%3)==(1) set %2=SunDay
if (%3)==(2) set %2=MoonDay
if (%3)==(3) set %2=TwickasDay
if (%3)==(4) set %2=WodensDay
if (%3)==(5) set %2=ThorsDay
if (%3)==(6) set %2=FreyasDay
if (%3)==(7) set %2=SaturnDay
goto endit


:DW3
if (%3)==(1) set %2=Sun
if (%3)==(2) set %2=Moo
if (%3)==(3) set %2=Twi
if (%3)==(4) set %2=Wod
if (%3)==(5) set %2=Tho
if (%3)==(6) set %2=Fre
if (%3)==(7) set %2=Sat
goto endit

:endit

:61 DO-ONCE: Run apps when booting for the first time of the day
:===============================================================
COMMENT
  Put this code in AUTOEXEC.BAT.  Note that this batch code requires DOS
  3.3+, since it uses CALL.

if not exist C:\LASTRUN.BAT goto RunNow

rem call LASTRUN.BAT, which will set an environment variable, %LASTRUN%,
rem that will contain the date when this batch file was last run.
rem ------------------------------------------------------------------
call C:\LASTRUN.BAT

rem compare the date in %LASTRUN% to today's date
rem ------------------------------------------------------------------
Fdate /Fcomp /At /B%LastRun% /Vcomp

: Today's date may be less than %LASTRUN% if you reset the system clock
IF (%COMP%)==(LT) goto NoRun
: If %LASTRUN% was the same as today's date,
:   then this batch file has already been run once today
IF (%COMP%)==(EQ) goto NoRun

: Daily processing hasn't been run today. Run it.
: Here, you should put the batch-file body --
: the code to run the applications that you want to run once per day
:

: ------------------------------------------------------------------
: Save today's date in a new version of LastRun.BAT.  Note that
: this code will be executed only if daily processing runs to
: completion without hanging the machine or aborting the batch file.
: ------------------------------------------------------------------
Fdate /Ff /Omm-dd-ccyy /At /P"@set LastRun=">LastRun.BAT

:NoRun
set LastRun=
set COMP=

:62 Run specific software, depending on the day of the week
:==================================================================
COMMENT
This is a very common use for Fdate.  I use it to load an alarm-clock TSR
(Terminate and Stay Resident, "memory resident", program) that beeps at me
(at different times on different days of the week) to remind me that it is
time to attend a meeting that is regularly scheduled for that day of the
week.

Note that stuff for a given day of the week will be executed every time you
boot up on that day of the week.  If you want stuff (e.g. a backup job) to
be run only once (the first time you boot up) on a given day of the week,
then:

(1)  copy the code from DO-ONCE (the previous example) into your
     AUTOEXEC.BAT file, then

(2)  copy this code into the body of the DO-ONCE code that you copied into
     AUTOEXEC.BAT in the last step.  If you do that, then this code will be
     run only once per day, even if you boot up multiple times per day.

Remember that if you are executing other batch files from a batch file, 
you should invoke them with a CALL statement:
              CALL batchfilename parm1 parm2 ...
so control will return to the calling batch file when execution of the
called batch file is complete.      

Note that the string comparison is case sensitive.
==================================================================

:: get 3-character day-of-week name and put it in DOW e-var
FDATE /ff /oDOW3 /vDOW

if (%DOW%)==(Mon) alarmTSR.exe 10:30 Time for Monday staff meeting

if (%DOW%)==(Fri) echo Running Friday backup.  Please wait...
if (%DOW%)==(Fri) CALL BACKUP C: 
if (%DOW%)==(Fri) CALL BACKUP D: 
set dow=



:63 Run a program at a specified time later in the day
:==================================================================
COMMENT
  This batch file involves a lot of disk activity because DOS re-reads the
  batch file from disk every time it does a GOTO LOOPTOP.  You can avoid
  all this disk activity by running the batch file from a RAM DISK.

REM GET CURRENT ABSOLUTE MINUTE AND PUT IN ENVIRONMENT VARIABLE RUNTIME
FDATE /Ff /At /Ominute#  |STRINGS RunTime= ASK >NUL

REM ADD 120 MINUTES (2 HOURS) TO ENVIRONMENT VARIABLE RUNTIME
FDATE /F#add /A%RunTime% /B120 |STRINGS RunTime= ASK >NUL

REM LOOP UNTIL NOWTIME HAS REACHED RUNTIME
:LoopTop
  FDATE /Ff /At  /Ominute#   |STRINGS NowTime=  ASK >NUL
  FDATE /F#comp  /A%NowTime% /B%RunTime% |STRINGS TimeComp= ASK >NUL
  if (%TimeComp%)==(LT) goto loopTop
:LoopEnd

echo STARTING EXECUTION OF APPLICATION: [program name]



:66 Change a filename to contain today's date in first 3 bytes
:==================================================================
FDATE /Ff /Oxxx /vXXX
ren  BACKUP.LOG  %XXX%-BACK.LOG
SET  XXX=



:67 Change a file's name to a name that contains today's date
:==================================================================
:: today's date (/At) in CCYYMMDD format into environment variable DATE1
FDATE /Ff /At /Occyymmdd /Vdate1
:: rename BACKUP.LOG to ccyymmdd.LOG (ex. 19950508.LOG on May 8, 1995)
REN BACKUP.LOG  %date1%.LOG
SET DATE1=


:68 Change a file's name to a name containing an absolute minute 
:===============================================================
COMMENT
  This is a way to keep a complete series of files, such as log files,
  that are all created with the same name on the same day.  The only
  requirement is that they be created at least one minute apart.  You
  won't need to be able to decipher the absolute minute to figure out when
  the file was created; you can simply do a DIR on the file and look at
  its date/time stamp.  

FDATE /FF /At /Ominute# /VJulMin
REN online.log %JulMin%.log
SET JulMin=



:71 Extract the rightmost n characters of a string 
:===============================================================
rem extract the rightmost 6 characters of a string
 FDATE /Fsubstr /a-6     /Q"1994 Jun 03"   ===> "Jun 03"



:72 Left-pad a number with zeroes, or a string with spaces
:===============================================================
:: pad a number (stored in environment variable) STRING
:: to the left with zeroes, to make sure it is 4 bytes long
set STRING=1
Fdate /FE  /Q%STRING% /Jr04  /Vstring
echo STRING is [%string%]

:: pad a string (stored in environment variable) STRING
:: to the left with spaces, to make sure it is 4 bytes long
set STRING=aa
Fdate /Fe  /Q%STRING% /J"r 4"  /Vstring
echo STRING is [%string%]

HOW FDATE THINKS ABOUT DATES
============================

FDATE'S BUSINESS VIEW OF THE CALENDAR
=====================================

  FDATE is intended for business applications, not historical ones.  

  FDATE does not take into account historical changes in the calendar such
  as the ten days that were dropped from the British calendar when Britain
  moved from the Julian to the Gregorian calendar in the 18th century, or
  the 11 days that were dropped from the Russian calendar when Russia made
  the same move in the early 20th century.

  As far as FDATE is concerned, the calendar has followed the same
  pattern, unchanged, since January 1, 0001.


FDATE'S BASE DATE
=================
  Internally, Fdate's date manipulations are based on translating a
  calendar date into an "absolute" or "TRUE Julian" date:  a date
  expressed as the number of days from some day in the distant past.

  FDATE's base date is January 1, 0001 (i.e. day 1 of month 1 of year 1)
  FDATE's absolute date for January 1, 0001 is      1.
  FDATE's absolute date for January 1, 1992 is 727198.


FDATE'S LEAP YEAR ALGORITHM
===========================
    Every year evenly divisible by 4 IS a leap year
      EXCEPT THAT
        Every year evenly divisible by 100 IS NOT a leap year
          EXCEPT THAT
            Every year evenly divisible by 400 IS a leap year
    .
    Using this algorithm
         1983  is not a leap year
         1984  is     a leap year
         1900  is not a leap year
         2000  is     a leap year

    See "A Machine Algorithm for Processing Calendar Dates", by
         Henry F. Fliegel (Georgetown University Observatory) and
         Thomas C. Van Flandern (U.S. Naval Observatory)
         COMMUNICATIONS OF THE ACM, Volume 11, Number 10, October 1968

There is supposedly a new adjustment to the leapyear algorithm,
which specifies the additional exception:

              EXCEPT THAT
                Every year evenly divisible by 4000 IS a leap year

See "Bit By Bit" column, COMPUTER LANGUAGE, November 1989, p. 148.
This adjustment is not part of FDATE's leapyear algorithm.
Unless your application is working with dates 2,000 years in the
future, the lack of this exception will be irrelevant for you.

FDATE'S CENTURY-ASSUMPTION ALGORITHM
====================================
If an input date is supplied in a format in which the year is
specified without a century -- that is, as YY rather than CCYY --
then Fdate does not automatically use the current century.
Instead,

   *  if YY is greater than 20,       then FDATE assumes CC = 19
   *  if YY is less than or equal 20, then FDATE assumes CC = 20

Examples:
         21    becomes  1921
         ...
         99    becomes  1999
         00    becomes  2000
         01    becomes  2001
         ...
         20    becomes  2020
but then (again)
         21    becomes  1921

To put it simply, FDATE makes what would be a reasonable assumption about
the century for someone operating in the 1990's: it looks back to 1921 and
forward to 2020.  If I, FDATE, and DOS are still alive in the year 2005
(which, given the introduction of Windows 95, seems unlikely) I'll probably
update FDATE's century-assumption algorithm to shift it forward several
decades.


FDATE'S IMPLEMENTATION LIMITS
====================================
Internally, numbers in Fdate are stored in Turbo Pascal's LONGINT datatype,
which means that Fdate can accept numbers up to 9 digits long.

DISTRIBUTION ISSUES
===================

USE, REGISTRATION, AND DISTRIBUTION OF FDATE
============================================

FDATE is freeware, or what is known as "zero-cost shareware".  FDATE is not
what is technically called "public domain" software because the author
retains the copyright.  FDATE can, however, be copied, used, and
distributed freely as long as FDATE.EXE and its associated doc file
(FDATE.TXT) and demonstration batch files and doc files (HOLIDAYS.BAT,
HOLIFEDS.BAT, HOLIFEDS.TXT) are not altered and are distributed together.  

There is no requirement to register FDATE in any way.

FDATE can be included in shareware packages as long as both FDATE and
its related files are included in the shareware package.

If you have received FDATE as part of some larger shareware package,
please be aware that you may freely use, copy, and distribute FDATE
without paying a fee for, or registering, the larger package.

The author explicitly disavows any claim whatsoever about the
correctness or functionality of FDATE, its documentation, and its
demonstration batch files, and disclaims liability for anything and
everything bad that might happen in connection with, before, during, or
after using it.  I have tried to make FDATE work right, but everybody
makes mistakes, so you use FDATE at your own risk.

I don't know if people will find FDATE useful, and I'd like to find
out.  If you find FDATE useful and use it on a regular basis, I'd
appreciate it if you would drop me a short note via US mail or
CompuServe, telling me about how you are using FDATE.

If you need other input/output formats, please contact the author.


TECHNICAL SUPPORT FOR FDATE
===============================================

Send me a message via CompuServe mail; I'll respond.  When sending your
message, please let me know what version of Fdate you're using.


WHERE TO FIND THE MOST CURRENT VERSION OF FDATE
===============================================

You will always be able to find the most recent version of FDATE on
CompuServe.  The filename will be FDATE.ZIP, and it will be available in
the CIS:IBMSYS forum (library 1, the "DOS Utilities" library).

If you have problems finding it, try using cross-library searching, looking
for the filename FDATE.ZIP or the keyword FDATE.


UPLOADING FDATE TO ELECTRONIC BULLETIN BOARDS
===============================================

Feel free to post copies of FDATE.ZIP on any BBS that you wish, but please
do not upload it to any CompuServe library.  As long as I am the only one
putting copies of FDATE onto CompuServe, we can keep confusion over
versions to a minimum.

I distribute all versions of FDATE in a files called FDATE.ZIP, rather than
embedding information about the version in the file name.  I think doing
this helps newer versions of FDATE to force older versions out of
circulation.  To give a BBS user information about the version, I always
identify the version of FDATE in the 1-line file description that most BBSs
support.  


CONTENTS OF THE FDATE.ZIP DISTRIBUTION FILE
===========================================

The current distribution package (FDATE.ZIP) contains the following:

       FDATE.EXE         [the FDATE program]
       FDATE.TXT         [this file, documentation for FDATE]
       FDATEBEG.TXT      [FDATE beginners documentation]

  [demonstration batch files]
       HOLIDAYS.BAT
       HOLIFEDS.BAT and HOLIFEDS.TXT

  [documentation files for use in BBS distribution]
       FILE_ID.DIZ
   DESC.SDI


RECENT FDATE REVISION HISTORY
=============================

Letters appended to version numbers indicate modifications to
the doc files, without any modification to the FDATE.EXE software.
Asterisks (*) indicate most important changes in the new version.

7.0a   Nov 14, 1992
       Added #mod function
       Major reformatting of documentation to make it more user-friendly
   
7.1a   Apr 15, 1993
       Added German language support.  Thanks for the request, and the
       necessary information, from Patrick Schmucki, via the Active-Net
       BBS in Rapperswil, Switzerland.

8.0    July, 1993
       Added "V" (validate) and "m" (month addition/subtraction) functions
       Added math functions: #mult #div #idiv
       Added /T (time) parameter

       Added FORATIME.BAT example, which Walter Ledge (assistant sysop of
       CompuServe's CRFORUM) and I developed.  A big thanks to Walt for
       his feedback and help.

8.1    July 27, 1993  BUG FIX
       An error-trapping routine that was added to version 7.9 contained a
       bug that caused Fdate's numeric math functions (#add, #dif, #mult,
       #div, #idiv, #mod, #comp, etc.) to return incorrect results. 
       
8.2    August, 1993
       Removed FILEDATE.BAT from the distribution .ZIP file.

       Corrected the Spanish and French "full" and "d1" output formats. 
       Thanks for the information on Spanish and French date formats to
       Gene J. Raymond, of GJR Software Products.

8.3a   Feb 24, 1994

*      Added the following string-handling functions:
       get    (get user input)
       getu   (get uppercase user input)
      upper  (uppercase a string)
       len    (length of a string)
       substr (substring)

*      Added /F#2xx (convert number to extended hex format) function. 
       Deleted SETXX.BAT, which has been made obsolete with the addition
       of this new function.  Modified second example of storing a 4-digit
       date to use #2xx instead of SETXX.BAT.

*      Added output formats "ddmmccyy" and "ddmmyy" at the request of
       several users.

*      Added output format "xxx" after several requests for advice on how
       to represent a large range of dates in a minimum number of bytes
       (usually for constructing filenames from today's date).

*      At the request of several users, enhanced the "compare" functions
       (comp, tcomp, #comp) so they set distinctive errorlevels for their
       different results.  See the table of contents ("COMPARE-FUNCTION
       ERRORLEVELS") and EXAMPLES.

       To discussion of /Fv parameter, added note about almost always
       redirecting output to NUL when using /Fv.

       Revised FORATIME.BAT example batch file to make error-correction a
       bit more robust and to add better documentation on how to use it.

       Added example batch files to use new functions, especially
       FORATIM2.BAT which uses new "get" function

       Removed FDATEX.BAT demonstration batch file from distribution
       package, to reduce its size.  The examples in this DOC file should
       make the examples in FDATEX.BAT unnecessary


8.4a   March 20, 1994
*      Added GETK (get keypress) function

*      Added ability to use /V when running in a Windows DOS box, thanks
       to a Turbo Pascal routine from the Turbo Professional library
       provided by Kim Kokkonen of TurboPower Software.

       Fixed a bug in which the prompt string (/Q) for the GET and GETU
       functions was being written to redirectable output (StdOut).  The
       prompt string is now written directly to the screen, and will not
       appear in FDATE's output when the output is redirected to a file.

       Removed ALARM.BAT, ALARM.DOC, TIC.BAT and TIC.DOC from distribution
       package.  They were too esoteric to be generally helpful.

       Added FILE_ID.DIZ and DESC.SDI to distribution package.

       Corrected algorithm for Mardi Gras in HOLIDAYS.BAT.  Modified
       HOLIDAYS.BAT and HOLIFEDS.BAT to make them more interactive, using
       FDATE's new abilities to get user input.

*      Started ZIPing FDATE.ZIP with PKZIP 2.04g rather than version 1.1

8.4b   April 2, 1994
       Revised example :08, to use /fgetK rather than /fgetU
       Fixed formatting of #dif function
       Reformatted examples to reduce number of printed pages
       Duplicate example :07 was renumbered 
       FORATIME.BAT (original version) removed as no longer interesting
       Modified JDATE.BAT to use new /Fget function

  8.4cSeptember 6, 1994
       Revised HOLIDAYS.BAT so it would not go into an infinite loop if
       run on a system where FDATE cannot manipulate the environment, and
       to pad the year to the left with zeroes, so years before 1000 will
       be accepted.

  Added example showing how to left-pad a number with zeroes.

       Rewrote example showing how to time execution of a program.

  Updated my home mailing address after moving.

       Corrected information on how to make sure you have enough
       environment space in a Windows DOS box.  Thanks for the feedback
       and on this issue from Ronny Richardson.

       Added WHATDAY.BAT (example :14).  Thanks for the request from Cal
       Pryluck, Radio-Television-Film, Temple University, Philadelphia

  8.5aSeptember 28, 1994
       Added output date format "mmddyy" (PKZIP's "American" date format),
       and an example showing how to use Fdate to get a date for use with
       PKZIP for archiving files.  Thanks for the tip on PKZIP's input
       formats from Dick Jensen.

  8.6aOctober 27, 1994
       Corrected a bug in output format T1: HOUR value was being prefixed
       by a leading zero if MINUTE value was less than 10.

8.7a   October 27, 1994
       Added output format TDOS, which mimics the format used in the DOS
       "time" command.  Added an example using it to the "roll your own"
       date format example (:19) as example (a).  Thanks for the request
       for this common time format from Roy Zider.

  8.8aNovember 06, 1994
       Changed error action in cases in which the prefix parm /P was
       specified.  In case of an error, the first line generated will
       always be "ERROR".  If prefix parm was specified, then a second
       line will be generated with the prefix followed by "ERROR".  Thus,
       if output is being routed to a batch file, and the prefix is
       something like "@set fdate=", then that will continue to work.

       Removed the example of using /Fe to put equal-signs and redirection
       symbols into the environment.  I doubt if anyone found this example
       useful.

       Added ability to break out of HELP using the ESC key

 *Added justify parm (/J)
  Re-wrote HOLIDAYS.BAT to illustrate uses for /J.

8.9a   1995 Feb 15
 *Added "absolute month" output format (/Omonth#)
       Added example YMD_DIF.BAT, which uses new /Omonth# facility
  Added FDATEBEG.TXT to the distribution .ZIP file

9.0a   1995 Feb 20
       prefixed "@" to the "echo ERROR ... " and "pause" that are
       generated when Fdate detects an error.  This should make error
       messages a bit easier to decipher.

9.1a   1995 May 15
       Corrected bug that gave runtime error when function was #mult and
       /A parm was 0.

  9.1b1995 June 12
       Corrected example of Japanese date format in this DOC file.  Thanks
       to Christopher Clark for pointing out the typo.

  9.1c1995 Oct 22
       Added a usage example to the discussion of the "file" input format
       (/If).  Thanks to Bob Stephan for the suggestion.

9.1d   1995 Dec 08
       Added comments to example :67 (putting date into filename) and
       changed output format to ccyymmdd.  Hopefully, these changes will
       make this popular example more useful and easier to understand.

9.2a   1996 Jan 28
*      Added /X (exclude) parm to /Fw (weekday arithmetic function). 
       Added appropriate documentation, and examples :46 and :47.  Thanks
       to Richard Rogers for a real-life application that required this
       feature.

9.2b   1996 Feb 1
       Rectified a minor documentation omission; I'd forgot to add /X to
       the overview list of FDATE parms. 
       Expanded FDATEBEG.TXT by adding the overview of things you can do
       with FDATE.

9.3a   1996 Apr 19
       Added output format mmddccyy.
       Added information on using Fdate with Windows NT.
       Added specific information on Garrett Wolman's FDATE.

9.4a   1996 Jun 10 
       Added input formats DAY# and MINUTE#.  This should enable a person
       to use Fdate to produce an absolute date or minute (using the DAY#
       or MINUTE# output format), manipulate it as he wishes (possibly in
       ways not supported by Fdate), and then convert the result back into
       a more readable format.  Specifically, this should allow a person
       to do "minute arithmetic" as well as "date arithmetic". Thanks to
       Kevin Jackson, of the New York State Executive Chamber, who
       reported the need to do time arithmetic.

       Added the MIN_MATH.BAT and TIME_SET.BAT examples.  
       Added news about TurboPower's withdrawal of support for
       environment-manipulating routines to documentation of /V parm under
       Windows NT.

9.4b   1996 Jun 24 
       Corrected minor bug in TIME_SET.BAT example.

9.5a   1997 March 17 
       Added #random function
       Added HHMMSSCC and HH:MM:SS:CC output formats 

9.6a   1997 April 22
       Fixed design flaw, in which justification was being applied to the
       entire output string, including prefix string and suffix string. 
       Now, justification is applied BEFORE prefix and suffix strings are
       added to output. 

       This essentially broke the "ECHO" function /FE.  So a /Q parm was
       added to the echo function that permits it to still be used with
       justification (the /J parm).  Modified all of the /FE examples that
       us justification, to show them working with the /Q parm rather than
       with /P.  Modified HOLIDAYS.BAT, which was affected by this change.

       Renamed all .DOC files to .TXT

       Added contact info for Garrett Wollman and PSL.
