China DOS Union

-- Unite DOS · Advance DOS · Grow DOS --

Union site: www.cn-dos.net Forum site: www.cn-dos.net/forum
DOS stands for freedom, openness and progress. Let us work hard, learn from the openness and GNU spirit of FreeDOS and Linux, and together build and grow a free GNU GPL world!

中国DOS联盟论坛
The time now is 2026-06-23 16:19
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » Batch version perpetual calendar DigestI View 16,200 Replies 44
Floor 16 Posted 2007-06-03 11:16 ·  中国 山东 济南 移动
钻石会员
★★★★★
Credits 10,046
Posts 3,039
Joined 2002-11-11 00:00
23-year member
UID 223
Gender Male
Status Offline
Originally posted by qzwqzw at 2007-5-27 06:14 PM:
For the lunar calendar, maybe there is a way that doesn't require table lookup

My father told me that back in his hometown there was a fool

Normally he was crazy and muddle-headed

But he alone had mastered a "divine skill" that people really admired

Namely, he ...


The only way is to teach the "fool" from your hometown to learn batch files. Hehe.
简单就是美
Floor 17 Posted 2007-06-03 13:32 ·  中国 广东 电信
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
  Posting a version that's a bit more convenient to use. I removed the extra blank lines in the calendar, and fixed the error in the code on the 15th floor where querying July 2007 showed only 30 days. This error was caused by the 1st of that month happening to be Sunday, while 37 loops could only scan up to the 30th. For more changes, see the code comments.

@echo off
:: Algorithm: Kim Larsen calculation formula
:: W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) mod 7
:: Treat January and February as the 13th and 14th months of the previous year
:: Example: if it is 2004-1-10 then convert it to: 2003-13-10 and substitute it into the formula.

:: The input date format is: year-month-day (- can be replaced with : or /, and they can be mixed)
:: In the calendar, ★=today

:: Supports multiple date input formats:
:: ① If only one number is entered, it is treated as querying the month of the current year; the last two digits are automatically taken for the query, and ★ is marked on the 1st;
:: ② If two numbers are entered, it is treated as querying the year and month, and ★ is marked on the 1st;
:: ③ If the full date is entered, ★ is marked on the specified date

:: About year conversion:
:: ① If a two-digit year is entered, it is converted as follows:
:: 50~99 is judged as 19xx
:: 00~49 is judged as 20xx
:: ② If the year entered is not two digits, then after removing all leading 0s,
:: calculate the date of that year;

color 27
mode con cols=40 lines=20
setlocal enabledelayedexpansion
set str=SunMonTueWedThuFriSat
set sdate=%date%

:Main
cls&echo.
:: Date extraction, formatting, and validation
for /f "tokens=1,2,3 delims=-/: " %%i in ("%sdate%") do (
(set sy=%%i) && (set sm=%%j) && (set sd=%%k)
)
if not defined sd set sd=1
if not defined sm set sm=%sy%& set sy=%date:~0,4%
(set sm=10%sm%) && (set sd=10%sd%)
(set sm=%sm:~-2%) && (set sd=%sd:~-2%)
set y=%sy%
set /a m=1%sm%-100, d=1%sd%-100
if not "%sy:~2%"=="" goto check
if "%sy:~1%"=="" goto check
set sy=00%sy%
set sy=%sy:~-2%
set /a y=1%sy%-100
if %y% lss 50 (set /a y+=2000) else (set /a y+=1900)
set sy=%y%
:check
for %%i in (%y% %m% %d%) do (
if %%i equ 0 echo.Invalid date.&pause>nul&set sdate=%date%&goto Main
)
for /f "delims=0 tokens=*" %%i in ("%sy%") do set /a sy=%%i,y=%%i
if %m% geq 13 (echo.Invalid date.&pause>nul&set sdate=%date%&goto Main)
if %d% geq 32 (echo.Invalid date.&pause>nul&set sdate=%date%&goto Main)

:: Calculate the number of days in each month
set days=31
for %%i in (4 6 9 11) do if %m% equ %%i set days=30
:: Calculate February adjustment
set /a leap="^!(y%%4) & ^!(^!(y%%100)) | ^!(y%%400)"
if %m% equ 2 set /a days=28+%leap%
if %m% leq 2 (set /a y-=1& set /a m+=12)
:: Calculate the weekday of the specified date
set /a w=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%%7
::set /a w=(%d%+2*%m%+3*(%m%+1)/5+%y%+%y%/4-%y%/100+%y%/400+1)%%7

