How to get date in DDMMYYYY format in Tcl? - datetime

I am creating a TCL script which creates a log file. The time and date are made part of the log file name.
This is what I have at present:
set fname_date [clock format [clock seconds] -format {%d-%h-%y}]
set fname_time [clock format [clock seconds] -format {%H%M%S}]
set log_fname "test_log"
append log_fname "_$fname_time"
append log_fname "_$fname_date"
append log_fname ".dat"
This gives the filename as:
test_log_155838_23-Aug-22.dat
However, I need the date to be all numbers so the filename looks like this instead:
life_test_log_155838_230822.dat
How to get the current date in DDMMYY format from TCL? I am not sure what format string to use to do this.

The clock format details are here:
https://www.tcl-lang.org/man/tcl8.6/TclCmd/clock.htm
DDMMYY format is %d%m%y
DDMMYYYY format is %d%m%Y

Long form, your code adapted
set fname_date [clock format [clock seconds] -format %d%m%y]
set fname_time [clock format [clock seconds] -format %H%M%S]
set log_fname "test_log"
append log_fname "_$fname_time"
append log_fname "_$fname_date"
append log_fname ".dat"
puts $log_fname
Short form
set log_fname "life_test_log_[clock format [clock seconds] -format %H%M%S]_[clock format [clock seconds] -format %d%m%y].dat"
puts $log_fname
See https://www.tcl.tk/man/tcl8.4/TclCmd/clock.html

Related

Specifying picture informant in order to read specific datetme string

I would like to read the "19-APR-21 18.17.06.301100" the string into a DATETIME and display accordingly. In order to achieve that I'm intending to define a display format and an informat as provided in the example below.
Example
* Define formats to read and display data;
* Input format;
PROC FORMAT LIB=work;
PICTURE indte other = '%d-%B-%y %H.%M.%S.%s'
(DATATYPE=DATETIME);
RUN;
* Nice display format;
PROC FORMAT LIB=work;
PICTURE outdte other = '%d %B %y %H:%M'
(DATATYPE=DATETIME);
RUN;
* Test with sample data;
DATA text;
strdate = "19-APR-21 18.17.06.301100";
RUN;
* Apply informat and display format;
DATA pretty(RENAME=(strdate=nicedte));
SET work.text;
ATTRIB strdate INFORMAT=indte.;
FORMAT strdate outdte.;
RUN;
Problems/questions
The DATA pretty procedure is not able to load the define formats and returns the following error:
NOTE 485-185: Informat $INDTE was not found or could not be loaded.
NOTE 484-185: Format $OUTDTE was not found or could not be loaded.
Is this an efficient way of doing this for the data that in the proper process is sourced via: infile <file ref created by filename> delimiter=',' stopover firstobs=2 dsd lrecl=32767;?
PICTURE is used to create a FORMAT, not an INFORMAT.
The ANYDTDTM informat should handle strings in that style. But it will ignore the fractions of a second.
DATA text;
strdate = "19-APR-21 18.17.06.301100";
datetime = input(strdate,anydtdtm.);
format datetime datetime26.6 ;
put (_all_) (=/);
RUN;
Results:
strdate=19-APR-21 18.17.06.301100
datetime=19APR2021:18:17:06.000000
If you need the fractions of a second then parse the string and read it separately.
datetime = dhms(input(strdate,date9.)
,input(scan(strdate,2,' .'),2.)
,input(scan(strdate,3,' .'),2.)
,input(scan(strdate,4,' .'),2.)
+input(scan(strdate,5,' .'),6.6)
);

Python ValueError: time data does not match format ' %H:%M %d/%m/%Y'

I am continually getting this string formatting error, but I cannot find what doesn't match properly. I've tried removing the leading space from the format string, but that does not make a difference. I'm using Python 3.5 on OSX 10.11.5
ValueError: time data ' 00:59 03/20/1978' does not match format ' %H:%M %d/%m/%Y'
The function call, in case there's a culprit farther back:
def bytedate2num(fmt):
def converter(b):
return mdates.strpdate2num(fmt)(b.decode('ascii'))
return converter
date_converter = bytedate2num(' %H:%M %d/%m/%Y')
def get_events(fname):
events = []
events.append(np.loadtxt(fname, comments = '#', delimiter='\t', converters = {0 : date_converter}))
return events
Any suggestions are much appreciated, since this function is responsible for gathering all the data to analyze.
According to the error:
ValueError: time data ' 00:59 03/20/1978' does not match format ' %H:%M %d/%m/%Y'
You are trying to use the wrong date format. Specifically, according to this, it is trying to parse the 20 as a month (%m). I think the date format you want is ' %H:%M %m/%d/%Y' (notice that the %m and %d have been switched).

