Gawk: Inverse of Strftime() - Convert Date String to Seconds Since Epoc Timestamp Using Format Pattern

GAWK: Inverse of strftime() - Convert date string to seconds since epoc timestamp using format pattern

The function you're looking for is called mktime(). You should use the gensub() function to manipulate the datespec into the format that can be read by mktime().


To format the second example that you give, consider:

BEGIN {
t = "2013-01-26 15:36:24"
f = "\\1 \\2 \\3 \\4 \\5 \\6"

s = mktime(gensub(/(....)-(..)-(..) (..):(..):(..)/, f, "", t))

print s
}

Results on my machine:

1359178584

To format the first example that you give, consider:

BEGIN {
t = "Sat 26. Jan 15:36:24 CET 2013"

gsub(/\.|:/, FS, t)
split(t,a)

Y = a[8]
M = convert(a[3])
D = a[2]

h = a[4]
m = a[5]
s = a[6]

x = mktime(sprintf("%d %d %d %d %d %d", Y, M, D, h, m, s))

print x
}

function convert(month) {

return(((index("JanFebMarAprMayJunJulAugSepOctNovDec", month) - 1) / 3) + 1)
}

Results on my machine:

1359178584

For more information, please consult the manual, specifically time functions and string functions. HTH.

Shell script to compare the time difference and alert if greater than 5 minutes?

Can't you use perl?

if perl -MDate::Parse -e '
exit( str2time($ARGV[1]) - str2time($ARGV[0]) <= $ARGV[2] )
' "$StartTime" "$CurrentTime" "$AlertThreshold"
then
echo alert
fi

RegExp to match date and time from custom log file

if you only work on your log file, the regex is ok. Because you could assume that your log file will always give a valid Datetime String. (e.g. 2012-13-56 28:23:77 won't happen)

But what I am gonna point out is, your awk codes may have problem.

  • I don't know which gawk version are you using (I guess > 4.0), --re-interval option is not default if version < 4.

  • There is an error in your string replace: you should replace "-" to " " as well right?

awk man page:

 mktime(datespec)
Turns datespec into a time stamp of the same form as returned by systime(). The datespec is a string of the form YYYY MM DD HH MM SS[ DST].

see the difference:

kent$  gawk '{print $0;gsub(/:|-/," ");print mktime($0)}' <<<"2012-11-01 15:27:28"
2012-11-01 15:27:28
1351780048

output with your awk line:
2012-11-01 15:27:28
1293719248

filter dates within a text file

Using GNU awk for time functions:

$ cat tst.awk
BEGIN {
tgtDays = 10
tgtSecs = tgtDays * 24 * 60 * 60

endTime = strftime("%Y %m %d 12 00 00")
endSecs = mktime(endTime,1)
}
{
mthNr = (index("JanFebMarAprMayJunJulAugSepOctNovDec",$4)+2)/3
begTime = sprintf("%04d %02d %02d 12 00 00", $7, mthNr, $5)
begSecs = mktime(begTime,1)
}
(endSecs - begSecs) < tgtSecs


$ awk -f tst.awk sample.txt
system system_data8 Thu Jul 29 22:36:38 2021

Note that in the above we replace the time of day in both the input data and the current time with noon because when determining how many days between 2 dates by converting a timestamp to seconds since the epoch first then dividing by the number of seconds in a day you have to use the same time each day because otherwise your "number of days" calculation can/will be thrown off by the time each day.

For example look at the following that's trying to determine if 2 dates which ARE 10 days apart are less than 10 days apart:

$ cat diffDatesDemo.awk
BEGIN {
tgtDays = 10
tgtSecs = tgtDays * 24 * 60 * 60

begTime = "2021/08/01 09:00:00"
endTime = "2021/08/11 08:00:00"

begDate = gensub(/([ :][0-9]{2}){3}$/,"",1,begTime)
endDate = gensub(/([ :][0-9]{2}){3}$/,"",1,endTime)

print "Is", begTime, "less than", tgtDays, "days before", endTime "?"

####
print "\nWrong: Compare 2 timestamps including date plus time of day:"
begSecs = mktime(gensub("[/:]"," ","g",begTime),1)
endSecs = mktime(gensub("[/:]"," ","g",endTime),1)

print begDate, "->", endDate, "is", ((endSecs - begSecs) < tgtSecs ? "<" : ">="), tgtDays, "days"
####

####
print "\nRight: Compare 2 dates at the same time each day:"
begSecs = mktime(gensub("[/:]"," ","g",begDate)" 12 00 00",1)
endSecs = mktime(gensub("[/:]"," ","g",endDate)" 12 00 00",1)

print begDate, "->", endDate, "is", ((endSecs - begSecs) < tgtSecs ? "<" : ">="), tgtDays, "days"
####
}


$ awk -f diffDatesDemo.awk
Is 2021/08/01 09:00:00 less than 10 days before 2021/08/11 08:00:00?

Wrong: Compare 2 timestamps including date plus time of day:
2021/08/01 -> 2021/08/11 is < 10 days

Right: Compare 2 dates at the same time each day:
2021/08/01 -> 2021/08/11 is >= 10 days

I also used the UTC flag for mktime() above to make sure that any local DST changes didn't impact the number of days calculation.

Convert Unix timestamp to a date string

With date from GNU coreutils you can do:

date -d "@$TIMESTAMP"
# date -d @0
Wed Dec 31 19:00:00 EST 1969

(From: BASH: Convert Unix Timestamp to a Date)

On OS X, use date -r.

date -r "$TIMESTAMP"

Alternatively, use strftime(). It's not available directly from the shell, but you can access it via gawk. The %c specifier displays the timestamp in a locale-dependent manner.

echo "$TIMESTAMP" | gawk '{print strftime("%c", $0)}'
# echo 0 | gawk '{print strftime("%c", $0)}'
Wed 31 Dec 1969 07:00:00 PM EST

How to convert YYYYMMDDHHMMSS to a date readable by `date`

date doesn't allow "YYYYMMDDHHMMSS", but it does "YYYYMMDD HH:MM:SS", so:

D="20100101123456"
date -d "${D:0:8} ${D:8:2}:${D:10:2}:${D:12:2}"

How to change Git log date formats

The others are (from git help log):

--date=(relative|local|default|iso|rfc|short|raw)
Only takes effect for dates shown in human-readable format,
such as when using "--pretty". log.date config variable
sets a default value for log command’s --date option.

--date=relative shows dates relative to the current time, e.g. "2 hours ago".

--date=local shows timestamps in user’s local timezone.

--date=iso (or --date=iso8601) shows timestamps in ISO 8601 format.

--date=rfc (or --date=rfc2822) shows timestamps in RFC 2822 format,
often found in E-mail messages.

--date=short shows only date but not time, in YYYY-MM-DD format.

--date=raw shows the date in the internal raw git format %s %z format.

--date=default shows timestamps in the original timezone
(either committer’s or author’s).

There is no built-in way that I know of to create a custom format, but you can do some shell magic.

timestamp=`git log -n1 --format="%at"`
my_date=`perl -e "print scalar localtime ($timestamp)"`
git log -n1 --pretty=format:"Blah-blah $my_date"

The first step here gets you a millisecond timestamp. You can change the second line to format that timestamp however you want. This example gives you something similar to --date=local, with a padded day.


And if you want permanent effect without typing this every time, try

git config log.date iso 

Or, for effect on all your git usage with this account

git config --global log.date iso


Related Topics



Leave a reply



Submit