set prmt=that day
if "%sy%-%sm%-%sd%"=="%date%" set prmt=Today
echo. %sy%-%sm% %prmt%:%sy%-%sm%-%sd%,week !str:~%w%,1!
echo.

:: Generate the date sequence
set /a wb=(w+35-d) %% 7, we=wb+days+1, day=1
echo. Sun Mon Tue Wed Thu Fri Sat
echo. ━━━━━━━━━━━━━━━━━━━
set /p= <nul
if %wb% equ 6 (set begin=7) else set begin=0
for /l %%i in (%begin%,1,37) do (
set "temp= "
if %%i GTR %wb% if %%i LSS %we% (
set temp= !day!
set temp=!temp:~-2!
if !d! EQU !day! set temp=★
set /a day+=1
)
set /p= !temp!<nul
if !day! gtr !days! goto end
set /a "wm=(%%i+1)%%7"
if !wm! equ 0 echo.&echo.&set /p= <nul
)
:end
echo.
echo ━━━━━━━━━━━━━━━━━━━
echo. Enter a date to view that month's calendar and the weekday of that day
echo.
set sdate=
set /p sdate= Format like: 07-02-03, Exit:
if defined sdate goto Main


[ Last edited by namejm on 2007-6-3 at 02:50 PM ]
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 18 Posted 2007-06-03 14:25 ·  中国 山西 运城 联通
银牌会员
★★★
天的白色影子
Credits 2,343
Posts 636
Joined 2004-03-06 00:00
22-year member
UID 19350
Gender Male
Status Offline
I noticed the July 2007 problem

but by then I didn't have time to change it anymore
----------------------------------

Removing blank lines will make the prompt information and the date input position change frequently

That does not have a positive effect on the layout

So I didn't consider it
----------------------------------
The changes in the date formatting and validation part are rather messy

If you input 7-6-3 you get 7-06-03 (the year is not formatted)

If you input 0 you get 2007-00-01 (the month is not validated)

The original default values for month and day were October / 10th

just because that was simpler to implement
----------------------------------
As for displaying "that day" / "today"

I now feel it doesn't mean much

especially when compared with %date% that already includes the weekday

[ Last edited by qzwqzw on 2007-6-3 at 02:33 PM ]
Floor 19 Posted 2007-06-03 14:57 ·  中国 广东 电信
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
Originally posted by qzwqzw at 2007-6-3 14:25:
If you input 7-6-3 you get 7-06-03 (the year is not formatted)

  I want to make this code into a perpetual calendar, and 7 means AD 7, so it can't be formatted.
If you input 0 you get 2007-00-01 (the month is not validated)

  The code on the 17th floor already added detection for dates and months being 0.
As for displaying "that day" / "today"
I now feel it doesn't mean much
especially when compared with %date% that already includes the weekday

  When running into a %date% format that includes the weekday, it really is quite a headache, and the date extraction code is hard to make fully compatible. Also, the date separator can be specified manually, which makes compatibility even harder.
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 20 Posted 2007-06-03 15:36 ·  中国 山西 运城 联通
银牌会员
★★★
天的白色影子
Credits 2,343
Posts 636
Joined 2004-03-06 00:00
22-year member
UID 19350
Gender Male
Status Offline
As I already said, a perpetual calendar doesn't mean much

Who is going to look up the weekday of year 1 AD?

Back then there wasn't even the Gregorian calendar

If you really want to make a professional chronology

then you need to consider BC as well

Who knows whether this formula is still applicable in BC

And your code has already added a 0~55 judgment

That means you are also defaulting 0~55 to +2000
----------------------------------------------------

After simplifying the date formatting and validation code, it is as follows


:: Monthly calendar query tool China DOS Union special edition. Please indicate copyright when reposting
:: Original: zjl5 Updated: namejm, qzwqzw 2007-06-03

:: Algorithm: Kim Larsen calculation formula
:: W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) mod 7
:: Treat January and February as the 13th and 14th months of the previous year
:: Example: if it is 2004-1-10 then convert it to: 2003-13-10 and substitute it into the formula.

:: The input date format is: year-month-day (- can be replaced with : or /, and they can be mixed)
:: In the calendar, ★=today

:: Supports multiple date input formats:
:: ① If only one number is entered, it is treated as querying the month of the current year; the last two digits are automatically taken for the query, and ★ is marked on the 1st;
:: ② If two numbers are entered, it is treated as querying the year and month, and ★ is marked on the 1st;
:: ③ If the full date is entered, ★ is marked on the specified date