How to make a plot that has x-axis for specified time frame in tcl/tk?

I'm fairly new to tcl/tk and i'm trying to create a stripchart plot that allows me to set the time frame for x-axis example:
Link to pic of a time graph
I'm able to do it with dates, like this:
set s [::Plotchart::createXYPlot .c [list [clock scan 2006-01-01] [clock scan 2007-01-01] ""] {0.0 100.0 20.0} \
-xlabels {2006-01-01 2006-06-01 2007-01-01}]
but when i try to enter a time instead of two dates it's not working.
Thanks
When using clock scan, you can parse dates and times quite easily (and the result has precision to the level of seconds). However, it is best to specify the format that you expect the time to be in, and to pick a fixed instant as baseline if you are just parsing times. When such things become common, it's best to write a helper procedure:
# This is just for parsing time-of-day, *NOT DATES*.
# Handles both HH:MM and HH:MM:SS...
proc timestamp {timeString} {
if {[scan $timeString %d:%d:%d dummy dummy dummy] == 3} {
clock scan $timeString -format %H:%M:%S -base 0 -gmt 1
} else {
clock scan $timeString -format %H:%M -base 0 -gmt 1
}
}
# This should be recognizably similar
set s [::Plotchart::createXYPlot .c \
[list [timestamp 2:40] [timestamp 7:20] [timestamp 12:00:19]] \
{0.0 100.0 20.0} \
-xlabels {2:40 7:20 12:00:19}]
If course, if you've got both times and dates then you can do a better job by picking different format(s).

In PowerShell, how do I convert DateTime to UNIX time?

