Fdate 16a

2003-07-26 02:18:41

Project Home Page
1     INTRODUCTION   1 - What Is Fdate?
2     INTRODUCTION   2 - Author Information
3     INTRODUCTION   2a - Running FDATE under NT, Windows2000, XP
4     INTRODUCTION   3 - What To Do If This Documentation Seems Too Overwhelming
5     INTRODUCTION   4 - The 3-Minute Introduction to Fdate
6     INTRODUCTION   Revision History
7     FAQ   How can I rename a log file or a directory to a name containing today's date?
8     FAQ   How do I put FDATE's output into an environment variable?
9     OVERVIEW   Examples
10     OVERVIEW   Functions
11     OVERVIEW   Parameters
12     PARAMETER   /C - Custom Output Date Formats
13     PARAMETER   /F - The Function Parm -- Fdate's Most Important Parm
14     PARAMETER   /I - Input Date Formats
15     PARAMETER   /J - Justifying Output
16     PARAMETER   /L - Output Language
17     PARAMETER   /O - Output Date Formats (pre-defined)
18     PARAMETER   /Oxxx - Extended Hex Output Date Format
19     PARAMETER   /P - Output prefix
20     PARAMETER   /S - Output suffix
21     PARAMETER   /T - Time Override Parameter
22     FUNCTION   #2Xx - Convert An Integer To Extended Hex Notation
23     FUNCTION   #Add - Add Two Numbers
24     FUNCTION   #Comp - Compare Numbers
25     FUNCTION   #Dif - Calculate The Difference Between Two Integers
26     FUNCTION   #Div - Divide Two Numbers
27     FUNCTION   #Idiv - Integer Division Of Two Numbers
28     FUNCTION   #Mod - Modulus, Division Remainder
29     FUNCTION   #Mult - Multiply Two Numbers
30     FUNCTION   #Random - Produce A Random Number
31     FUNCTION   ADD a number of days to a date
32     FUNCTION   Comp - Compare Dates
33     FUNCTION   DIF - find the number of days between two dates
34     FUNCTION   Echo - Output A String
35     FUNCTION   F - Output A Formatted Date
36     FUNCTION   Get And Getu - Get User Input Functions
37     FUNCTION   Getk (Get Keypress) Function
38     FUNCTION   Len (Length) Function
39     FUNCTION   M - Month Date Arithmetic
40     FUNCTION   Substr (Substring) Function
41     FUNCTION   Tcomp - Compare Times
42     FUNCTION   Upper - Put A String Into Upper Case
43     FUNCTION   V - Date Validation
44     FUNCTION   W - Weekday Date Arithmetic
45     TOPIC   Fdate's Century-Assumption Algorithm
46     TOPIC   Fdate's Leap Year Algorithm
47     TOPIC   Fdate's Support For Long Filenames
48     TOPIC   How Fdate Thinks About Dates
49     TOPIC   How To Put Fdate Output Into An Environment Variable
50     TOPIC   Problem - /V Does Not Work Under NT, Windows2000, XP
51     TOPIC   Problem - /V Does Not Work Under Win3X Or Win9X
52     TOPIC   Xset - A Utility For Creating Environment Variables Under NT, Win2k, XP
53     TOPIC   Y2K - Is Fdate Y2K Compliant
54     APPENDIX   Another Utility Named "Fdate"
55     APPENDIX   Contents Of The Fdate.Zip Distribution File
56     APPENDIX   Fdate's Error Handling
57     APPENDIX   Fdate's Implementation Limits
58     APPENDIX   Revision History
59     APPENDIX   Symbols used in Date Formats
60     APPENDIX   Technical Support For Fdate
61     APPENDIX   Uploading Fdate To Electronic Bulletin Boards
62     APPENDIX   Use, Registration, And Distribution Of Fdate
63     APPENDIX   Where To Find The Most Current Version Of Fdate
64     EXAMPLE   01 Display Fdate output on screen
65     EXAMPLE   02 Redirect FDATE output to a file
66     EXAMPLE   03 Put FDATE output in an environment variable using a batch file
67     EXAMPLE   04 Put FDATE output in an environment variable using /V parm
68     EXAMPLE   05 Put FDATE output in an environment variable using STRINGS
69     EXAMPLE   06 Put FDATE output in an environment variable using GET
70     EXAMPLE   07 Get user input
71     EXAMPLE   08 Get a user menu selection
72     EXAMPLE   09 Change a date from one format into another
73     EXAMPLE   10 Find the difference in days between two dates
74     EXAMPLE   11 Find the elapsed days/hours/minutes between two date/times.
75     EXAMPLE   13 Find the elapsed years/months/days between two dates.
76     EXAMPLE   14 Determine how long it took a program to run
77     EXAMPLE   15 Find years when a given date fell on a given day of the week
78     EXAMPLE   16 Find calendar date corresponding to a "business Julian" date
79     EXAMPLE   17 Set your PC's date to a business Julian date
80     EXAMPLE   18 Determine if parm %1 contains a valid date
81     EXAMPLE   19 "Roll your own" date format
82     EXAMPLE   20 Find the 4th Thursday in November (Thanksgiving)
83     EXAMPLE   22 On a date, show what anniversary it is for some event
84     EXAMPLE   23 Show a list of holidays in a given year
85     EXAMPLE   24 Show a list of Federal holidays in a given year
86     EXAMPLE   25 Determine if a year is valid, and evenly divisible by 4
87     EXAMPLE   30 Find the date 1 month, 3 months, 1 year from today
88     EXAMPLE   33 MIN_MATH.BAT -- "time arithmetic" in minutes
89     EXAMPLE   34 TIME_SET.BAT -- "time arithmetic" -- set TIME
90     EXAMPLE   42 Get date to tell PKZIP to compress files older than 30 days
91     EXAMPLE   43 Loop through an array of environment variables
92     EXAMPLE   44 Do something on the last day (or last Friday) of the month
93     EXAMPLE   45 Get information about the month prior to the current month
94     EXAMPLE   46 Show the last Monday (or any other weekday) in this month
95     EXAMPLE   47 Show the last Monday in the month, for a series of months
96     EXAMPLE   50 Represent a date in 3 bytes of "extended hex" notation
97     EXAMPLE   51 Represent a date in a short (4-byte) format (technique #1)
98     EXAMPLE   52 Represent a date in a short (4-byte) format (technique #2)
99     EXAMPLE   53 Convert numbers to "extended hex" (XX) format
100     EXAMPLE   54 Customize Fdate for a language of your choice
101     EXAMPLE   55 Fergian.BAT (used in the previous example)
102     EXAMPLE   61 DO-ONCE: Run apps when booting for the first time of the day
103     EXAMPLE   62 Run specific software, depending on the day of the week
104     EXAMPLE   63 Run a program at a specified time later in the day
105     EXAMPLE   71 Extract the rightmost n characters of a string
106     EXAMPLE   72 Left-pad a number with zeroes, or a string with spaces
107     EXAMPLE   80 --- SECTION: CHECKING/MANIPULATING A FILE'S DATE/TIMESTAMP
108     EXAMPLE   81 Rename a file name to a name that contains today's date
109     EXAMPLE   82 Rename a file to a name that contains today's time
110     EXAMPLE   83 Rename a file to a name that contains today's date in only 3 bytes
111     EXAMPLE   85 Compare a file's date to today's date
112     EXAMPLE   86 Compare two files' date/time using COMPARE-FUNCTION ERRORLEVELS
113     EXAMPLE   87 Take action if a file has not been updated recently
114     EXAMPLE   88 Display a list of all files that were created/updated today.
115     EXAMPLE   89 Delete files more than X days old (use a batch-file subroutine)



Entry number 1                    Table of Contents

.INTRODUCTION: 1 - What Is Fdate?
.DISCUSSION..:
The Fdate motto is "Everything you'd ever want to do with dates in batch files."

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 APPENDIX Use, Registration, And Distribution Of Fdate


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


Entry number 2                    Table of Contents

.INTRODUCTION: 2 - Author Information
.DISCUSSION..:
The author of Fdate is:

Stephen Ferg

608 N. Harrison Street

Arlington, VA 22203-1416

USA

Internet : steve@ferg.org

telephone (voice, not FAX): (703) 525-2241

Also, you can see Steve Ferg's home page www.ferg.org which has the latest version of Fdate.


Entry number 3                    Table of Contents

.INTRODUCTION: 2a - Running FDATE under NT, Windows2000, XP
.DISCUSSION..:
NOTE that the /V parameter WILL NOT WORK under Windows NT and its derivatives such as Windows 2000 and Windows XP. For more information, see TOPIC Problem - /V Does Not Work Under NT, Windows2000, XP



Entry number 4                    Table of Contents

.INTRODUCTION: 3 - What To Do If This Documentation Seems Too Overwhelming
.DISCUSSION..:
As Fdate has grown in functionality over the years, its documentation has also grown. Folks who encounter Fdate for the first time sometimes feel 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!

see Introduction 4 - The 3-Minute Introduction to Fdate



Entry number 5                    Table of Contents

.INTRODUCTION: 4 - The 3-Minute Introduction to Fdate
.DISCUSSION..:
This is a "quick start" introduction to using Fdate.

INTRODUCTION: WHAT IS FDATE?

Fdate is a utility for doing date formatting and date arithmetic in DOS batch files. At least, that was its original purpose. Over the years, functions were added to Fdate to support activities that people often need to do in conjunction with working with dates.

To help you get started using Fdate, I've created this short introduction which shows how to use Fdate to do the things most users want to do. When you've finished, you may still have a question: "Can I do such-and- such with Fdate?" If it involves dates, it probably CAN be done with Fdate, although tricky things are of course tricky to do, even with Fdate. A good next step would be to look at the list of examples. With luck, you will find an example that shows Fdate doing just what you want to do. To understand how Fdate is working in a particular example, look up the parameters used in the example. see OVERVIEW Examples


THE 3-MINUTE INTRODUCTION TO FDATE

By far the most popular use of Fdate is to put today's date-- in a particular format-- into an environment variable. Once this has been done, the environment variable can be used and manipulated in many ways in a batch file. Here are a few short exercises that will help you to learn how to use Fdate's most basic features to do that.

1. At the DOS prompt, type:

       FDATE
This will show you Fdate's HELP screens. Press ENTER to page through the HELP screens.

The information on these HELP screens is very dense. It won't teach you how to use Fdate, but it is useful for jogging your memory as you become familiar with Fdate's various features.

2. At the DOS prompt, type:

       FDATE /Ff
I've used lowercase "f" here to distinguish the value of the parameter from the parameter-letter itself, but it really doesn't matter whether the parameter or its value is in upper or lower case. Except for the /K parameter (one of Fdate's advanced features), Fdate's parameters are not case sensitive.

Here, the value of the "/F" (function) parameter is "f" (format a date). The "/Ff" parameter tells Fdate that the function you want it to perform is to format a date. Since the default date is "today", this command will cause Fdate to display today's date on your screen in Fdate's default output format.

3. At the DOS prompt, type:

       FDATE /Ff /P"Today is "
This command is just like the one in the previous example, except that we've specified the "prefix parameter" (/P), which tells Fdate to add a string to the beginning of its output. (There is also a "suffix parameter" that tells Fdate to add a string to the end of its output.) Note that the value of the /P parameter is enclosed in quotes. (Either single quotes or double quotes will work.) We've had to enclose the value in quotes because it contains embedded blanks (one blank after the word "today" and another after the word "is").

4. At the DOS prompt, type:

       FDATE /Ff /Occyymmdd
(Or you can put the same statement in a batch file.)

Here, you are telling Fdate to put out today's date in a specific format. On the "output format" parm (/O) you are specifying that you want the day in "ccyymmdd" format: two digits each for century, year- within-century, month, day-of-month.

Note that the /O parm is a predefined, fixed, format. Fdate supports many such pre-defined output formats. If you want more flexibility, then you can "roll your own" date format using the /C (custom output) parameter.

5. At the DOS prompt, type:

       FDATE /Ff /C"$Today is $N $d, $Y"
Here, you are telling Fdate to put out a string that you have formatted. The /C parm tells Fdate that the output will be a customized format. The string after the /C is enclosed in quotes, because it contains blanks. The first character inside the string is a $ -- this tells Fdate that you will be using the $ as the escape character. The symbols $M, $d, and $Y have special meaning. (Note that, unlike most of Fdate's parameters, these special symbols ARE case-sensitive.) For more information, see PARAMETER /C - Custom Output Date Formats



6. At the DOS prompt, type:

      FDATE /Ff /Occyymmdd /p"@set date1="  >junk.bat
(Or you can put the same statement in a batch file.)

Here, you are telling Fdate to put out today's date in "ccyymmdd" format. Because you are specifying the redirection symbol (>) and a batch file name, Fdate's output is being redirected to the batch file. You can look at the batch file by using the DOS "type" command:

        TYPE JUNK.BAT
Now you can run the batch file by typing

        JUNK.BAT
at the DOS command prompt.

This will cause JUNK.BAT to run and to put today's date in the DATE1 environment variable. If you type "SET" at the DOS prompt, and if today is February 1, 1995, you will see as the last line of the SET output:

            DATE1=19950201
7. Use your favorite text editor to create a batch file called TEST.BAT. In TEST.BAT, put the following lines:

       @echo off
       FDATE /Ff /p"@set date1="  >junk.bat
       call  junk.bat
       del   junk.bat
       echo Today's date is: %date1%
       set  date1=
Note that in this example we have not specified an output format at all, so Fdate will use its default format.

Here is the same batch file, with some commentary:

       @echo off                *** turn ECHO off, so the batch file executes quietly
       FDATE /Ff /p"@set date1=" >junk.bat   *** you know what this does
       call  junk.bat           *** call junk.bat to set the date1 environment variable
       del   junk.bat           *** cleanup -- delete junk.bat
       echo Today's date is: %date1%     *** use the environment variable
       set  date1=              *** cleanup -- delete date1
8. At this point, you know everything you need to know to put today's date into an environment variable, which you can then use for whatever you want. As the last step in this introduction, here's an example in which you are copying a file (BACKUP.LOG, which is put out by a backup program) to a file whose name contains today's date.

            FDATE /Ff /Occyymmdd /Vdate1
            copy BACKUP.LOG  %date1%.LOG

WHAT TO DO NEXT?

Now that you know the basics, you may have everything you need to know in order to use FDATE to satisfy your basic date-handling needs. If you need more information, or are feeling adventurous, your next step should be to explore the Fdate documentation, which discusses many more features of FDATE.

One of the most useful parts of the documentation is the list of examples. Browse through the titles of the examples, to get a feel for what is there. see OVERVIEW Examples


Then look at the examples themselves. Many are quite elaborate (which is natural, since they are there to show you how to do Hard Stuff).

Most of the examples are self-contained and ready-to-run -- if you copy the text of the example into a batch file, the example code will run and do what the title says it will do. I suggest you try one or two of the examples that seem most interesting to you.

After the examples, the most useful parts of the Fdate documentation are the sections documenting Fdate's various functions (the functions that you can specify on the function parm, /F) and its various output formats. I suggest you scan those sections, just to get a quick feel for what's available to you.

Good Luck!

Steve Ferg


Entry number 6                    Table of Contents

.INTRODUCTION: Revision History
.DISCUSSION..:
For a listing of the FDATE revision history, goto APPENDIX Revision History



Entry number 7                    Table of Contents

.FAQ.........: How can I rename a log file or a directory to a name containing today's date?
.DISCUSSION..:
This is certainly the most frequently asked question regarding Fdate.

Here are several examples of renaming a file and a directory, to a date that contains a 2-digit or 4-digit year.

Note that in the custom output format, lower-case "y" indicates a 2-digit year, and upper-case "Y" indicates a 4-digit year.

Note that the rename operation will fail if a file/directory with the old name cannot be found, or if a file/directory with the new name already exists. That means that if you attempt to run the same command more than once a day, it will fail on the second attempt to run it because a file (or directory) with the new name will already have been created when you ran it the first time.

Note that we TYPE (echo to the screen) junk.bat before calling it. That way, if it fails, we will be able to see the text of the command that failed.

For more information on the custom output format, see the entry for the "/C" parameter.

.EXAMPLE.....:
@echo off
:: rename file BACKUP.LOG to yymmdd.LOG (ex. 950508.LOG on May 8, 1995)
FDATE /Ff /C"~@rename backup.log ~y~M~D.log"> junk.bat
type junk.bat
call junk.bat
del  junk.bat

.EXAMPLE.....:
@echo off
:: rename file BACKUP.LOG to ccyymmdd.LOG (ex. 19950508.LOG on May 8, 1995)
FDATE /Ff /C"~@rename backup.log ~Y~M~D.log"> junk.bat
type junk.bat
call junk.bat
del  junk.bat

.EXAMPLE.....:
@echo off
:: rename directory BACKUP to yymmdd (ex. 950508 on May 8, 1995)
FDATE /Ff /C"~@rename backup ~y~M~D"> junk.bat
type junk.bat
call junk.bat
del  junk.bat

.EXAMPLE.....:
@echo off
:: rename directory BACKUP to ccyymmdd (ex. 19950508 on May 8, 1995)
FDATE /Ff /C"~@rename backup ~Y~M~D"> junk.bat
type junk.bat
call junk.bat
del  junk.bat


Entry number 8                    Table of Contents

.FAQ.........: How do I put FDATE's output into an environment variable?
.DISCUSSION..:
There are two methods. One uses a temporary batch file. The other uses enhanced features of the FOR command.

Method 1 should work on all versions of Windows. But note that it will not work if the person running your batch file does not have WRITE permissions on the directory where you want to put junk.bat. If this is a problem, then you can work around it by creating the temporary batch file in a directory where you are sure that the user does have WRITE permissions -- for example, in the root directory of the C: drive: c:\junk.bat.

.EXAMPLE.....:
@echo off
:: put Fdate output into an environment variable called "date1"

:: ------------------------------------------------------------
:: METHOD #1 -- Use a temporary batch file
:: ------------------------------------------------------------
FDATE /Ff /ofull /p"set date1=" >junk.bat
call junk.bat
echo It is now %date1%

:: cleanup
del  junk.bat
set date1=

.DISCUSSION..:
An alternative work-around is to use Method 2, if you are using a version of Windows that supports it.

Method 2 uses enhanced features of the FOR command that should be available on Windows NT, Windows 2000, XP, and later versions of Windows. Note that the parameter "tokens=*" is required is the Fdate output contains multiple words -- as a general practice, you should always specify it. In using Method 2, you may have to watch carefully to make sure that any strings in quote-marks are closed by matching quote-marks of the correct type.

.EXAMPLE.....:
@echo off
:: put Fdate output into an environment variable called "date1"

:: ------------------------------------------------------------
:: METHOD #2 -- use the enhanced FOR command features
:: This method should work on Windows NT, Windows 2000, and XP
:: ------------------------------------------------------------
for /f "tokens=*" %%v in ('FDATE /Ff /C"~~Y-~M-~D (~W)"') do set date1=%%v
echo Today is %date1%

:: cleanup
set date1=


Entry number 9                    Table of Contents

.OVERVIEW....: Examples
.DISCUSSION..:
The examples in this file are listed here as Backward References.


Entry number 10                    Table of Contents

.OVERVIEW....: Functions
.DISCUSSION..:
Fdate's functions are listed here as Backward References.

.DISCUSSION..:
In this section, we present an overview of the functions that can specified on the /F (function) parameter.

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 in other sections of this documentation.

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

The general format of an Fdate statement is:

  • Fdate /Ffunc
with a variety of parameters following the /F.

For example:

  • Fdate /Ff
  • Fdate /Fadd /A5 /B6 [adds 5 and 6]
  • Fdate /Flen /Q"this is a test" [produces the length of "this is a test"]

GENERAL DATE FUNCTIONS

  • 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.

MATH FUNCTIONS

Note that these are NOT date math functions; they are NUMBER math 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

    Returns a random number between a lowerbound (specified on the /B parm) and an upperbound (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.
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.

  • #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 LT /A is less than /B
    • returns EQ /A is equal to /B
    • returns 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 file.

  • #2XX

    Convert number to "extended hex" format.

Entry number 11                    Table of Contents

.OVERVIEW....: Parameters
.DISCUSSION..:
Fdate's parameters are listed here as Backward References.

.DISCUSSION..:
Fdate accepts the following parameters:

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

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.

SUMMARY OF PARAMETERS

  • /F Requests a particular Fdate function. This is Fdate's most important parameter.

  • /A and /B For date functions, these two parameters are used to specify dates. 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.

  • /C specifies a "custom" output date format If the /C parameter is omitted, it is assumed that the output format will be specified on the /O parameter.

  • /D day-of-week number (used only with W function)

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

  • /J specifies justification, length, and pad character(s) 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.

  • /W The GETK function takes a /W "seconds to wait" parameter that tells it how many seconds to wait before returning the first key in the /K "keymask" parameter. Valid values are in the range of 1..36000 (10 hours). Default value of /W is 36000 (10 hours).

  • /L specifies language of output.
    • /Lus US (American) English-language output
    • /Lfr French-language output
    • /Lgr German-language output
    • /Lsp Spanish-language output
    • /Ldk Danish-language output (requires codepage 850 to display correctly)
    If the /L parameter is omitted, /Lus [American English] is assumed.

  • /N number of days (always a number)

  • /O specifies 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"

.DISCUSSION..:
  • /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 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 function W - Weekday Date Arithmetic


  • /Y Years to look back when converting a 2-digit year to a 4-digit year. Valid values are in range 0..99. Default is 80.

Entry number 12                    Table of Contents

.PARAMETER...: /C - Custom Output Date Formats
.CATEGORY....: parameters
.DISCUSSION..:
The CUSTOM OUTPUT FORMAT parameter (/C) is designed to be more flexible than Fdate's original OUTPUT DATE FORMAT parameter (/O). You may specify the /C parameter in conjunction with any Fdate function that produces a date or time as its output. The /C parm allows you to specify any desired output string, with components of the date and time inserted into the string in any place where they are desired.

The first character of the /C parm is taken to be the character that you want to use as the ESCAPE CHARACTER. Starting with character 2, the string specified on the /C parm is processed.

When an escape character is found, the next character will be processed as an INSERT CODE -- a character that indicates that a special value is to be inserted into the output string. If the INSERT CODE is the same as the escape character, the escape character is inserted. Otherwise, one of the following values is inserted. Note that these values for the insert code are case-sensitive. Upper-case and lower-case codes are related, with the lower-case code inserting a string that is generally shorter than the one inserted by the upper-case code.

DEBUGGING TIP

If you are having problems with your custom output format, make sure that the first character in the /C parm is the escape character. If the first thing in your output string is an insert code, then the string should start with TWO escape characters, one to define the escape character, and one to identify the insert code. For instance, to produce the current 4-digit year, you would code:

    fdate /ff  /c"~~Y"



  • J - JJJ Business Julian date with leading zeros (1999/009)
  • j - zzJ Business Julian date without leading zeros (1999/9)

  • Y - 4-digit year (1999)
  • y - 2-digit year (99)

  • A - time in AM/PM format with a space between the minute and am/pm (09:04 am)
  • a - time in AM/PM format with no space preceding the am/pm (09:04am)

  • D - Day of month with leading zeros (09)
  • d - Day of month without leading zeros (9)

  • M - Month number with leading zeros (09)
  • m - Month number without leading zeros (9)

  • I - Long ISO date (ccyy-mm-dd) (1999-09-09)
  • i - Short ISO date (ccyymmdd) (19990909)

  • T - Long ISO time (hh:mm:ss) (09:09:09)
  • t - Short ISO time (hhmmss) (090909)

  • H - Hour with leading zeros (09)
  • h - Hour without leading zeros (9)

  • R - am/pm hour with leading zeroes
  • r - am/pm hour without leading zeroes
  • Q - "am" or "pm", depending on the time

  • U - minUte with leading zeros (09)
  • u - minUte without leading zeros (9)

  • S - Second with leading zeros (09)
  • s - Second without leading zeros (9)

  • C - Hundredth of second with leading zeros (09)
  • c - Hundredth of second without leading zeros (9) Values for hundredths of a second are not available in a file timestamp, so this value will always be zero when displaying information from a file timestamp.

  • N - Name of month (January)
  • n - Name of month, left 3 characters (Jan)

  • W - Name of day-of-week (Wednesday)
  • w - Name of day-of-week, left 3 characters (Wed)
  • # - Day-of-week number

  • L - Leapyear flag (1=leapyear, 0= non-leapyear)

The results of an escape character followed by any other character are undefined. (This is to allow for the addition of future insert codes.)

.EXAMPLE.....:
   (The tilde "~" is used as the escape character)
   On April 4, 1999, the following statement:
      Fdate /Ff /c"~Today is ~W, ~N ~d, ~Y (ISO date ~Y-~M-~D)"
   produces: "Today is Sunday, April 4, 1999 (ISO date 1999-04-04)"

.NOTE........:
The names of the days and the months are controlled by the language parameter (/L), and will vary with the language. For examples, run CUSTOM.BAT.


Entry number 13                    Table of Contents

.PARAMETER...: /F - The Function Parm -- Fdate's Most Important Parm
.CATEGORY....: parameters
.DISCUSSION..:
The /F parameter specifies the function that you want Fdate to perform. It is the most important of Fdate's parms. For more information, see overview functions



Entry number 14                    Table of Contents

.PARAMETER...: /I - Input Date Formats
.CATEGORY....: parameters
.DISCUSSION..:
For a list of the symbols used in specifying fixed date formats, see APPENDIX Symbols used in Date Formats


ABSOLUTE DATE -- day#

Returns the "absolute date", that is, the date expressed as the number of days since the beginning of the calendar.

ABSOLUTE TIME -- minute#

Returns the "absolute minute", that is, the time expressed as the number of minutes since midnight, January 1, 1990.


FILE DATE/TIME STAMP -- /IF

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.

   Fdate /Ff /If /Afilex.txt /P"FILEX.TXT 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. "FooBar.1" and "C:\DBASE\WORKDIR\FooBar.1" are both acceptable.

A filename may contain wildcards, but only if there is only one file that matches the wildcard. If Fdate finds more than one file that matches the filespec, it will return an error message.

CALENDAR DATE INPUT FORMATS

 FORMAT      EXAMPLES      DISCUSSION
 ------      --------------------------------------
 ccyymmdd    19922002
   yymmdd      922002     Century will be assumed.
see Topic Fdate's Century-Assumption Algorithm


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

  yy-mm-dd    92-02-20    Leading zeros MUST be present, since the
              92/02/20    date does not begin with dd-mm or mm-dd.
              92.02.20    century is assumed
:see Topic Fdate's Century-Assumption Algorithm


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.
             2/5/92       century is assumed.
:see Topic Fdate's Century-Assumption Algorithm

                          ---------------------------------------
                          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.
             5/2/92       century is assumed.
see Topic Fdate's Century-Assumption Algorithm



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 Topic Fdate's Century-Assumption Algorithm

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


Entry number 15                    Table of Contents

.PARAMETER...: /J - Justifying Output
.CATEGORY....: parameters
.DISCUSSION..:
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 or character string.

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 BEFORE the strings specified on the /P (prefix) and /S (suffix) parms are added to the output.

The format of the /J parm is:

       /J"TP##"
In this example:

          - - - - - - my output string - - - - - -
          -*--*--*--*- my output string -*--*--*--*-
Note that when the pad string is more than one character, output will be slightly unpredictable, as it will depend on the length of the pad string, the length of the field in which the output is to be justified, and the length of the (pre-justification) 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.

.EXAMPLE.....:
  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.

.EXAMPLE.....:
  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.

.EXAMPLE.....:
  For more examples, see HOLIDAYS.BAT.


Entry number 16                    Table of Contents

.PARAMETER...: /L - Output Language
.CATEGORY....: parameters
.DISCUSSION..:
Fdate supports output in several different languages. The /L parm specifies the language of output.

  • /Lus US (American) English-language output [the default]
  • /Lfr French-language output
  • /Lgr German-language output
  • /Lsp Spanish-language output
  • /Ldk Danish-language output (requires codepage 850 to display correctly)
The /L parm affects the following predefined outputs. These language-specific output formats produce the date/time in whatever is the most common expression in the given language. The formats will vary from language to language.

  • full -- the full date and time, including the weekday
    • 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 -- the full date, including the weekday
    • Saturday, February 5, 1992
    • samedi le 5 fevrier 1992 [/Lfr specified]
    • Mittwoch, 5. Februar 1992 [/Lgr specified]

  • t1 -- the time
    • 9:05 am [/Lus specified]
    • 21:05 [/Lgr specified]
The /L parm also affects components of custom output formats such as the name of the weekday, and of the month.


Entry number 17                    Table of Contents

.PARAMETER...: /O - Output Date Formats (pre-defined)
.CATEGORY....: parameters
.DISCUSSION..:
This set of fixed formats has been largely been replaced by the /C format introduced in Fdate version 10. It is documented here for backward compatibility, and some of the "canned" formats (e.g. /Ofull) that may still be useful. see PARAMETER /C - Custom Output Date Formats


For a list of the symbols used in specifying fixed date formats, see APPENDIX Symbols used in Date Formats


.EXAMPLES....:
  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    dot-separated format

  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     dot-separated format

  mm/dd/yy      02/08/92
  mm-dd-yy      02-08-92
  mm.dd.yy      02.08.92      dot-separated format

  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    dot-separated format

  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     dot-separated format

  dd/mm/yy      02/08/93
  dd-mm-yy      02-08-93
  dd.mm.yy      02.08.93      dot-separated format

  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       dot-separated format


 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


  LANGUAGE-SPECIFIC OUTPUT FORMATS
  ===============================================

  These language-specific output formats produce the date/time in whatever is the most
  common expression in the given language.  The formats will vary from language to language.

  full      -- the full date and time, including the weekday
            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        -- the full date, including the weekday
            Saturday, February 5, 1992
            samedi le 5 fevrier 1992      [/Lfr specified]
            Mittwoch, 5. Februar 1992     [/Lgr specified]

  t1        -- the time
            9:05 am [/Lus specified]
            21:05   [/Lgr specified]


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

  ddmn3yy   05Feb92


Also:
see PARAMETER /Oxxx - Extended Hex Output Date Format

  -----------------------------------------------------------------------
  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
  ===================

For related information,
see PARAMETER /T - Time Override Parameter

  tdos          9:05:10:10a     format used in DOS's TIME command (in the United States)
                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
  =================================

For related information,
see PARAMETER /T - 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.


Entry number 18                    Table of Contents

.PARAMETER...: /Oxxx - Extended Hex Output Date Format
.CATEGORY....: parameters
.DISCUSSION..:
The "extended hex" output format is a pre-defined output format, represented as:

/Oxxx

This format represents dates for the years 1990-2024 in 3 characters of "extended hex" ("XX") notation. For more on XX notation, see FUNCTION #2Xx - Convert An Integer To Extended Hex Notation


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.

.EXAMPLES....:
     "1993 Feb  1"  is represented as  "321"
     "2000 Dec 25"  is represented as  "ACP"


Entry number 19                    Table of Contents

.PARAMETER...: /P - Output prefix
.CATEGORY....: parameters
.DISCUSSION..:
Supplying a value for the /P parameter prepends the value to the Fdate output:

Example: On July 4, 2003

  fdate /ff /oCCYY-MM-DD /p"Today is: "
produces

 Today is: 2003-07-04
A common use for this feature is to help create a batch file that sets an environment variable containing the Fdate output.

  Fdate /ff /oCCYY-MM-DD /p"set date1" >junk1.bat
  call junk1.bat
  del  junk1.bat
This feature was needed before the introduction of the /C (custom output format). Since then, there is less need for it, although it is still convenient for many purposes.

This is a companion parameter to the /S parameter.


Entry number 20                    Table of Contents

.PARAMETER...: /S - Output suffix
.CATEGORY....: parameters
.DISCUSSION..:
Supplying a value for the /S parameter appends the value to the Fdate output:

Example: On July 4, 2003

  set num=3
  fdate /ff /oCCYY-MM-DD /s" -- %num% backup files were generated today"
produces

 2003-07-04 -- 3 backup files were generated today
This feature was needed before the introduction of the /C (custom output format). Since then, there is less need for it, although it is still convenient for many purposes.

This is a companion parameter to the /P parameter.


Entry number 21                    Table of Contents

.PARAMETER...: /T - Time Override Parameter
.CATEGORY....: parameters
.DISCUSSION..:
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).

.EXAMPLE.....:
@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


Entry number 22                    Table of Contents

.FUNCTION....: #2Xx - Convert An Integer To Extended Hex Notation
.CATEGORY....: functions
.DISCUSSION..:
This function takes an integer supplied on parameter /A, and returns a single character in extended hex (XX) notation.

  • The input number must be an integer in the range of 0-35. A number of less than 0 or larger than 35 is rejected as an error.

ABOUT EXTENDED HEX NOTATION

"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.

With extended hex, even the 31st day of a month can be expressed as a single character (31 = V). So a monthly date can be expressed as just two characters. October 31 is "AV".

.EXAMPLE.....:
     :: returns the letter "Z"
     Fdate /F#2xx /A35

.TABLE.......:
      number:    in XX is:
        0           0
        1           1
        9           9
       10           A
       15           F
       16           G
       17           H
       30           U
       31           V
       35           Z


Entry number 23                    Table of Contents

.FUNCTION....: #Add - Add Two Numbers
.CATEGORY....: functions
.DISCUSSION..:
Add the integers specified on the /A and /B parms. To do subtraction, add a negative number to a positive number.


Entry number 24                    Table of Contents

.FUNCTION....: #Comp - Compare Numbers
.CATEGORY....: functions
.DISCUSSION..:
Fdate /F#comp /Anum /Bnum

#comp compares the integers specified on the /A and /B parms.

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

In addition, the errorlevel is set to a special value:

  • LT = 101
  • EQ = 102
  • GT = 103

Entry number 25                    Table of Contents

.FUNCTION....: #Dif - Calculate The Difference Between Two Integers
.CATEGORY....: functions
.DISCUSSION..:
Returns the difference between the integers specified on the /A and /B parms.


Entry number 26                    Table of Contents

.FUNCTION....: #Div - Divide Two Numbers
.CATEGORY....: functions
.DISCUSSION..:
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.


Entry number 27                    Table of Contents

.FUNCTION....: #Idiv - Integer Division Of Two Numbers
.CATEGORY....: functions
.DISCUSSION..:
Integer division. Divide the integer on the /A parm by the integer on the /B parm, and return the result as an integer.


Entry number 28                    Table of Contents

.FUNCTION....: #Mod - Modulus, Division Remainder
.CATEGORY....: functions
.DISCUSSION..:
Modulus. Divide the integer on the /A parm by the integer on the /B parm, and return the remainder.


Entry number 29                    Table of Contents

.FUNCTION....: #Mult - Multiply Two Numbers
.CATEGORY....: functions
.DISCUSSION..:
#mult

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


Entry number 30                    Table of Contents

.FUNCTION....: #Random - Produce A Random Number
.CATEGORY....: functions
.DISCUSSION..:
#RANDOM returns a random number between a lowerbound number and an upperbound number.

More precisely, it returns a number X, where:

That is:

RESTRICTIONS

.EXAMPLE.....:
@echo off
:: a batch file to demonstrate generation of a
:: random number between 3 and 10, and putting
:: it into an environment variable named RAND

Fdate /f#random /A10 /B3 /p"@set RAND=">junk.bat
call junk.bat
del  junk.bat

echo Random number is %RAND%
:: use the RAND environment variable as you wish, here.

:: cleanup
set RAND=


Entry number 31                    Table of Contents

.FUNCTION....: ADD a number of days to a date
.CATEGORY....: functions
.DISCUSSION..:
This function can be used to add N days to a date. Supplying a negative number for N will subtract N days from the date.

The number of days should be specified on the /N parm. For example N90 for 90 days.

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

.FORMAT......:
 Fdate /Fadd /Nnumdays /Adate /Iformat /Oformat

 adds    numdays to the date specified on the /A parm
 and     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


Entry number 32                    Table of Contents

.FUNCTION....: Comp - Compare Dates
.CATEGORY....: functions
.DISCUSSION..:
Fdate /Fcomp /Adate /Bdate /Iformat

COMP compares the dates specified on the /A and /B parms (time granularity = 1 day).

In addition, the errorlevel is set to a special value:


Entry number 33                    Table of Contents

.FUNCTION....: DIF - find the number of days between two dates
.CATEGORY....: functions
.DISCUSSION..:
Returns number of days between /Adate and /Bdate

The 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.

.FORMAT......:
  Fdate /Fdif /Adate /Bdate /Iformat

.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


Entry number 34                    Table of Contents

.FUNCTION....: Echo - Output A String
.CATEGORY....: functions
.DISCUSSION..:
EXAMPLE: Fdate /Fe /P"My name" /q" is " /S"Sonny-boy Slim"

The ECHO function (/Fe) produces only the strings specified using the /Q, /P, and /S parameters.

The /Fe function is mostly useful in conjunction with the /J (justify) parm. Justification, if specified using the /J parm, is applied only to the string, if any, supplied on the /Q parm. see PARAMETER /J - Justifying Output


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 "|". However, as we move into more advanced Windows environments (that is, NT and its derivatives, Win2000 and XP), the /V parm will no longer work, and this nifty feature will no longer be available.


Entry number 35                    Table of Contents

.FUNCTION....: F - Output A Formatted Date
.CATEGORY....: functions
.DISCUSSION..:
FUNCTION Fdate /Ffunc /Adate /Iformat /Oformat

Since /Aformat and /Oformat can be different, the FORMAT function is used to change a date from one format to another.

The date formatting function "f" (invoked as "/Ff") returns /Adate in format specified by /Oformat

Because of the wide variety of output formats, the FORMAT function can also be used to determine the day of week of the ate, whether the date is in a normal or leap year, etc.

"format" is an obsolete, deprecated, synonym for this function.

.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


Entry number 36                    Table of Contents

.FUNCTION....: Get And Getu - Get User Input Functions
.CATEGORY....: functions
.DISCUSSION..:
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.

GET == get user input (case is unchanged from what was entered)

GETU == get user input (uppercase)

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.


FILTERING OF INPUT -- A FEATURE THAT Fdate DOES NOT PROVIDE

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.


Entry number 37                    Table of Contents

.FUNCTION....: Getk (Get Keypress) Function
.CATEGORY....: functions
.DISCUSSION..:
The GETK 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:

For 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.

SPECIFYING HOW MANY SECONDS TO WAIT FOR A KEYPRESS

Starting with version 10, GETK takes a /W "seconds to wait" parameter that tells it how many seconds to wait before returning the first key in the /K "keymask" parameter. Valid values are in the range of 1..36000 (10 hours). Default value of /W is 36000 (10 hours).



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.

.EXAMPLE.....:
  @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

.DISCUSSION..:
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:

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.


Entry number 38                    Table of Contents

.FUNCTION....: Len (Length) Function
.CATEGORY....: functions
.DISCUSSION..:
The "len" function produces a number that is the length of the string on the /Q parm.

For example:

   Fdate /Flen /Q"this is a test"
returns 14


Entry number 39                    Table of Contents

.FUNCTION....: M - Month Date Arithmetic
.CATEGORY....: functions
.DISCUSSION..:
Function name is "m" for "month arithmetic".

Here is an example:

       Fdate /Fm /Nnumdays /Adate /Iformat /Oformat
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

.DISCUSSION..:

Fdate's MONTH DATE ARITHMETIC IS SMART!

Month arithmetic that is done just by subtracting a certain number of months can produce non-existent dates. For example, subtracting one 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 smarter 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.

Problems with overly-simple date arithmetic are not merely academic. Here is a passage from Peter G. Neumann's INSIDE RISKS column in COMMUNICATIONS OF THE ACM, June 1992 (Vol. 35, No. 6). The column title was "Leap-Year Problems":


Entry number 40                    Table of Contents

.FUNCTION....: Substr (Substring) Function
.CATEGORY....: functions
.DISCUSSION..:
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:

 EXAMPLE....:  Fdate /Fsubstr  /A-2 /Qabcd
 CALCULATION:  StartColumn = length(ParmQ) + 1 + ParmA
               StartColumn =      4        + 1 + (-2)     = 3
.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

.DISCUSSION..:
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"

Entry number 41                    Table of Contents

.FUNCTION....: Tcomp - Compare Times
.CATEGORY....: functions
.DISCUSSION..:
 Fdate /Ftcomp /Adate /Bdate /Iformat
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 /AFooBar.1 /Bfilezzz.1
In addition, the errorlevel is set to a special value:


Entry number 42                    Table of Contents

.FUNCTION....: Upper - Put A String Into Upper Case
.CATEGORY....: functions
.DISCUSSION..:
The UPPER function produces the string on the /Q parm, converted to upper case.


Entry number 43                    Table of Contents

.FUNCTION....: V - Date Validation
.CATEGORY....: functions
.DISCUSSION..:
The date validation function is "V". It can be used by specify that the function is to be validation: "/Fv".

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.


Entry number 44                    Table of Contents

.FUNCTION....: W - Weekday Date Arithmetic
.CATEGORY....: functions
.DISCUSSION..:
This function provides a way of doing date arithmetic in terms of weeks rather than days.

Function name is "w" for "week arithmetic".

EXAMPLE: Fdate /Fw /Nnumdays /Adate /Iformat /Oformat

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...

then /Fw returns the date of the third Thursday after November 14, 1992. (See full example, below)


NEGATIVE VALUES FOR /N

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 ...

IF THE /X PARM IS PRESENT ...

.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: "


Entry number 45                    Table of Contents

.TOPIC.......: Fdate's Century-Assumption Algorithm
.DISCUSSION..:
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 must estimate which century the year is in.

Starting with version 9.8, Fdate does the following:

First, Fdate obtains the current year from the system clock. Then it looks inside a 100-year window (which floats, based on the current year) to find a two-digit year that matches the input year. When it finds it, it uses the century of the year that it has found.

The boundaries of the window are calculated in the following way.

Let Y stand for the number of years that Fdate looks backward.

   EXAMPLES
   ==========================================
   If Y is 80, and the current year is 1999,
   then the window extends from 1919 to 2018.

   If Y is 80, and the current year is 2050,
   then the window extends from 1970 to 2069.

   If Y is 10, and the current year is 2000,
   then the window extends from 1990 to 2089.
The default value of Y is 80. This value can be over-ridden by the /Y parameter. /Y40, for example, would set Y to 40.

If specified, the /Y parameter must be an integer between 0 and 99. Specifying /Y99 will cause Fdate to look only into the past. Specifying /Y0 will cause Fdate to look only into the future.

Note that this date-windowing algorithm is not "fixed". That is, it is not tied to any particular year, and specifically it is not tied to the year 2000. The date window floats along with the current year. And because it floats, it will produce reasonable results in the year 2000, 2050, 2100, and even 3000.


Entry number 46                    Table of Contents

.TOPIC.......: Fdate's Leap Year Algorithm
.DISCUSSION..:
Here is how Fdate decides whether or not a year is a leap year.

Using this algorithm:

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


Entry number 47                    Table of Contents

.TOPIC.......: Fdate's Support For Long Filenames
.DISCUSSION..:
Fdate, because it is a 16-bit application, does not support long filenames.


Entry number 48                    Table of Contents

.TOPIC.......: How Fdate Thinks About Dates
.DISCUSSION..:
Also, see Topic Fdate's Century-Assumption Algorithm
see Topic Fdate's Leap Year Algorithm


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 eleven days that were dropped from the British calendar when Britain moved from the Julian to the Gregorian calendar in the 18th century, or the 13 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" date: a date expressed as the number of days from some day in the distant past.


Entry number 49                    Table of Contents

.TOPIC.......: How To Put Fdate Output Into An Environment Variable
.DISCUSSION..:

CALL A BATCH FILE

The most basic way to put Fdate's output into an environment variable, although not the most convenient, is to:

         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 freeware utilities that are written specifically to manipulate environment variables. Fdate's output can be put into an environment variable by piping it to one of these utilities.

For older, DOS-based systems, Bob Stephan's GET and PC Magazine's STRINGS are excellent choices.

If you are running Windows NT, Windows 2000, or Windows XP, see TOPIC Xset - A Utility For Creating Environment Variables Under NT, Win2k, XP


Fdate's /V PARAMETER

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. 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

Fdate's /V PARAMETER CAN NOT ALWAYS BE USED

NOTE HOWEVER that the /V parameter WILL NOT WORK under Windows NT, Win2k, or XP. see TOPIC Problem - /V Does Not Work Under NT, Windows2000, XP


There may be times when the /V parameter does not work under Win3x or Win9x. Sometimes it is possible to correct these problem situations. see TOPIC Problem - /V Does Not Work Under Win3X Or Win9X


In addition, due to the complexities of manipulating the environment, there may be other circumstances on older machines 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), are running under Carousel, etc. In such cases, you must use one of the more basic techniques described above.


Entry number 50                    Table of Contents

.TOPIC.......: Problem - /V Does Not Work Under NT, Windows2000, XP
.DISCUSSION..:
There are two problems that people commonly report when attempting to run Fdate under Windows NT (and its derivatives, Win2000 and Windows XP). One is that they run out of environment space. The other is that the /V parm does not work, and Fdate's output is not being put into an environment variable. These problems will apply to all versions of NT, including NT 4.0, Window2000, and XP.

/V DOES NOT WORK

The bottom line is that Fdate's /V feature doesn't work under Windows NT, 2k, or XP. Microsoft never made it easy to access the environment programmatically, and the situation became worse in Windows NT, to the point where TurboPower Software, which markets add-on utilities, withdrew support for utilities that change environment variables. Since Fdate uses these utilities, Fdate's /V feature will not work under NT, 2k, or XP.

This does not mean, however, that Fdate can't be used with those operating systems. What it means is that 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.

CALL A BATCH FILE

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

       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.

You might also want to investigate a utility called XSET. see TOPIC Xset - A Utility For Creating Environment Variables Under NT, Win2k, XP



Entry number 51                    Table of Contents

.TOPIC.......: Problem - /V Does Not Work Under Win3X Or Win9X
.DISCUSSION..:

"OUT OF ENVIRONMENT SPACE"

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). This does not give a subprocess any free space that it can use for its own purposes, so when it tries to set an environment variable, you get the "out of environment space" message. This is a problem that may affect any process that runs in a "DOS box" under Windows, and sets an environment variable.

The trick is to tell Windows that when it starts the "DOS box" (COMMAND.COM), it should allocate a certain minimum amount of memory for the environment, regardless of the amount that is currently being used.


How to do it under NT, Windows2000, XP

/V will not work under NT, Windows2000, or XP. see TOPIC Problem - /V Does Not Work Under NT, Windows2000, XP



How to do it under Win95

Select the shortcut icon that you use to start MS-DOS. Rhex ight-click on it. When the pop-up menu appears, click on PROPERTIES. When the properties for the shortcut come up, click on the MEMORY tab. When the tab sheet is displayed, set a value for INTITIAL ENVIRONMENT. I usually set it to 2048 (that is, 2K) bytes. This will ensure that when DOS (COMMAND.COM) is started, 2K bytes are allocated to the environment.


Windows 3.1

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.


DOS or Windows 3.0 and earlier

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.


Using 4Dos, NDOS, And UMB

Aran Spence has reported 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.




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.


Entry number 52                    Table of Contents

.TOPIC.......: Xset - A Utility For Creating Environment Variables Under NT, Win2k, XP
.DISCUSSION..:
XSET 5.29 : Extended SET Instruction

(C) 1991-1998 Stern Marc

Everything you always wanted to put in an environment variable but were afraid to ask DOS, NT or OS/2 for . . .

XSET: The easy way to write efficient batch files.

XSET allows you to put EVERYTHING you want in a variable of the current environment and use it as if you had assigned it the value with the standard DOS command 'SET'. You will be able to write very efficient batch files including string manipulation, calculation, ...

XSET is the most powerful environment variable manipulation program you have ever seen. It also has a very easy and intuitive user interface (very close to the 'SET' command). It is not a resident program; so it will not interfere with any of your other applications.

XSET is fully compatible with MS-DOS (from 3.30), DR-DOS, NDOS, 4DOS, OS/2, Windows 95/98 and Windows NT.


XSET has seven major features:

WEB CONTACT INFO

xset.tripod.com


Entry number 53                    Table of Contents

.TOPIC.......: Y2K - Is Fdate Y2K Compliant
.DISCUSSION..:
Starting in 1998, I began receiving frequent enquiries as to whether Fdate is Y2K-compliant.

The short answer is:

The long answer is:

Fdate's YEAR-ASSUMPTION ALGORITHM, AND Y2K

Prior to version 9.8 Fdate used a "fixed" date-windowing algorithm for dealing with 2-digit years.

if YY is greater than 20, then CC (the century) = 19

if YY is less than or equal 20, then CC = 20

This algorithm (like most Y2K date-windowing algorithms) is date-dependent on the turn of the century that will occur in 2000. I have developed a new algorithm that is independent of that date, and it is the primary reason for the release of Fdate version 9.8 in March 1999. Starting with version 9.8 Fdate uses a "floating" date-windowing algorithm for dealing with 2-digit years. This algorithm will NEVER expire.

see TOPIC Fdate's Century-Assumption Algorithm



Entry number 54                    Table of Contents

.APPENDIX....: Another Utility Named "Fdate"
.DISCUSSION..:
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.


Entry number 55                    Table of Contents

.APPENDIX....: Contents Of The Fdate.Zip Distribution File
.DISCUSSION..:
The current distribution package (Fdate.ZIP) contains the following:

[demonstration batch files]

[documentation files for use in BBS distribution]


Entry number 56                    Table of Contents

.APPENDIX....: Fdate's Error Handling
.DISCUSSION..:
If Fdate detects an error:

(1) it will return an errorlevel of 1 (rather than 0), and

(2) its output will be 3 lines:

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:

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


Entry number 57                    Table of Contents

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

Fdate is a 16-bit MS-DOS program, which means that it cannot handle long filenames.


Entry number 58                    Table of Contents

.APPENDIX....: Revision History
.DISCUSSION..:
Letters appended to version numbers indicate modifications to the doc files, without any modification to the Fdate.EXE software.


16a 2003 July 04

15a 2001 September 11

14d 2001 July 26

14c 2001 Jun 21

14b 2001 Mar 21

14a 2000 Aug 28

13a 2000 Aug 15

12a 1999 May 9

11a 1999 May 4

10a 1999 Mar 27

9.9a 1999 Mar 23

9.8a 1999 Mar 07

9.7a 1997 Dec 01

9.6a 1997 April 22

9.5a 1997 March 17

9.4b 1996 Jun 24

9.4a 1996 Jun 10

9.3a 1996 Apr 19

9.2b 1996 Feb 1

9.2a 1996 Jan 28

9.1d 1995 Dec 08

9.1c 1995 Oct 22

9.1b 1995 June 12

9.1a 1995 May 15

9.0a 1995 Feb 20

8.9a 1995 Feb 15

8.8a November 06, 1994

8.7a October 27, 1994

8.6a October 27, 1994

8.5a September 28, 1994

8.4c September 6, 1994

8.4b April 2, 1994

8.4a March 20, 1994

8.3a Feb 24, 1994

8.2 August, 1993

8.1 July 27, 1993 BUG FIX

8.0 July, 1993

7.1a Apr 15, 1993

7.0a Nov 14, 1992


Entry number 59                    Table of Contents

.APPENDIX....: Symbols used in Date Formats
.DISCUSSION..:
The following symbols are used in specifying input (/I) and output (/O) 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: "


Entry number 60                    Table of Contents

.APPENDIX....: Technical Support For Fdate
.DISCUSSION..:
Send e-mail message to Stephen Ferg at

steve@ferg.org

When sending your message, please let me know what version of Fdate you're using.


Entry number 61                    Table of Contents

.APPENDIX....: Uploading Fdate To Electronic Bulletin Boards
.DISCUSSION..:
Feel free to post copies of the Fdate distribution file to any BBS that you wish.


Entry number 62                    Table of Contents

.APPENDIX....: Use, Registration, And Distribution Of Fdate
.DISCUSSION..:
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 documentation files (Fdate.TXT, HISTORY.TXT, EXAMPLES.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.


Entry number 63                    Table of Contents

.APPENDIX....: Where To Find The Most Current Version Of Fdate
.DISCUSSION..:
For many years, up until 1999, one was always be able to find the most recent version of Fdate on CompuServe. The filename was Fdate.ZIP, and it was available in the CIS:IBMSYS forum (library 1, the "DOS Utilities" library).

However, more recently, the best way to find the most recent version of Fdate is on Steve Ferg's home page www.ferg.org

If this doesn't work, you can contact me directly via e-mail at steve@ferg.org


Entry number 64                    Table of Contents

.EXAMPLE.....: 01 Display Fdate output on screen
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
FDATE /Ff /At /Od1 /P"Today is "


Entry number 65                    Table of Contents

.EXAMPLE.....: 02 Redirect FDATE output to a file
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
FDATE /Ff /At /Od1 /P"Today is " >FDATE.OUT


Entry number 66                    Table of Contents

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


Entry number 67                    Table of Contents

.EXAMPLE.....: 04 Put FDATE output in an environment variable using /V parm
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
FDATE /Ff /Atoday /O"mn zd, ccyy" /Vdate1


Entry number 68                    Table of Contents

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


Entry number 69                    Table of Contents

.EXAMPLE.....: 06 Put FDATE output in an environment variable using GET
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
FDATE /Ff /Atoday /O"mn zd, ccyy" |GET ZE /Vdate1 >NUL


Entry number 70                    Table of Contents

.EXAMPLE.....: 07 Get user input
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
@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=


Entry number 71                    Table of Contents

.EXAMPLE.....: 08 Get a user menu selection
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
@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


Entry number 72                    Table of Contents

.EXAMPLE.....: 09 Change a date from one format into another
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
:: change date from mm-dd-yy format to ccyymmdd format
FDATE /Ff /Imm-dd-yy /A05-08-92 /Occyymmdd


Entry number 73                    Table of Contents

.EXAMPLE.....: 10 Find the difference in days between two dates
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
FDATE /Fdif /Imm-dd-ccyy /A%date1% /B%date2% /vdif
echo The difference is %dif% days.


Entry number 74                    Table of Contents

.EXAMPLE.....: 11 Find the elapsed days/hours/minutes between two date/times.
.CATEGORY....: examples
.DISCUSSION..:
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.

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.

.CODE........:
@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


Entry number 75                    Table of Contents

.EXAMPLE.....: 13 Find the elapsed years/months/days between two dates.
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
@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


Entry number 76                    Table of Contents

.EXAMPLE.....: 14 Determine how long it took a program to run
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
@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=


Entry number 77                    Table of Contents

.EXAMPLE.....: 15 Find years when a given date fell on a given day of the week
.CATEGORY....: examples
.DISCUSSION..:
This program has virtually no data validation, but if you are careful to enter valid input data, it does the job.

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.

.CODE........:
 @echo off
 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=


Entry number 78                    Table of Contents

.EXAMPLE.....: 16 Find calendar date corresponding to a "business Julian" date
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
:: business Julian date is 1992:045.   Note input format CCYYjjj
FDATE /Ff /A1992045  /Iccyyjjj  /Od1

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

:: You can assume the century, if you specify the YYjjj input format
FDATE /Ff /A9245  /Iyyjjj  /Od1


Entry number 79                    Table of Contents

.EXAMPLE.....: 17 Set your PC's date to a business Julian date
.CATEGORY....: examples
.DISCUSSION..:
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.

.CODE........:
@echo off

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.


Entry number 80                    Table of Contents

.EXAMPLE.....: 18 Determine if parm %1 contains a valid date
.CATEGORY....: examples
.DISCUSSION..:
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.

.CODE........:
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


Entry number 81                    Table of Contents

.EXAMPLE.....: 19 "Roll your own" date format
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
@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%]


Entry number 82                    Table of Contents

.EXAMPLE.....: 20 Find the 4th Thursday in November (Thanksgiving)
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
Fdate /Fw /D5 /N4 /A11-01-%year% /Imm-dd-ccyy /Od1 /P"Thanksgiving: "


Entry number 83                    Table of Contents

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

.CODE........:

Entry number 84                    Table of Contents

.EXAMPLE.....: 23 Show a list of holidays in a given year
.CATEGORY....: examples
.DISCUSSION..:
See HOLIDAYS.BAT demo batch file

.CODE........:

Entry number 85                    Table of Contents

.EXAMPLE.....: 24 Show a list of Federal holidays in a given year
.CATEGORY....: examples
.DISCUSSION..:
See HOLIFEDS.BAT demo batch file

.CODE........:

Entry number 86                    Table of Contents

.EXAMPLE.....: 25 Determine if a year is valid, and evenly divisible by 4
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
@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 ===================================================================

:: 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


Entry number 87                    Table of Contents

.EXAMPLE.....: 30 Find the date 1 month, 3 months, 1 year from today
.CATEGORY....: examples
.DISCUSSION..:
This example uses Fdate's month-arithmetic function: /Fm.

The /N parm specifies the number of months that we want to add to the date specified on the /A parm. Note that we can specify a negative number on the /N parm, which will return a date which is the number of months BEFORE the date on the /A parm.

In the last example, we find the date one year after February 29, 2004, which is a leap year. Note that Fdate does NOT return February 29, 2005, which is a non-existent date.

.CODE........:
@ECHO OFF
echo.

set months=1
FDATE /Fm /At  /N%months%    /p"set date2=" > junk.bat
call junk.bat
del junk.bat
Echo %months% month(s) from today is %date2%

:: Show month arithmetic
set months=-1
FDATE /Fm /At  /N%months%    /p"set date2=" > junk.bat
call junk.bat
del junk.bat
Echo %months% month(s) from today is %date2%

echo.
set months=3
FDATE /Fm /At  /N%months%    /p"set date2=" > junk.bat
call junk.bat
del junk.bat
Echo %months% month(s) from today is %date2%

set months=12
FDATE /Fm /At  /N%months%    /p"set date2=" > junk.bat
call junk.bat
del junk.bat
Echo One year from today is %date2%


echo.
set date1=2004-02-29
set months=12
FDATE /Fm /A%date1% /Iccyy-mm-dd /N%months%    /p"set date2=" > junk.bat
call junk.bat
del junk.bat
Echo %months% month(s) from %date1% is %date2%

::cleanup
SET DATE1=
SET DATE2=


Entry number 88                    Table of Contents

.EXAMPLE.....: 33 MIN_MATH.BAT -- "time arithmetic" in minutes
.CATEGORY....: examples
.DISCUSSION..:
MIN_MATH.BAT -- Add or subtract time, in minutes, from the present

We get number of minutes from parm1, if present. otherwise, we use a default of 4 minutes.

Note that Minutes can contain a negative number, if we wish to subtract some minutes

.CODE........:
@echo off
cls
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


Entry number 89                    Table of Contents

.EXAMPLE.....: 34 TIME_SET.BAT -- "time arithmetic" -- set TIME
.CATEGORY....: examples
.DISCUSSION..:
Advance the time by 3 hours, then set it back again

.CODE........:
@echo off
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


Entry number 90                    Table of Contents

.EXAMPLE.....: 42 Get date to tell PKZIP to compress files older than 30 days
.CATEGORY....: examples
.DISCUSSION..:
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.)

The example code compress all files that were created before a date 30 days ago. For more information, see PKZIP's MANUAL.DOC file.

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


Entry number 91                    Table of Contents

.EXAMPLE.....: 43 Loop through an array of environment variables
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
@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
:: 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


Entry number 92                    Table of Contents

.EXAMPLE.....: 44 Do something on the last day (or last Friday) of the month
.CATEGORY....: examples
.DISCUSSION..:
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.

.CODE........:
@echo off
:: ---------------------------------------------------------------
:: check to see if today is the last day of the month
:: ---------------------------------------------------------------
:: get today's month
Fdate /Ff        /omm /vmmtoday

:: get tomorrow's month
Fdate /fadd /n1 /omm  /vmmtomorrow

:: if tomorrow occurs in a different month,
:: 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

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

:: today is Friday.   Get next Monday's month
Fdate /fadd /n3 /omm  /vmmMonday

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

:EndCheck

:: cleanup
set dow3=
set mmtoday=
set mmtomorrow=
set mmMonday=


Entry number 93                    Table of Contents

.EXAMPLE.....: 45 Get information about the month prior to the current month
.CATEGORY....: examples
.DISCUSSION..:
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.

.CODE........:
@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 : "


Entry number 94                    Table of Contents

.EXAMPLE.....: 46 Show the last Monday (or any other weekday) in this month
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
@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%


Entry number 95                    Table of Contents

.EXAMPLE.....: 47 Show the last Monday in the month, for a series of months
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
@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=


Entry number 96                    Table of Contents

.EXAMPLE.....: 50 Represent a date in 3 bytes of "extended hex" notation
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
:: produce today's date as 3 bytes
Fdate /Ff /oxxx

:: produce yesterday's date in xxx format
Fdate /Fsub /N1 /oxxx


Entry number 97                    Table of Contents

.EXAMPLE.....: 51 Represent a date in a short (4-byte) format (technique #1)
.CATEGORY....: examples
.DISCUSSION..:
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.

In the year 2003 you can switch to using January 1, 2000 as your base date and function quite nicely for the next 20 years after that.

.CODE........:

Entry number 98                    Table of Contents

.EXAMPLE.....: 52 Represent a date in a short (4-byte) format (technique #2)
.CATEGORY....: examples
.DISCUSSION..:
This batch file shows how to use Fdate's #2XX function to obtain and represent today's date in 4 characters, YYMD, where:

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

.CODE........:
@echo off
cls

:: 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%

:: 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%

:: 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%

:: CLEANUP
set mm=
set dd=
set date=

:endit


Entry number 99                    Table of Contents

.EXAMPLE.....: 53 Convert numbers to "extended hex" (XX) format
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
@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


Entry number 100                    Table of Contents

.EXAMPLE.....: 54 Customize Fdate for a language of your choice
.CATEGORY....: examples
.DISCUSSION..:
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.

.CODE........:
@echo off
cls

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%

:: cleanup
set Fdate=
set result=


Entry number 101                    Table of Contents

.EXAMPLE.....: 55 Fergian.BAT (used in the previous example)
.CATEGORY....: examples
.DISCUSSION..:
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:

.CODE........:
@echo off
set  %2=
goto %1



: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


Entry number 102                    Table of Contents

.EXAMPLE.....: 61 DO-ONCE: Run apps when booting for the first time of the day
.CATEGORY....: examples
.DISCUSSION..:
Put this code in AUTOEXEC.BAT.

.CODE........:
if not exist C:\LASTRUN.BAT goto RunNow

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

:: compare the date in %LASTRUN% to today's date
:: ------------------------------------------------------------------
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=


Entry number 103                    Table of Contents

.EXAMPLE.....: 62 Run specific software, depending on the day of the week
.CATEGORY....: examples
.DISCUSSION..:
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:

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.

.CODE........:
:: 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=


Entry number 104                    Table of Contents

.EXAMPLE.....: 63 Run a program at a specified time later in the day
.CATEGORY....: examples
.DISCUSSION..:
This batch file can be used to run a program at a specified time during the day.

In general, this is probably not a good use of Fdate, because this batch file involves a lot of disk activity, which occurs 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. This was quite a common solution in the days of DOS, but has pretty much fallen by the wayside now. For this reason, you're probably better off using a proper task-scheduler program, some of which are available free on the Web.

But if all else fails, it is indeed possible to use Fdate to do this.

This first batch file uses Fdate's /V feature to put the result into an environment variable. (If you are running in an environment where /V doesn't work, see below.) Note that I have included a display of second#, so you could see that the batch file is looping properly -- you can see the seconds ticking by! You'll want to remove this if you decide to use the batch file from some real use.

.CODE........:
@echo off
:: GET CURRENT ABSOLUTE MINUTE AND PUT IN ENVIRONMENT VARIABLE RUNTIME
FDATE /Ff /At /Ominute#  /vRUNTIME


:: ADD 120 MINUTES (2 HOURS) TO ENVIRONMENT VARIABLE RUNTIME
FDATE /F#add /A%RunTime% /B120  /vRUNTIME


:: LOOP UNTIL NOWTIME HAS REACHED RUNTIME
:LoopTop
  FDATE /Ff /At  /Ominute#   /vNOWTIME
  Fdate /Ff /Osecond#
  FDATE /F#comp  /A%NowTime% /B%RunTime% /vTIMECOMP
  if (%TimeComp%)==(LT) goto LoopTop
:LoopEnd

echo STARTING EXECUTION OF APPLICATION: [program name]

.DISCUSSION..:
If you are running on a system that doesn't support the /V parm, you can use the following code.

The problem with this technique is that it is constantly writing a new copy of TEMP.BAT to your hard disk. A lot of wear and tear on your hard disk. Back in the days when DOSausaurs ruled the earth, and people routinely used virtual disks, that wasn't a problem. But nowadays (September, 2001) I wouldn't use it except as a last resort.

.CODE........:
@echo off
::  GET CURRENT ABSOLUTE MINUTE AND PUT IN ENVIRONMENT VARIABLE RUNTIME
FDATE /Ff /At /Ominute#  /p"set RUNTIME=" > temp.bat
call temp.bat

::  ADD 120 MINUTES (2 HOURS) TO ENVIRONMENT VARIABLE RUNTIME
FDATE /F#add /A%RunTime% /B120  /p"set RUNTIME=" > temp.bat
call temp.bat

::  LOOP UNTIL NOWTIME HAS REACHED RUNTIME
:LoopTop
  FDATE /Ff /At  /Ominute#   /p"set NOWTIME=" > temp.bat
  call temp.bat

  FDATE /F#comp  /A%NowTime% /B%RunTime% /p"set TIMECOMP=" > temp.bat
  call temp.bat
  if (%TimeComp%)==(LT) goto LoopTop
:LoopEnd

:: cleanup
del temp.bat

echo STARTING EXECUTION OF APPLICATION: [program name]


Entry number 105                    Table of Contents

.EXAMPLE.....: 71 Extract the rightmost n characters of a string
.CATEGORY....: examples
.DISCUSSION..:
extract the rightmost 6 characters of a string

.CODE........:
 FDATE /Fsubstr /a-6     /Q"1994 Jun 03"   ===> "Jun 03"


Entry number 106                    Table of Contents

.EXAMPLE.....: 72 Left-pad a number with zeroes, or a string with spaces
.CATEGORY....: examples
.DISCUSSION..:
Pad a number (stored in environment variable) STRING to the left with zeroes, to make sure it is 4 bytes long

.CODE........:
set STRING=1
Fdate /FE  /Q%STRING% /Jr04  /Vstring
echo STRING is [%string%]

.DISCUSSION..:
Here's another example -- we pad a string (stored in environment variable) STRING to the left with spaces, to make sure it is 4 bytes long

.CODE........:
set STRING=aa
Fdate /Fe  /Q%STRING% /J"r 4"  /Vstring
echo STRING is [%string%]


Entry number 107                    Table of Contents

.EXAMPLE.....: 80 --- SECTION: CHECKING/MANIPULATING A FILE'S DATE/TIMESTAMP
.CATEGORY....: examples
.DISCUSSION..:
I've collected together the examples that involve checking or change a file's date/timestamp. Read on...


Entry number 108                    Table of Contents

.EXAMPLE.....: 81 Rename a file name to a name that contains today's date
.CATEGORY....: examples
.DISCUSSION..:
A very common need is to change a file's name to a name that contains today's date. This is something that you might want to do if you are a system administrator, for example, and every night you run a backup utility that produces a log file called something like BACKUP.LOG. To keep a historical collection of these files, each night, you need to rename BACKUP.LOG to <TodaysDate>.LOG.

This is how to do it.

If you need to do this with a granularity down to the minute, see EXAMPLE 82 Rename a file to a name that contains today's time


If you need to store a date in a filename, but are really limited in the number of bytes available, see EXAMPLE 83 Rename a file to a name that contains today's date in only 3 bytes


.CODE........:
:: 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=


Entry number 109                    Table of Contents

.EXAMPLE.....: 82 Rename a file to a name that contains today's time
.CATEGORY....: examples
.DISCUSSION..:
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.

If don't need to do this with a granularity down to the minute, if a granularity of just a date will do the job, see EXAMPLE 81 Rename a file name to a name that contains today's date


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


Entry number 110                    Table of Contents

.EXAMPLE.....: 83 Rename a file to a name that contains today's date in only 3 bytes
.CATEGORY....: examples
.DISCUSSION..:
It is possible to store information about a date in only 3 bytes, using "extended hex" format.

If you need to store a date in a filename, but are really limited in the number of bytes available, here is how to do it.

For more information about the extended hex output format ("/Oxxx"), see PARAMETER /Oxxx - Extended Hex Output Date Format


.CODE........:
:: get today's date in extended hex format
FDATE /Ff /Oxxx /p"SET XXX=">junk.bat
call junk.bat
del  junk.bat

:: rename a file, using the xxx date
ren  BACKUP.LOG  %XXX%-BACK.LOG

:: cleanup
SET  XXX=


Entry number 111                    Table of Contents

.EXAMPLE.....: 85 Compare a file's date to today's date
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
:: 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=


Entry number 112                    Table of Contents

.EXAMPLE.....: 86 Compare two files' date/time using COMPARE-FUNCTION ERRORLEVELS
.CATEGORY....: examples
.DISCUSSION..:
There are many ways to check errorlevels. This example shows several of them.

.CODE........:
@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


Entry number 113                    Table of Contents

.EXAMPLE.....: 87 Take action if a file has not been updated recently
.CATEGORY....: examples
.DISCUSSION..:
Steve Komosa, IT Operations Manager at the National Gallery in London, needed to check the timestamp on a particular logfile. The logfile SHOULD be updated every 10 minutes. If for some reason the file had not been updated in the last hour, he wanted to kick off a program that would send a message to his pager. Here's how we did it.

.CODE........:
@ECHO OFF

:: We set the name of the file whose date we want to check.
:: Here, for demo purposes, we check on AUTOEXEC.BAT
SET F=C:\AUTOEXEC.BAT

:: get date/time stamp, in seconds, from the file
FDATE /FF /Osecond# /If /A%f% /P"set ftime=" > junk.bat
call junk.bat

:: get date/time, in seconds, of the current time
FDATE /FF /Osecond# /P"set ctime=" > junk.bat
call junk.bat

:: get the difference
Fdate /f#dif /a%ctime% /b%ftime% /P"set tdiff=">junk.bat
call junk.bat

:: see if the difference is greater than 3600 seconds (1 hour)
Fdate /F#comp /a%tdiff% /b3600  >nul

:: if difference is greater than 3600 seconds, we have a problem
if errorlevel 103 goto bad_time
:: else..
goto ok_time


:bad_time
:: PUT YOUR PROBLEM-HANDLING CODE HERE
:: For demo purposes, we just display a message and pause.
:: Steve would have put code here to send a message to his pager
echo File %F% has not been updated on time
echo Time difference is %tdiff% seconds
pause
goto endit


:ok_time
:: For demo purposes, we display a message and pause.
:: In an actual batch file, you'd probably do nothing at all.
echo Time difference is %tdiff% seconds
echo No problem!
pause
:: ... and fall through to the ":endit" label

:endit
:: cleanup
set ctime=
set ftime=
set tdiff=
set f=
del  junk.bat


Entry number 114                    Table of Contents

.EXAMPLE.....: 88 Display a list of all files that were created/updated today.
.CATEGORY....: examples
.DISCUSSION..:
.CODE........:
@echo off
if (%1)==(SUBROUTINE) goto %2

CLS
echo FILES MEETING FILESPEC [%1] THAT WERE CREATED OR UPDATED TODAY
::   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

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

:: echo the filename if the file was created/updated today
if (%comp%)==(EQ) echo %1

:endit


Entry number 115                    Table of Contents

.EXAMPLE.....: 89 Delete files more than X days old (use a batch-file subroutine)
.CATEGORY....: examples
.DISCUSSION..:

Some background

I present two versions of this batch file. The older version is for use with DOS, the newer version for use with Win9X, Win2000, ME, NT, etc. The difference in the batch files is due to the fact that the newer versions of Windows (1) support long filenames, which FDATE does not, and (2) don't allow Fdate to use its /V feature to set environment variables

Introduction

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
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
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
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
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.

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.

.CODE........:
@echo off
:: A newer version, for use with Windows 9X, Win2000, NT, etc.
::
if (%1)==(SUBROUTINE) goto %2
cls

:: 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 ------------------------------------------------------------------
:: Note the use of ~s in the variable reference.
:: This causes the use of the short (8.3) filename, since Fdate cannot
:: handle long filenames.

for %%I in (*.*) do  CALL %0 SUBROUTINE PROCESS! %%~sI
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 /p"set DaysOld=" >temp.bat
call temp.bat

:: compare DaysOld to NumDays
Fdate /F#comp /A%DaysOld% /B%NumDays%  /p" set comparison=">temp.bat
call temp.bat

:: 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%
:: -----------------------------------------------
:: 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%
:: -----------------------------------------------
:: if (%comparison%)==(GT) DEL %1

:: fall through to endit
:endit

.CODE........:
@echo off
:: An older version, for use with DOS
::
if (%1)==(SUBROUTINE) goto %2
cls

:: 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%
:: -----------------------------------------------
:: 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%
:: -----------------------------------------------
:: if (%comparison%)==(GT) DEL %1

:: fall through to endit
:endit