:: About year conversion:
:: ① If the year entered has fewer than three digits, it is converted as follows:
:: 50~99 is judged as 19xx
:: 0~49 is judged as 20xx
:: ② If the entered year has more than two digits, then take the last four characters (pad the high end with 0 if needed),
:: and calculate the date of that year according to rule ①;

@echo off
color 3F
mode con cols=40 lines=20
setlocal enabledelayedexpansion
set str=SunMonTueWedThuFriSat
set sdate=%date%

:Main
cls&echo.
:: Date extraction, formatting, and validation
for /f "tokens=1,2,3 delims=-/: " %%i in ("%sdate%") do (
(set sy=%%i) && (set sm=%%j) && (set sd=%%k)
)
if not defined sd set sd=1
if not defined sm set sm=%sy%& set sy=%date:~0,4%

(set sy=0000%sy%) && (set sm=00%sm%) && (set sd=00%sd%)
(set sy=%sy:~-4%) && (set sm=%sm:~-2%) && (set sd=%sd:~-2%)
cd.
set /a y=1%sy%-10000, m=1%sm%-100, d=1%sd%-100 2>nul
if errorlevel 1 goto Error
if %y% lss 100 (
if %y% lss 50 (set /a y+=2000) else (set /a y+=1900)
set sy=!y!
)
if %m% lss 13 if %d% lss 32 goto Calc

:Error
echo.Invalid date.
pause>nul
set sdate=%date%
goto Main

:Calc
:: Calculate the number of days in each month
set days=31
for %%i in (4 6 9 11) do if %m% equ %%i set days=30
:: Calculate February adjustment
set /a leap="^!(y%%4) & ^!(^!(y%%100)) | ^!(y%%400)"
if %m% equ 2 set /a days=28+%leap%
if %m% leq 2 (set /a y-=1& set /a m+=12)
:: Calculate the weekday of the specified date
set /a w=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%%7

echo. %sy%-%sm% Query date:%sy%-%sm%-%sd%,week !str:~%w%,1!
echo.
:: Generate the monthly calendar
set /a wb=(w+35-d) %% 7, we=wb+days+1, day=1
echo. Sun Mon Tue Wed Thu Fri Sat
echo. ━━━━━━━━━━━━━━━━━━━
set /p= <nul
for /l %%i in (0,1,37) do (
set "temp= "
if %%i GTR %wb% if %%i LSS %we% (
set temp= !day!
set temp=!temp:~-2!
if !d! EQU !day! set temp=★
set /a day+=1
)
set /p= !temp!<nul
set /a "wm=(%%i+1)%%7"
if !wm! equ 0 echo.&echo.&set /p= <nul
)
echo.
echo ━━━━━━━━━━━━━━━━━━━
echo. Enter a date to query the weekday and display that month's calendar
echo.
set sdate=
set /p sdate= Format like: 07-02-03, Exit:
if defined sdate goto Main


[ Last edited by qzwqzw on 2007-8-5 at 06:48 PM ]
Floor 21 Posted 2007-06-03 16:10 ·  中国 广东 电信
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
Originally posted by qzwqzw at 2007-6-3 15:36:
As I already said, a perpetual calendar doesn't mean much
Who is going to look up the weekday of year 1 AD?
Back then there wasn't even the Gregorian calendar

  Hehe, a perpetual calendar really doesn't mean much. I'll just treat it as a game to make ^_^.

And your code has already added a 0~55 judgment
That means you are also defaulting 0~55 to +2000

  Actually, in my code I added a judgment for 00~55, not 0~55, so if you want the script to automatically add the 19 or 20 prefix, you need to enter a two-digit year.

  The code on the 20th floor fully takes into account people's reading and query habits, and also formats the date, so it is already very complete. It's just that the explanation about the year conversion part was copied directly from my code, so the described effect does not completely match your code's function. I suggest changing it to this:
:: About year conversion:
:: ① If the year entered has fewer than three digits, it is converted as follows:
:: 50~99 is judged as 19xx
:: 0~49 is judged as 20xx
:: ② If the entered year has more than two digits, then take the last four characters (pad the high end with 0 if needed),
:: and calculate the date of that year according to rule ①;
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 22 Posted 2007-06-03 22:16 ·  中国 江西 南昌 电信
银牌会员
★★★
天的白色影子
Credits 2,343
Posts 636
Joined 2004-03-06 00:00
22-year member
UID 19350
Gender Male
Status Offline
Thanks for pointing it out

