Subscribe to Windows IT Pro
September 11, 2006 12:00 AM

Creating Date and Time Stamps

Scripts generate ISO 8601–format dates and times that you can use in filenames
Windows IT Pro
InstantDoc ID #92941
Rating: (8)
Downloads
92941.zip

Administrators occasionally need unambiguous datestamps and timestamps usable in file and folder names, but how to create them isn’t immediately obvious. VBScript’s date-manipulation tools generate dates and times that are formatted according to locale and that usually include characters that you can’t use in filenames.

The ISO 8601 standard is a good choice for a date- and timestamp format—I’ll explain why and then show you how to generate ISO 8601 stamps easily, even on pre–Windows XP systems that don’t provide some convenient stamping tools.

The ISO 8601 Format
If you want to insert a date or time into a log file, you can use almost any format you want. However, you have more restrictions if you want to use a date- or timestamp as a name or part of a name for a file; the ubiquitous forward slash and colon are both reserved characters, and removing them can make a date or time that doesn’t include leading zeroes ambiguous.

The simplest solution I’ve found that generally works is to represent dates and times in the widely adopted ISO 8601 standard’s basic format for displaying calendar dates.

The ISO 8601 standard provides guidance for representing dates and times in an unambiguous form. The basic format is all-numeric; there is also an extended format in which elements are separated with delimiting characters.

A datestamp in the basic format is eight numeric digits in the pattern yyyymmdd, where yyyy is the four-digit year, mm is the two-digit month, and dd is the two-digit day of the month. You must pad any month or day that has only one digit with a leading 0. In this scheme, February 1, 2005 is 20050201.

A timestamp that uses the ISO 8601 basic format is six digits in the form hhmmss, where hh is the two-digit hour of the day in 24-hour format, mm is the two-digit minute, and ss is the two-digit second. Using this format, 9:05 A.M. is 090500; 9:05 P.M. is 210500.

Why this particular format? The most crucial issue is that we settle on some format. We can’t generally use raw numeric dates and expect them to be useful. Suppose we just chop punctuation out of a date string to get a stamp such as 1122005. In the United States, that might refer to either January 12, 2005 or November 2, 2005.

If you’re in a multinational organization, things are even more confusing. Most of the world uses day/month/year ordering; thus, 1122005 could also refer to December 1, 2005 or February 11, 2005. Even with the missing leading 0 in place in this stamp, this format is ambiguous in multinational organizations because 01122005 could still refer to either January 12 or December 1.

The ISO 8601 basic format, in contrast, has a variety of simple advantages that add up:

  • The format is friendly with most file systems. All the characters are allowed in file and folder names and don’t need to be escaped. If you’re using stamps as the complete folder names or file base names, there’s no risk of them being truncated if the files are copied to a volume that supports only 8.3 filenames.
  • The meaning of the format is difficult to misinterpret. This is one of the important features of the ISO 8601 standard. Dates are generally very ambiguous because some regions use month first and others use day first for common display. However, the first four characters of an ISO 8601 date string are always clearly the year portion of a date, and every format that begins with the year uses month/day order following it. Technically oriented people often find the format instinctive because the year/month/day order is similar to the greater-to-lesser order used in numbers.
  • If you sort ISO 8601 date- or timestamps alphabetically, they’re also sorted chronologically. For example, you might use the stamps 20060501 and 20061130 as names for folders. Regardless of when the folders were created or modified last, if you sort the folder names alphabetically, they’ll be ordered by the date reference in the stamp.
  • The individual date and time elements are short enough to be apparent even without punctuation.
  • The format might be familiar even to those who don’t know about ISO 8601. Windows Management Instrumentation (WMI) uses a similar datestamp format that’s based on ISO 8601. The standard is also widely accepted and used informally, even by people who have no clue that it’s a standard.

If we want to use this ISO 8601 format, the next question is: How do we actually generate a stamp that complies with it?

Using WMI
Generating an ISO 8601 date- or timestamp is easy on XP and later Windows versions. WMI’s SWbemDateTime class wraps up a bunch of functionality for easily translating dates and times between what Microsoft calls an OLE DateTime or VarDate—the kind of date and time object that VBScript uses—and other significant forms, including WMI’s own time string format. Bobby Malik previously discussed some aspects of this class in “WMI Time Bewilderment” (September 2002, InstantDoc ID 26030). I’ll show you how to do one simple thing: put in a VBScript date and get back a WMI date/time string.

Listing 1 shows the code for this task. Note that at callout A in Listing 1, the first line of code, which would normally generate a script date and time, is commented out. For testing purposes, the second line of code supplies a VBScript date corresponding to 3:26:58 P.M. on August 18, 2005.

SWbemDateTime doesn’t have a date or time when you set it up; its role is really just that of a translator between different time formats. To initialize it, the code at callout B in Listing 1 passes it the referenceTime value by using the SetVarDate method. Then the code can get the date and time back as a WMI date/time string by reading the value named Value in this class.

On my system, the echo statement in callout B shows this:

20050818152658.000000-300 

On your particular system, the last four characters might be different because they correspond to the number of minutes offset from Coordinated Universal Time (UTC), but everything before that should be identical.

The beauty of using SWbemDateTime is that we get our stamps by just cutting the string contained in Value into pieces. As shown at callout C in Listing 1, we get a datestamp by extracting the first eight characters of the string and a timestamp by extracting the six-character sequence that starts with the ninth character in the string.

Unfortunately, for the substantial portion of working PCs that have a pre-XP OS, this technique won’t work. We can get everything we need by using pure VBScript, though; it just takes a little bit of work.

Related Content:

ARTICLE TOOLS

Comments
  • Alex
    4 years ago
    Jun 11, 2008

    OlliK -
    The approach you show is definitely more compact, but there actually is a case where it could be a problem due to the discrete amount of time it takes for each evaluation of Now().
    If you're generating a date/time stamp right around the time when the year, month, day, hour, or minute is about to increment, you can get a bad value generated. It's going to be very rare of course, but it could be bizarre in the worst possible cases. As an example, suppose the code is running at approximately midnight on 2008 December 31. By evaluating Now() once, you get a specific value that may turn out to be
    20081231 235959
    or, if run milliseconds later,
    20090101 000000
    The first one is just before the beginning of the year, the second is just after the beginning of the year.
    However, with multiple evaluations of Now(), wDate might be evaluated before midnight as 20081231 and wTime right after midnight, giving you
    20081231 000000
    which is 24 hours earlier! It could even happen within a line of code; VBScript evaluates right to left, so if the date changes immediately after the day is evaluated, then you would get
    20091231 000000
    which is almost a year off.
    The code runs _very_ fast on modern machines so I would be very surprised to see this happen, but the mere possibility would qualify as a bug. That's why I use the longer way that evaluates Now() once.

  • Alex
    4 years ago
    Jun 11, 2008

    Jim -
    These look like they work on Vista with default US date/time settings as well. Unfortunately, I found the cmd approach doesn't work very well if the settings are already in an ISO8601 form (although it _should_ be possible to make a batch file that uses reg.exe to check the registry for the current date settings format and base parsing on that).

  • Niels
    4 years ago
    Jun 06, 2008

    The standard gives several formats, and I find the format

    T:: more readable. Unfortunately one has to define the format in the given language.
    But it is defently worth the effort.

  • Oliver
    4 years ago
    Jun 06, 2008

    what about an even easier approach?

    wDate = CStr(Year(Now) * 10000 + Month(Now) * 100 + Day(Now))
    wTime = Right(CStr(1000000 + Hour(Now) * 10000 + Minute(Now) * 100 + Second(Now)), 6)

    to get an ISO date in a batch file just put the mathematical part of the aforementioned expressions (ie without the string functions) in a vbscript file and return the result with WScript.Quit, like

    WScript.Quit(Year(Now) * 10000 + Month(dtNow) * 100 + Day(Now))

    and retrieve the value by using %ErrorLevel%

  • Jim
    4 years ago
    Jun 06, 2008

    Without knowing it had a definition, I've been using ISO 8601 format for some time for just the advantages you listed, in particular that this format is easy to understand and read, and that it sorts very nicely.

    From a CMD file, you can create an ISO 8601 compatible string for the date by using this:

    FOR /F "tokens=2-4 delims=/ " %%f in ("%date%") do set ISO9601Date=%%h%%f%%g

    Note that I'm using two delimiters here, a forward slash AND a space, the space is necessary to lop off the day of the week from the front of the date variable.

    and for time, use

    FOR /F "tokens=1-3 delims=:." %%f in ("%time: =0%") do set ISO9601Time=%%f%%g%%h


    The %time: =0% (after the colon it is 'space equals 0' changes all the blanks in the time variable to 0, taking care of the single digit hour issue

    (These were prepared on Windows XP Pro using English-US regional settings. Your configuration may require this code to be tweaked)

    Jim

You must log on before posting a comment.

Are you a new visitor? Register Here

advertisement

advertisement

Windows is a trademark of the Microsoft group of companies. Windows IT Pro is used by Penton Media Inc. under license from owner.