Zero-padded date and time system variables, e.g., _monthzp, _dayzp, _doyzp

Oct 18, 2009
351
17
I routinely create a set of monthly or daily folders in these formats:

< year>
05 - May 2020
06 - Jun 2020
07 - Jul 2020
08 - Aug 2020
09 - Sep 2020
10 - Oct 2020

<daily>
01
02
...
10
11

The _month and _day variables don't zero-pad the numbers, so I wind up having to write something like:

echo %@right[2,0%_month]

It would simplify this to have a set of zero-padded date and time variables equivalent to _month, _day, _dow, _doy, _hour, etc. Plus, adding those should be pretty simple.
 

Charles Dye

Super Moderator
Staff member
May 20, 2008
4,233
78
Albuquerque, NM
prospero.unm.edu
The new @DATEFMT function already has tokens for these. You can wrap 'em up in variables if you like:
Code:
C:\>set _monthzp=`%@datefmt[*,%%m]`

C:\>set _dayzp=`%@datefmt[*,%%d]`

C:\>set _*zp
_dayzp=%@datefmt[*,%%d]
_monthzp=%@datefmt[*,%%m]

C:\>echo %_monthzp :: %_dayzp
06 :: 04

C:\>
 
May 20, 2008
10,675
83
Syracuse, NY, USA
We already have padding functions. And wrapping up @FORMAT can make life easier.

Code:
v:\> echo %@format[02,%_month]
06

v:\> function p2 `%@format[02,%1]`

v:\> echo %@p2[%_month]
06
 
May 20, 2008
10,675
83
Syracuse, NY, USA
The new @DATEFMT function already has tokens for these. You can wrap 'em up in variables if you like:
Code:
C:\>set _monthzp=`%@datefmt[*,%%m]`

C:\>set _dayzp=`%@datefmt[*,%%d]`

C:\>set _*zp
_dayzp=%@datefmt[*,%%d]
_monthzp=%@datefmt[*,%%m]

C:\>echo %_monthzp :: %_dayzp
06 :: 04

C:\>
Yup. And you can build your own strings inside @DATEFMT.

Code:
v:\> echo %@datefmt[*,%%m :: %%d]
06 :: 04
 
May 20, 2008
10,675
83
Syracuse, NY, USA
Code:
Code:
e:\utils>set _month=%@right[2,0%_month]

e:\utils>echo %_month
06