Already fixed
Floor 23 Posted 2007-06-16 03:05 ·  中国 广东 广州 番禺区 电信
初级用户
Credits 82
Posts 15
Joined 2007-05-26 20:14
19-year member
UID 89403
Gender Male
Status Offline
Still can't find a way to calculate the lunar calendar, can only calculate the zodiac and the Heavenly Stem/Earthly Branch year.
@echo off&setlocal enabledelayedexpansion
set sx=MonkeyRoosterDogPigRatOxTigerRabbitDragonSnakeHorseGoat
set tg=GengXinRenGuiJiaYiBingDingWuJi
set dz=ShenYouXuHaiZiChouYinMaoChenSiWuWei
set /p year=Please enter lunar year:
set /a sxnum=%year% %% 12
set /a tgnum=%year:~-1%
echo/&echo The zodiac for year %year% is:!sx:~%sxnum%,1! Lunar calendar year !tg:~%tgnum%,1!!dz:~%sxnum%,1!
echo/&echo Press any key to calculate the years from 1800-2500 that are !sx:~%sxnum%,1! years.
pause>nul&set n=1799&echo/
:a
set /a n+=1
set /a ynum=!n! %% 12
set /a tgnum=!n:~-1!
if !n! equ 2500 ECHO -End, press any key to exit.&pause>nul&exit
if !ynum! equ !sxnum! (echo The years that are also !sx:~%sxnum%,1! years include !n! Lunar calendar year !tg:~%tgnum%,1!!dz:~%ynum%,1!&goto :a) else (goto :a)
Floor 24 Posted 2007-08-01 05:00 ·  中国 湖北 武汉 电信
新手上路
Credits 10
Posts 5
Joined 2007-08-01 04:09
18-year member
UID 94410
Gender Male
Status Offline
Such a great atmosphere, you two are really active. I've looked through 3 or 4 posts and you're both in all of them
Floor 25 Posted 2007-08-01 09:17 ·  中国 广东 梅州 电信
中级用户
★★
Credits 262
Posts 129
Joined 2007-07-11 06:50
18-year member
UID 93679
Gender Male
Status Offline
So which one is the most perfect in the end?
Floor 26 Posted 2007-08-01 09:21 ·  中国 广东 梅州 电信
中级用户
★★
Credits 262
Posts 129
Joined 2007-07-11 06:50
18-year member
UID 93679
Gender Male
Status Offline
The one on the 20th floor: if the date input is wrong, it goes into an infinite loop. It's always an error.
Floor 27 Posted 2007-08-01 10:15 ·  中国 山西 运城 联通
银牌会员
★★★
天的白色影子
Credits 2,343
Posts 636
Joined 2004-03-06 00:00
22-year member
UID 19350
Gender Male
Status Offline
Please be more specific
What kind of wrong date did you enter?
Where does it go into an infinite loop?
Floor 28 Posted 2007-08-01 12:33 ·  中国 中电华通
高级用户
★★
Credits 846
Posts 247
Joined 2006-10-27 12:03
19-year member
UID 68504
Gender Male
From 湖南==》广东
Status Offline
Brother namejm and brother qzwqzw are still this enthusiastic, admirable ing
Floor 29 Posted 2007-08-01 18:04 ·  中国 广东 梅州 电信
中级用户
★★
Credits 262
Posts 129
Joined 2007-07-11 06:50
18-year member
UID 93679
Gender Male
Status Offline
Originally posted by qzwqzw at 2007-8-1 10:15 AM:
Please be more specific
What kind of wrong date did you enter?
Where does it go into an infinite loop?

I copied your code into a bat file. No matter what I enter, letters or the format you gave, even 07-02-03 doesn't work. After pressing Enter it says there's an error. At that point, pressing any key won't return to the main menu, causing an infinite loop, and it just stays on the error screen unless you close it.
Floor 30 Posted 2007-08-01 18:36 ·  中国 山西 运城 联通
银牌会员
★★★
天的白色影子
Credits 2,343
Posts 636
Joined 2004-03-06 00:00
22-year member
UID 19350
Gender Male
Status Offline
I can't reproduce your error
If you know some simple batch debugging techniques
you can insert a statement before the error prompt in the code
to check the results of the variable input at that moment

echo [%OS%][%date%][%sDate%][%y%=%m%=%d%]
Forum Jump: