Làm cách nào để lưu ngày hiện tại ở định dạng YYYY-MM-DD vào một số biến trong tệp .bat Windows?
Tương tự của Unix shell:
today=`date +%F`
echo $today
Làm cách nào để lưu ngày hiện tại ở định dạng YYYY-MM-DD vào một số biến trong tệp .bat Windows?
Tương tự của Unix shell:
today=`date +%F`
echo $today
Câu trả lời:
Bạn có thể lấy ngày hiện tại theo cách bất khả tri ngôn ngữ bằng cách sử dụng
for /f "skip=1" %%x in ('wmic os get localdatetime') do if not defined MyDate set MyDate=%%x
Sau đó, bạn có thể trích xuất các phần riêng lẻ bằng cách sử dụng chuỗi con:
set today=%MyDate:~0,4%-%MyDate:~4,2%-%MyDate:~6,2%
Một cách khác, nơi bạn nhận được các biến chứa các phần riêng lẻ, sẽ là:
for /f %%x in ('wmic path win32_localtime get /format:list ^| findstr "="') do set %%x
set today=%Year%-%Month%-%Day%
Đẹp hơn nhiều so với việc loay hoay với các chuỗi con, với chi phí làm ô nhiễm không gian tên biến của bạn.
Nếu bạn cần UTC thay vì giờ địa phương, lệnh này ít nhiều giống nhau:
for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr "="') do set %%x
set today=%Year%-%Month%-%Day%
for /f
trả về hai dòng, dòng thứ hai là dòng trống. Bạn có thể giải quyết điều đó bằng cách sử dụng set MyDate=
ở giữa. Tôi đoán đó là điều mà người dùng2023861 đã vấp phải.
Year
, Month
, Day
, Hour
, Minute
, Second
, Quarter
, WeekInMonth
,DayOfWeek
for /f %%x in ('wmic path win32_localtime get /format:list ^| findstr "="') do set %%x set today=%Year%-%Month%-%Day%
là câu trả lời không hợp lệ: nó trả về một chữ số tháng và ngày. Làm thế nào để có 2 chữ số bên trái được đệm bằng không chuỗi ngày và tháng?
Nếu bạn muốn đạt được điều này bằng cách sử dụng các lệnh MS-DOS tiêu chuẩn trong một tệp hàng loạt thì bạn có thể sử dụng:
FOR /F "TOKENS=1 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET dd=%%A
FOR /F "TOKENS=1,2 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET mm=%%B
FOR /F "TOKENS=1,2,3 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET yyyy=%%C
Tôi chắc chắn rằng điều này có thể được cải thiện hơn nữa nhưng điều này cho ngày thành 3 biến cho Ngày (dd), Tháng (mm) và Năm (yyyy). Sau đó, bạn có thể sử dụng chúng sau này trong tập lệnh lô của mình theo yêu cầu.
SET todaysdate=%yyyy%%mm%%dd%
echo %dd%
echo %mm%
echo %yyyy%
echo %todaysdate%
Mặc dù tôi hiểu rằng một câu trả lời đã được chấp nhận cho câu hỏi này, phương pháp thay thế này có thể được đánh giá cao bởi nhiều người đang tìm cách đạt được điều này mà không sử dụng bảng điều khiển WMI, vì vậy tôi hy vọng nó bổ sung một số giá trị cho câu hỏi này.
Sử dụng date /T
để tìm định dạng trên dấu nhắc lệnh.
Nếu định dạng ngày được Thu 17/03/2016
sử dụng như thế này:
set datestr=%date:~10,4%-%date:~7,2%-%date:~4,2%
echo %datestr%
SELECT CONVERT(VARCHAR(16), GETDATE(), 112)
".
%date:~10,4%%date:~7,2%%date:~4,2%T%time:~0,2%%time:~3,2%%time:~6,2%
Hai cách nữa mà không phụ thuộc vào cài đặt thời gian (cả hai đều lấy từ Cách lấy dữ liệu / thời gian độc lập với bản địa hóa ). Và cả hai cũng nhận được ngày trong tuần và không ai trong số họ yêu cầu quyền quản trị viên !:
MAKECAB - sẽ hoạt động trên MỌI hệ thống Windows (nhanh nhưng tạo một tệp tạm thời nhỏ) (tập lệnh foxidrive):
@echo off
pushd "%temp%"
makecab /D RptFileName=~.rpt /D InfFileName=~.inf /f nul >nul
for /f "tokens=3-7" %%a in ('find /i "makecab"^<~.rpt') do (
set "current-date=%%e-%%b-%%c"
set "current-time=%%d"
set "weekday=%%a"
)
del ~.*
popd
echo %weekday% %current-date% %current-time%
pause
ROBOCOPY - đây không phải là lệnh gốc dành cho Windows XP và Windows Server 2003 , nhưng nó có thể được tải xuống từ trang của Microsoft . Nhưng nó được tích hợp sẵn trong mọi thứ từ Windows Vista trở lên:
@echo off
setlocal
for /f "skip=8 tokens=2,3,4,5,6,7,8 delims=: " %%D in ('robocopy /l * \ \ /ns /nc /ndl /nfl /np /njh /XF * /XD *') do (
set "dow=%%D"
set "month=%%E"
set "day=%%F"
set "HH=%%G"
set "MM=%%H"
set "SS=%%I"
set "year=%%J"
)
echo Day of the week: %dow%
echo Day of the month : %day%
echo Month : %month%
echo hour : %HH%
echo minutes : %MM%
echo seconds : %SS%
echo year : %year%
endlocal
Và ba cách khác sử dụng các ngôn ngữ script Windows khác. Chúng sẽ mang lại cho bạn sự linh hoạt hơn, ví dụ như bạn có thể nhận được tuần trong năm, thời gian tính bằng mili giây, v.v.
JScript / BATCH hybrid (cần được lưu dưới dạng .bat
). JScript có sẵn trên mọi hệ thống từ Windows NT trở lên, như một phần của Windows Script Host ( mặc dù có thể bị vô hiệu hóa thông qua sổ đăng ký, đây là một trường hợp hiếm ):
@if (@X)==(@Y) @end /* ---Harmless hybrid line that begins a JScript comment
@echo off
cscript //E:JScript //nologo "%~f0"
exit /b 0
*------------------------------------------------------------------------------*/
function GetCurrentDate() {
// Today date time which will used to set as default date.
var todayDate = new Date();
todayDate = todayDate.getFullYear() + "-" +
("0" + (todayDate.getMonth() + 1)).slice(-2) + "-" +
("0" + todayDate.getDate()).slice(-2) + " " + ("0" + todayDate.getHours()).slice(-2) + ":" +
("0" + todayDate.getMinutes()).slice(-2);
return todayDate;
}
WScript.Echo(GetCurrentDate());
Kết hợp VBScript / BATCH ( Có thể nhúng và thực thi VBScript trong một tệp loạt mà không sử dụng tệp tạm thời không? ) Trường hợp tương tự như jscript, nhưng kết hợp không quá hoàn hảo:
:sub echo(str) :end sub
echo off
'>nul 2>&1|| copy /Y %windir%\System32\doskey.exe %windir%\System32\'.exe >nul
'& echo current date:
'& cscript /nologo /E:vbscript "%~f0"
'& exit /b
'0 = vbGeneralDate - Default. Returns date: mm/dd/yy and time if specified: hh:mm:ss PM/AM.
'1 = vbLongDate - Returns date: weekday, monthname, year
'2 = vbShortDate - Returns date: mm/dd/yy
'3 = vbLongTime - Returns time: hh:mm:ss PM/AM
'4 = vbShortTime - Return time: hh:mm
WScript.echo Replace(FormatDateTime(Date, 1), ", ", "-")
PowerShell - có thể được cài đặt trên mọi máy có .NET - tải xuống từ Microsoft ( v1 , v2 và v3 (chỉ dành cho Windows 7 trở lên)). Được cài đặt theo mặc định trên mọi dạng Windows 7 / Win2008 trở lên:
C:\> powershell get-date -format "{dd-MMM-yyyy HH:mm}"
Jscript.net/batch tự biên dịch (Tôi chưa bao giờ thấy một máy Windows nào không có .NET nên tôi nghĩ đây là một máy khá di động):
@if (@X)==(@Y) @end /****** silent line that start jscript comment ******
@echo off
::::::::::::::::::::::::::::::::::::
::: Compile the script ::::
::::::::::::::::::::::::::::::::::::
setlocal
if exist "%~n0.exe" goto :skip_compilation
set "frm=%SystemRoot%\Microsoft.NET\Framework\"
:: searching the latest installed .net framework
for /f "tokens=* delims=" %%v in ('dir /b /s /a:d /o:-n "%SystemRoot%\Microsoft.NET\Framework\v*"') do (
if exist "%%v\jsc.exe" (
rem :: the javascript.net compiler
set "jsc=%%~dpsnfxv\jsc.exe"
goto :break_loop
)
)
echo jsc.exe not found && exit /b 0
:break_loop
call %jsc% /nologo /out:"%~n0.exe" "%~dpsfnx0"
::::::::::::::::::::::::::::::::::::
::: End of compilation ::::
::::::::::::::::::::::::::::::::::::
:skip_compilation
"%~n0.exe"
exit /b 0
****** End of JScript comment ******/
import System;
import System.IO;
var dt=DateTime.Now;
Console.WriteLine(dt.ToString("yyyy-MM-dd hh:mm:ss"));
Logman Điều này không thể lấy năm và ngày trong tuần. Nó tương đối chậm, cũng tạo ra một tệp tạm thời và dựa trên các dấu thời gian mà logman đặt trên tệp nhật ký của nó. Sẽ hoạt động mọi thứ từ Windows XP trở lên. Nó có thể sẽ không bao giờ được sử dụng bởi bất kỳ ai - kể cả tôi - nhưng nó là một cách nữa ...
@echo off
setlocal
del /q /f %temp%\timestampfile_*
Logman.exe stop ts-CPU 1>nul 2>&1
Logman.exe delete ts-CPU 1>nul 2>&1
Logman.exe create counter ts-CPU -sc 2 -v mmddhhmm -max 250 -c "\Processor(_Total)\%% Processor Time" -o %temp%\timestampfile_ >nul
Logman.exe start ts-CPU 1>nul 2>&1
Logman.exe stop ts-CPU >nul 2>&1
Logman.exe delete ts-CPU >nul 2>&1
for /f "tokens=2 delims=_." %%t in ('dir /b %temp%\timestampfile_*^&del /q/f %temp%\timestampfile_*') do set timestamp=%%t
echo %timestamp%
echo MM: %timestamp:~0,2%
echo dd: %timestamp:~2,2%
echo hh: %timestamp:~4,2%
echo mm: %timestamp:~6,2%
endlocal
exit /b 0
Thông tin thêm về chức năng Get-Date .
Tôi thực sự thích phương pháp của Joey, nhưng tôi nghĩ rằng tôi sẽ mở rộng nó một chút.
Trong cách tiếp cận này, bạn có thể chạy mã nhiều lần và không phải lo lắng về việc giá trị ngày cũ "dính xung quanh" vì nó đã được xác định.
Mỗi lần bạn chạy tệp loạt này, nó sẽ xuất ra biểu diễn ngày và giờ kết hợp tương thích ISO 8601.
FOR /F "skip=1" %%D IN ('WMIC OS GET LocalDateTime') DO (SET LIDATE=%%D & GOTO :GOT_LIDATE)
:GOT_LIDATE
SET DATETIME=%LIDATE:~0,4%-%LIDATE:~4,2%-%LIDATE:~6,2%T%LIDATE:~8,2%:%LIDATE:~10,2%:%LIDATE:~12,2%
ECHO %DATETIME%
Trong phiên bản này, bạn sẽ phải cẩn thận không sao chép / dán cùng một mã vào nhiều vị trí trong tệp vì điều đó sẽ gây ra các nhãn trùng lặp. Bạn có thể có một nhãn riêng cho mỗi bản sao hoặc chỉ cần đặt mã này vào tệp lô của riêng nó và gọi nó từ tệp nguồn của bạn bất cứ khi nào cần thiết.
Theo câu trả lời của @ProVi chỉ cần thay đổi để phù hợp với định dạng bạn yêu cầu
echo %DATE:~10,4%-%DATE:~7,2%-%DATE:~4,2% %TIME:~0,2%:%TIME:~3,2%:%TIME:~6,2%
sẽ trở lại
yyyy-MM-dd hh:mm:ss
2015-09-15 18:36:11
CHỈNH SỬA Theo nhận xét của @Jeb, định dạng thời gian ở trên sẽ chỉ hoạt động nếu lệnh DATE / T của bạn trả về
ddd dd/mm/yyyy
Thu 17/09/2015
Tuy nhiên, có thể dễ dàng chỉnh sửa cho phù hợp với ngôn ngữ của bạn, bằng cách sử dụng lập chỉ mục của từng ký tự trong chuỗi được trả về bởi biến môi trường% DATE% có liên quan, bạn có thể trích xuất các phần của chuỗi mà bạn cần.
ví dụ. Sử dụng% DATE ~ 10,4% sẽ mở rộng biến môi trường DATE, sau đó chỉ sử dụng 4 ký tự bắt đầu ở ký tự thứ 11 (bù 10) của kết quả được mở rộng
Ví dụ: nếu sử dụng ngày tháng theo kiểu Hoa Kỳ thì điều sau sẽ áp dụng
ddd mm/dd/yyyy
Thu 09/17/2015
echo %DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2% %TIME:~0,2%:%TIME:~3,2%:%TIME:~6,2%
2015-09-17 18:36:11
Kiểm tra cái này ..
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%" & set "MS=%dt:~15,3%"
set "datestamp=%YYYY%%MM%%DD%" & set "timestamp=%HH%%Min%%Sec%" & set "fullstamp=%YYYY%-%MM%-%DD%_%HH%-%Min%-%Sec%-%MS%"
echo datestamp: "%datestamp%"
echo timestamp: "%timestamp%"
echo fullstamp: "%fullstamp%"
pause
Nếu bạn đã cài đặt Python, bạn có thể làm
python -c "import datetime;print(datetime.date.today().strftime('%Y-%m-%d'))"
Bạn có thể dễ dàng điều chỉnh chuỗi định dạng theo nhu cầu của mình.
python -c "import datetime;print(datetime.date.today())"
vì __str__
phương thức của date
lớp chỉ gọi isoformat()
.
Có thể sử dụng PowerShell và chuyển hướng đầu ra của nó đến một biến môi trường bằng cách sử dụng vòng lặp.
Từ dòng lệnh ( cmd
):
for /f "tokens=*" %a in ('powershell get-date -format "{yyyy-MM-dd+HH:mm}"') do set td=%a
echo %td%
2016-25-02+17:25
Trong một tệp hàng loạt, bạn có thể thoát %a
dưới dạng %%a
:
for /f "tokens=*" %%a in ('powershell get-date -format "{yyyy-MM-dd+HH:mm}"') do set td=%%a
FOR /F "tokens=*" %%a IN ('powershell get-date -format "{yyyy\-MM\-dd\THH\:mm\:ss}"') DO SET date=%%a
vì vậy hãy sử dụng MM trên cho tháng và dấu gạch chéo ngược để thoát các ký tự theo nghĩa đen.
Do định dạng ngày và giờ là thông tin vị trí cụ thể, việc truy xuất chúng từ các biến% date% và% time% sẽ cần thêm nỗ lực để phân tích cú pháp chuỗi có cân nhắc chuyển đổi định dạng. Một ý tưởng hay là sử dụng một số API để truy xuất cấu trúc dữ liệu và phân tích cú pháp như bạn muốn. WMIC là một lựa chọn tốt. Ví dụ dưới đây sử dụng Win32_LocalTime . Bạn cũng có thể sử dụng Win32_CurrentTime hoặc Win32_UTCTime .
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
for /f %%x in ('wmic path Win32_LocalTime get /format:list ^| findstr "="') do set %%x
set yyyy=0000%Year%
set mmmm=0000%Month%
set dd=00%Day%
set hh=00%Hour%
set mm=00%Minute%
set ss=00%Second%
set ts=!yyyy:~-4!-!mmmm:~-2!-!dd:~-2!_!hh:~-2!:!mm:~-2!:!ss:~-2!
echo %ts%
ENDLOCAL
Kết quả:
2018-04-25_10: 03: 11
Đây là phần mở rộng của câu trả lời của Joey để bao gồm thời gian và thêm các phần bằng 0.
Ví dụ: kết quả sẽ là 2019-06-01_17-25-36. Cũng lưu ý rằng đây là giờ UTC.
for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr "="') do set %%x
set Month=0%Month%
set Month=%Month:~-2%
set Day=0%Day%
set Day=%Day:~-2%
set Hour=0%Hour%
set Hour=%Hour:~-2%
set Minute=0%Minute%
set Minute=%Minute:~-2%
set Second=0%Second%
set Second=%Second:~-2%
set TimeStamp=%Year%-%Month%-%Day%_%Hour%-%Minute%-%Second%
Tôi đang sử dụng những thứ sau:
set iso_date=%date:~6,4%-%date:~3,2%-%date:~0,2%
Hoặc kết hợp với tên tệp log 'MyLogFileName':
set log_file=%date:~6,4%-%date:~3,2%-%date:~0,2%-MyLogFileName
Nếu bạn không ngại đầu tư một lần từ 10 đến 30 phút để có được giải pháp đáng tin cậy (điều đó không phụ thuộc vào cài đặt khu vực của Windows), vui lòng đọc tiếp.
Hãy giải phóng tâm trí của chúng ta. Bạn có muốn đơn giản hóa các tập lệnh để chỉ trông như thế này không? (Giả sử bạn muốn đặt biến LOG_DATETIME)
FOR /F "tokens=* USEBACKQ" %%F IN (`FormatNow "yyyy-MM-dd"`) DO (
Set LOG_DATETIME=%%F
)
echo I am going to write log to Testing_%LOG_DATETIME%.log
Bạn có thể. Chỉ cần tạo một FormatNow.exe với C # .NET và thêm nó vào PATH của bạn.
Ghi chú:
Những lợi ích:
Mã nguồn của FormatNow.exe mà tôi đã tạo bằng Visual Studio 2010 (Tôi muốn tự mình tạo mã này để tránh rủi ro tải xuống một chương trình không xác định, có thể là độc hại). Chỉ cần sao chép và dán các mã bên dưới, xây dựng chương trình một lần và sau đó bạn có một bộ định dạng ngày đáng tin cậy cho tất cả các lần sử dụng trong tương lai.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
namespace FormatNow
{
class Program
{
static void Main(string[] args)
{
try
{
if (args.Length < 1)
{
throw new ArgumentException("Missing format");
}
string format = args[0];
Console.Write(DateTime.Now.ToString(format, CultureInfo.InvariantCulture.DateTimeFormat));
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
Nói chung, khi xử lý các lôgic phức tạp, chúng ta có thể làm cho nó đơn giản hơn bằng cách xây dựng một chương trình rất nhỏ và thay vào đó gọi chương trình để thu kết quả đầu ra về một biến tập lệnh lô Chúng tôi không phải là sinh viên và chúng tôi không tham gia các kỳ thi yêu cầu chúng tôi tuân theo quy tắc chỉ tập lệnh theo lô để giải quyết vấn đề. Trong môi trường làm việc thực tế, bất kỳ phương pháp nào (hợp pháp) đều được phép. Tại sao chúng ta vẫn phải tuân theo các khả năng kém của tập lệnh hàng loạt Windows cần giải pháp thay thế cho nhiều tác vụ đơn giản? Tại sao chúng ta nên sử dụng công cụ sai cho công việc?