In PowerShell, how can I convert string of DateTime to sum of seconds?
PS H:\> (New-TimeSpan -Start $date1 -End $date2).TotalSeconds
1289923177.87462
New-TimeSpan can be used to do that. For example,
$date1 = Get-Date -Date "01/01/1970"
$date2 = Get-Date
(New-TimeSpan -Start $date1 -End $date2).TotalSeconds
Or just use this one line command
(New-TimeSpan -Start (Get-Date "01/01/1970") -End (Get-Date)).TotalSeconds
With .NET Framework 4.6 you can use ToUnixTimeSeconds method of DateTimeOffset class:
[DateTimeOffset]::Now.ToUnixTimeSeconds()
$DateTime = Get-Date #or any other command to get DateTime object
([DateTimeOffset]$DateTime).ToUnixTimeSeconds()
As mentioned, the UNIX Epoch is January 1st, 1970 at 12:00 AM (midnight) UTC.
To get the current seconds-since-the-epoch in UTC in a whole-number I use this 80-character one-liner
$ED=[Math]::Floor([decimal](Get-Date(Get-Date).ToUniversalTime()-uformat "%s"))
The code above is PowerShell 2.0 compliant & rounds-down (to ensure consistent behavior w/ UNIX)
Not sure when -UFormat was added to Get-Date but it allows you to get the date and time in UNIX epoch timestamp format:
[int64](Get-Date -UFormat %s)
It's supported by both the PowerShell and PowerShell Core.
This one-liner works for me (compared it to http://www.unixtimestamp.com/)
[int64](([datetime]::UtcNow)-(get-date "1/1/1970")).TotalSeconds
For milliseconds
[int64](([datetime]::UtcNow)-(get-date "1/1/1970")).TotalMilliseconds
To get seconds since 1970 independent of time zone, I would go with:
$unixEpochStart = new-object DateTime 1970,1,1,0,0,0,([DateTimeKind]::Utc)
[int]([DateTime]::UtcNow - $unixEpochStart).TotalSeconds
I just wanted to present yet another, and hopefully simpler, way to address this. Here is a one liner I used to obtain the current Unix(epoch) time in UTC:
$unixTime = [long] (Get-Date -Date ((Get-Date).ToUniversalTime()) -UFormat %s)
Breaking this down from the inside out:
(Get-Date).ToUniversalTime()
This gets the current date/time in UTC time zone. If you want the local time, just call Get-Date.
This is then used as input to...
[long] (Get-Date -Date (UTC date/time from above) -UFormat %s)
Convert the UTC date/time (from the first step) to Unix format.
The -UFormat %s tells Get-Date to return the result as Unix epoch time (seconds elapsed since January 01, 1970 00:00:00). Note that this returns a double data type (basically a decimal). By casting it to a long data type, it is automatically converted (rounded) to a 64-bit integer (no decimal). If you want the extra precision of the decimal, don't cast it to a long type.
Extra credit
Another way to convert/round a decimal number to a whole number is to use System.Math:
[System.Math]::Round(1485447337.45246)
Powershell
$epoch = (Get-Date -Date ((Get-Date).DateTime) -UFormat %s)
I suggest the following, which is based on ticks (Int64), rather than seconds (Int32), to avoid the Year 2038 problem. [Math]::Floor is used, as Unix time is based on the number of whole seconds since the epoch.
[long][Math]::Floor((($DateTime.ToUniversalTime() - (New-Object DateTime 1970, 1, 1, 0, 0, 0, ([DateTimeKind]::Utc))).Ticks / [timespan]::TicksPerSecond))
Here's a script which converts both TO and FROM CTIME that I've been using for a while (longer, because it was written for a "new to scripting" type crowd, with various comments.
# Here's a very quick variant to 'get the job done'
[Int64]$ctime=1472641743
[datetime]$epoch = '1970-01-01 00:00:00'
[datetime]$result = $epoch.AddSeconds($Ctime)
write-host $result
# A few example values for you to play with:
# 1290100140 should become ... 2010-11-18 17:09:00.000
# 1457364722 should become ... 2016-03-07 15:32:02.000
# 1472641743 should become ... 31/08/2016 11:09:03
# For repeated use / calculations, functions may be preferable. Here they are.
# FROM C-time converter function
# Simple function to convert FROM Unix/Ctime into EPOCH / "friendly" time
function ConvertFromCtime ([Int64]$ctime) {
[datetime]$epoch = '1970-01-01 00:00:00'
[datetime]$result = $epoch.AddSeconds($Ctime)
return $result
}
# INTO C-time converter function
# Simple function to convert into FROM EPOCH / "friendly" into Unix/Ctime, which the Inventory Service uses.
function ConvertToCTime ([datetime]$InputEpoch) {
[datetime]$Epoch = '1970-01-01 00:00:00'
[int64]$Ctime = 0
$Ctime = (New-TimeSpan -Start $Epoch -End $InputEpoch).TotalSeconds
return $Ctime
}
Hope that helps, especially if you just want something that's a little friendlier for beginners or so :).
For sending data to Grafana I needed the Unix Epoch time as 32 bit Integer from UTC. The best solution in the end was this:
$unixtime = (get-date -Date (get-date).ToUniversalTime() -UFormat %s).Substring(0,10)
This results in a string, but can easy converted to an integer:
[int]$unixtime = (get-date -Date (get-date).ToUniversalTime() -UFormat %s).Substring(0,10)
I tested this against an Ubuntu machine. The results from the commands above and the Linux command
date +%s
are identically.
Below cmdlet will convert the windows uptime into Unix understandable epoch time format:
$s=Get-WmiObject win32_operatingsystem | select csname,#{LABEL='LastBootUpTime';EXPRESSION{$_.ConverttoDateTime($_.lastbootuptime)}};
[Math]::Floor([decimal](Get-Date($s.LastBootUpTime.ToUniversalTime()).ToUniversalTime()-uformat "%s"))
Again comparing to http://www.unixtimestamp.com and building on others above
$date1 = (Get-Date -Date "01/01/1970").ToUniversalTime()
$date2 = (Get-Date).ToUniversalTime()
$epochTime = [Math]::Floor((New-TimeSpan -Start $date1 -End $date2).TotalSeconds)
This one should also work since javascript uses milliseconds since epoch :
ConvertTo-Json (Get-Date) | ? { $_ -Match '\(([0-9]+)\)' } | % { $Matches[1]/1000 }
Step by Step :
PS P:\> Get-Date
lundi 15 janvier 2018 15:12:22
PS P:\> ConvertTo-Json (Get-Date)
{
"value": "\/Date(1516025550690)\/",
"DisplayHint": 2,
"DateTime": "lundi 15 janvier 2018 15:12:30"
}
PS P:\> (ConvertTo-Json (Get-Date)) -Match '\(([0-9]+)\)'
True
PS P:\> $Matches
Name Value
---- -----
1 1516025613718
0 (1516025613718)
You can use the Uformat parameter of get-date. But first I like to be sure the date of a given workstation is correct (I consider a workstation connected to a company network where there is a server with a correct time set).
#Synchronize workstation time with server
cmd /c "sc config w32time start= auto"
cmd /c "w32tm /unregister"
cmd /c "w32tm /register"
cmd /c "net start w32time"
cmd /c 'tzutil.exe /s "W. Europe Standard Time"'
cmd /c 'reg add "HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" /v DisableAutoDaylightTimeSet /t REG_DWORD /d 0 /f'
cmd /c "net time \\full-servername.ru /set /yes"
Then I get the actual unix timestamp to compare objects (accounts) between actual date and creation date (account deletion tasks when unix timestamp exceeds limit date)
#Get actual unix timestamp and compare it to something
$actual_date = (get-date -UFormat "%s")
$final_date = "some unix date of the database"
if(($final_date - $actual_date) -lt 0 ){
#make deletion task
}
Signal15's answer is a bit verbose for me. I did it this way:
[int] (Get-Date (Get-Date).ToUniversalTime() -uformat '%s')
Late answer...
Hare are both convert functions ConvertTo-UnixTime & ConvertFrom-UnixTime for convenience (both pipeline capable)
function ConvertFrom-UnixTime () {
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline, Position = 0)]
[Int64]$UnixTime
)
begin {
$epoch = [DateTime]::SpecifyKind('1970-01-01', 'Utc')
}
process {
$epoch.AddSeconds($UnixTime)
}
}
function ConvertTo-UnixTime {
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline, Position = 0)]
[DateTime]$DateTime
)
begin {
$epoch = [DateTime]::SpecifyKind('1970-01-01', 'Utc')
}
process {
[Int64]($DateTime.ToUniversalTime() - $epoch).TotalSeconds
}
}
A culture-independent, and actually pretty fast answer:
[int64]([double]::Parse((get-date -uformat "%s"),[cultureinfo][system.threading.thread]::currentthread.currentculture))
This invokes some .NET "magic" when it comes to actually produce a formatted string, it gets converted to double using current thread's culture settings, then it converts to int64 which by default does exactly floor the double provided. Should you desire a UTC timestamp, use -date ([DateTime]::UtcNow) in get-date to use current UTC time as the time to convert.
[int64]([double]::Parse((get-date -date ([DateTime]::UtcNow) -uformat "%s"),[cultureinfo][system.threading.thread]::currentthread.currentculture))
PS: Unless you really need a string as your output, having an integer is overall better to your programming culture.

How to format a DateTime in PowerShell

I can format the Get-Date cmdlet no problem like this:
$date = Get-Date -format "yyyyMMdd"
But once I've got a date in a variable, how do I format it? The statement below
$dateStr = $date -format "yyyMMdd"
returns this error:
"You must provide a value expression
on the right-hand side of the '-f'
operator"
The same as you would in .NET:
$DateStr = $Date.ToString("yyyyMMdd")
Or:
$DateStr = '{0:yyyyMMdd}' -f $Date
A simple and nice way is:
$time = (Get-Date).ToString("yyyy:MM:dd")
The question is answered, but there is some more information missing:
Variable vs. Cmdlet
You have a value in the $Date variable and the -f operator does work in this form: 'format string' -f values. If you call Get-Date -format "yyyyMMdd" you call a cmdlet with some parameters. The value "yyyyMMdd" is the value for parameter Format (try help Get-Date -param Format).
-f operator
There are plenty of format strings. Look at least at part1 and part2. She uses string.Format('format string', values'). Think of it as 'format-string' -f values, because the -f operator works very similarly as string.Format method (although there are some differences (for more information look at question at Stack Overflow: How exactly does the RHS of PowerShell's -f operator work?).
A very convenient -- but probably not all too efficient -- solution is to use the member function GetDateTimeFormats(),
$d = Get-Date
$d.GetDateTimeFormats()
This outputs a large string-array of formatting styles for the date-value. You can then pick one of the elements of the array via the []-operator, e.g.,
PS C:\> $d.GetDateTimeFormats()[12]
Dienstag, 29. November 2016 19.14
One thing you could do is:
$date.ToString("yyyyMMdd")
Do this if you absolutely need to use the -Format option:
$dateStr = Get-Date $date -Format "yyyMMdd"
However
$dateStr = $date.toString('yyyMMdd')
is probably more efficient.. :)
Very informative answer from #stej, but here is a short answer:
Among other options, you have 3 simple options to format [System.DateTime] stored in a variable:
Pass the variable to the Get-Date cmdlet:
Get-Date -Format "HH:mm" $date
Use toString() method:
$date.ToString("HH:mm")
Use Composite formatting:
"{0:HH:mm}" -f $date
For anyone trying to format the current date for use in an HTTP header use the "r" format (short for RFC1123) but beware the caveat...
PS C:\Users\Me> (get-date).toString("r")
Thu, 16 May 2019 09:20:13 GMT
PS C:\Users\Me> get-date -format r
Thu, 16 May 2019 09:21:01 GMT
PS C:\Users\Me> (get-date).ToUniversalTime().toString("r")
Thu, 16 May 2019 16:21:37 GMT
I.e. Don't forget to use "ToUniversalTime()"
If you got here to use this in cmd.exe (in a batch file):
powershell -Command (Get-Date).ToString('yyyy-MM-dd')
I needed the time and a slight variation on format. This works great for my purposes:
$((get-date).ToLocalTime()).ToString("yyyy-MM-dd HHmmss")
2019-08-16 215757
According to #mklement0 in comments, this should yield the same result:
(get-date).ToString("yyyy-MM-dd HHmmss")
Format Date Time to your Output Needs
If you want to format the date and assign the string to a variable.
I have combined both PowerShell and .NET to provide the flexibility.
$oDate = '{0}' -f ([system.string]::format('{0:yyyyMMddHHmmss}',(Get-Date)))
How this Works
PowerShell Operator - '{0}' -f (.....)
.NET Notation - [system.string]::format('customformat',InputObject)
Customised Format by combining PowerShell with .NET - '{0:yyyyMMddHHmmss}'
Input Object provided by PowerShell cmdlet - (Get-Date)
Stored in the PowerShell variable - $oDate
Example
If the date and time when run was Monday, 5 July 2021 5:45:22 PM (Format '{0:F}').
$oDate = 20210705174522
Using the Code
You can customise the the string to meet your requirements by modifying 'yyyMMddHHmmss' using the Microsoft .NET Custom Date Time Notation.
You could just use this to select the format you want and then past it wherever it is needed.
$DTFormats = (Get-Date).GetDateTimeFormats()
$Formats = #()
$i=0
While ($i -lt $DTFormats.Count){
$row = [PSCustomObject]#{
'IndexNumber' = $i
'DateTime Format' = $DTFormats[$i]
}
$Formats += $row
$i++
}
$DTSelection = ($Formats | Out-GridView -OutputMode Single -Title 'Select DateTime Format').IndexNumber
$MyDTFormat = "(Get-Date).GetDateTimeFormats()[$DTSelection]"
Write-Host " "
Write-Host " Use the following code snippet to get the DateTime format you selected:"
Write-Host " $MyDTFormat" -ForegroundColor Green
Write-Host " "
$MyDTFormat | Clip
Write-Host " The code snippet has been copied to your clipboard. Paste snippet where needed."
I converted my dueDate string to a datetime then formatted it.
[Datetime]::ParseExact($dueDate,'MM/dd/yyyy H:mm:ss',$null).ToString('MM/dd/yyyy')

Resources