That will set _MONTH to (literally) 06 (it won't be expanded at run time. That's what happens with _SECOND.

Code:
v:\> set _second=%@right[2,0%_second]

v:\> echo %_second & delay 2 & echo %_second
53
53

If you try to patch it up you'll get a variable loop.

Code:
v:\> set _second=`%@right[2,0%_second]`

v:\> echo %_second & delay 2 & echo %_second
TCC: Variable loop

I don't think you can reuse the variable name that way.
 
You are correct @vefatica, but maybe this will work;
Code:
e:\utils>set _month=`%@right[2,0%@month[%_date]]`

e:\utils>set _m*
_month=%@right[2,0%@month[%_date]]

e:\utils>echo %_month
06

In my opinion, it seems better to redefine the Internal Variable, than create a different-named variable.

Maybe a global setting could be added to TCC (maybe via SETDOS) to indicate if zero-padded values are wanted.

Joe
 
May 20, 2008
10,675
83
Syracuse, NY, USA
You are correct @vefatica, but maybe this will work;
Code:
e:\utils>set _month=`%@right[2,0%@month[%_date]]`

e:\utils>set _m*
_month=%@right[2,0%@month[%_date]]

e:\utils>echo %_month
06

In my opinion, it seems better to redefine the Internal Variable, than create a different-named variable.

Maybe a global setting could be added to TCC (maybe via SETDOS) to indicate if zero-padded values are wanted.

Joe
Yup, and that brings us back to @DATEFMT.

Code:
v:\> set _month=`%@datefmt[*,%%m]`

v:\> set _month
%@datefmt[*,%%m]

v:\> echo %_month
06
 
Oct 18, 2009
351
17
The point of the suggestion is to have an easy standard way--not something custom to an individual program or a custom library program, etc. Two-digit hours, minutes, day of month, etc., are routinely used for all sorts of things like timestamps or datestamps.

Realistically, in TCC's source code it should just be a matter of taking the existing variables and running them through a padding function where the number of digits is specified, and then setting the new system variable to the function's output.
 
May 20, 2008
10,675
83
Syracuse, NY, USA
The point of the suggestion is to have an easy standard way--not something custom to an individual program or a custom library program, etc. Two-digit hours, minutes, day of month, etc., are routinely used for all sorts of things like timestamps or datestamps.

Realistically, in TCC's source code it should just be a matter of taking the existing variables and running them through a padding function where the number of digits is specified, and then setting the new system variable to the function's output.
@DATEFMT and @FORMAT seem pretty standard to me. Are they too hard to use?
 
What is the standard, though?

Remembering my COBOL days, I always had to zero pad numbers with something like;
Code:
INSPECT THEPRICE REPLACING LEADING SPACE BY '0'

There was never a built-in method of zero padding numbers in Visual Basic, Visual FoxPro, dBASE, etc.

I agree with @vefatica, in that the standard seems to be to format the number to what you want, not un-format a formatted number.

Joe
 
Oct 18, 2009
351
17
It's not about "zero padding numbers", it's specifically about zero padding system variables for time, day of week, etc., so they always have the same length without needing formatting code for hours, separate formatting code for minutes, separate code for day of month, etc. ... And if those variables are used in different subroutines, needing separate formatting code each time.

Realistically, it would just be:
day of week
day of month
day of year
hour
minute
seconds

All of those would be "zero pad to 2 digits" except day of year zero pads to 3 digits.
 
Oct 18, 2009
351
17
Why pad _DOWI? It's always 1 digit. And why not pad _MONTH?
You're right on both of those. I didn't go through the current set, I was just listing those off the top of my head.

Pretty much always, when I'm working with "day of the week" I'm working with the the three-letter version, so my code is: IFF "%var" EQ "Mon" THEN ...


Corrected list:

Realistically, it would just be:
month
day of month
day of year
hour
minute
seconds

All of those would be "zero pad to 2 digits" except day of year zero pads to 3 digits.
 
May 20, 2008
10,675
83
Syracuse, NY, USA
These may be useful ... two ways to accomplish the same thing.
Code:
v:\> function zp `%@format[0%@if["%1"=="_doy",3,2],%[%1]]`

v:\> do t in /L _month _day _hour _minute _second _doy ( echo %t = %@zp[%t] )
_month = 06
_day = 09
_hour = 10
_minute = 41
_second = 02
_doy = 161

v:\> function zp `%@right[%@if["%1"=="_doy",3,2],00%[%1]]`

v:\> do t in /L _month _day _hour _minute _second _doy ( echo %t = %@zp[%t] )
_month = 06
_day = 09
_hour = 11
_minute = 29
_second = 08
_doy = 161

Here's another that saves your typing the '_' on the variable name.
Code:
v:\> function zp `%@right[%@if["%1"=="doy",3,2],00%_%1]`

v:\> do t in /L month day hour minute second doy ( echo _%t = %@zp[%t] )
_month = 06
_day = 09
_hour = 11
_minute = 35
_second = 03
_doy = 161
 
Oct 18, 2009
351
17
Again, you keep missing the point--it's not about "How do I write custom code to zero pad?" It's about having something simple, standard, and built-in so it won't be necessary to write custom code.
 
May 20, 2008
10,675
83
Syracuse, NY, USA
Again, you keep missing the point--it's not about "How do I write custom code to zero pad?" It's about having something simple, standard, and built-in so it won't be necessary to write custom code.
I'm not missing your point; I just don't support your suggestion. In my opinion, it's just not worth it ... six new variables (plus six new help pages and edits to (at least) two others) so you can do a common task for which there are already built-in (and generic) tools that are easy to use.
 
Aug 23, 2010
590
7
Padding dates: use @DATE.
Padding time… ???

I'd like to have a @DATEFORMAT that accepts usual date formatting macroses as first argument and optional date/time string as second.
 
May 20, 2008
10,675
83
Syracuse, NY, USA
I'd like to have a @DATEFORMAT that accepts usual date formatting macroses as first argument and optional date/time string as second.
Have you looked at @DATEFMT? The date is first (* means now) and the format is second.

Code:
v:\> echo %@datefmt[1988-01-11 14:32:45,It's %%A, %%B %%e in the year %%Y; it's %%#M minutes %%#S seconds after %%#I %%p]
It's Monday, January 11 in the year 1988; it's 32 minutes 45 seconds after 2 PM

v:\> echo %@datefmt[*,It's %%A, %%B %%e in the year %%Y; it's %%#M minutes %%#S seconds after %%#I %%p]
It's Thursday, June 11 in the year 2020; it's 55 minutes 10 seconds after 2 PM
 
Oct 18, 2009
351
17
Padding dates: use @DATE.
Padding time… ???

I'd like to have a @DATEFORMAT that accepts usual date formatting macroses as first argument and optional date/time string as second.
I'm not talking about padding a date, I'm talking about padding date parts, i.e., only day of month or only day of year. The examples I gave are for creating folders with names in the format 06 - Jun 2020

In those I have subfolders 01, 02, etc., for the days.

I also have code that has to calculate where to move files to, etc., so that code has to calculate the whole path of both the source folder and the target folder, with multiple zero-padded parts.

(Yes, it would be a whole lot easier to have all this in a database in a database application, so the huge number of folders wouldn't be necessary, but I don't have a say in that.)

It's also for parsing filenames that end with a date in various formats, such as 200601.txt or 060120.txt and then comparing those to the day of the month or the month of the year.

We don't compare to day of year, but if zero-padding _month, etc., is done, that might as well be done too.