How do I convert a UNIX timestamp to ISO in CMake - cmake

I have a UNIX-style timestamp that looks like 1587405820 -0600 which I would like to convert to an ISO style format, something like YYYY-MM-DDTHH:MM:SSZ
CMake has a string(TIMESTAMP ...) command at https://cmake.org/cmake/help/v3.12/command/string.html#timestamp but this only gets me the current time in a formatted string which does not work for my application. I need to be able to convert an existing time into ISO format.
Is there a way to do this?
UPDATE
Based on #squareskittles answer, here's what I ended up with this test which is doing the right thing:
# Check that we get the current timestamp
string(TIMESTAMP TIME_T UTC)
message(STATUS ">>> T1: ${TIME_T}")
# Get the ISO string from our specific timestamp
set(ENV{SOURCE_DATE_EPOCH} 1587405820)
string(TIMESTAMP TIME_T UTC)
unset(ENV{SOURCE_DATE_EPOCH})
message(STATUS ">>> T2: ${TIME_T}")
# Check that we get the current timestamp again correctly
string(TIMESTAMP TIME_T UTC)
message(STATUS ">>> T3: ${TIME_T}")
Which gives me this output:
-- >>> T1: 2020-04-22T15:08:13Z
-- >>> T2: 2020-04-20T18:03:40Z
-- >>> T3: 2020-04-22T15:08:13Z

If you want this function to use a specific time other than than the current time, you can set the environment variable SOURCE_DATE_EPOCH to the UNIX-style timestamp (integer):
# Set the environment variable to a specific timestamp.
set(ENV{SOURCE_DATE_EPOCH} 1587405820)
# Convert to ISO format, and print it.
string(TIMESTAMP MY_TIME)
message(STATUS ${MY_TIME})
prints (for UTC -0600):
2020-04-20T12:03:40
If you need to adjust this time to UTC time, you can add the UTC argument:
set(ENV{SOURCE_DATE_EPOCH} 1587405820)
string(TIMESTAMP MY_TIME UTC)
message(STATUS ${MY_TIME})
prints:
2020-04-20T18:03:40Z
Note: If this SOURCE_DATE_EPOCH variable is used elsewhere in your CMake code, it is best to save the SOURCE_DATE_EPOCH value before modifying it, so it can be set back to its previous value when complete.

Related

mktime() returns an incorrect value right after entering DST

The following snippet code is from rtc.c in busybox-1.22.1.
In my case the utc is always 0, so this function is just doing a conversion from struct tm to time_t.
time_t FAST_FUNC rtc_tm2time(struct tm *ptm, int utc)
{
//fprintf(stdout, "ptm->tm_hour: %d\n", ptm->tm_hour);
char *oldtz = oldtz; /* for compiler */
time_t t;
if (utc) {
oldtz = getenv("TZ");
putenv((char*)"TZ=UTC0");
tzset();
}
t = mktime(ptm); //problem here
//struct tm* temp = localtime(&t);
//fprintf(stdout, "temp->tm_hour: %d\n", temp->tm_hour);
if (utc) {
unsetenv("TZ");
if (oldtz)
{
putenv(oldtz - 3);
}
tzset();
}
return t;
}
Also, there is a file /etc/TZ displaying timezone and DST information.
~ # cat /etc/TZ
LMT0:00LMT-1:00,M8.5.1/10,M12.5.1/10
Then, I set system time to 2021/8/30, 9:59:30 (30 seconds earlier than DST start date), and sync to hwclock.
date -s 2021.08.30-09:59:30 >/dev/null 2>/dev/null //set system time
hwclock -w //sync RTC to system time
Entering hwclock continuously while observing the output on CLI.
~ # hwclock
ptm->tm_hour : 9
temp->tm_hour : 9
Mon Aug 30 09:59:58 2021 0.000000 seconds
~ # hwclock
ptm->tm_hour : 10
temp->tm_hour : 11 //why not 10?
Mon Aug 30 11:00:00 2021 0.000000 seconds
Why the return value from mktime is added by 1 when entering DST? Shouldn't it be affected by DST?
According to the mktime() man pages, mktime() is allowed to update the tm_isdst value. The starting value may cause the mktime() algorithm to branch differently:
The value specified in the tm_isdst field informs mktime() whether or not
daylight saving time (DST) is in effect for the time supplied in the tm
structure: a positive value means DST is in effect; zero means that DST is not in
effect; and a negative value means that mktime() should (use timezone information
and system databases to) attempt to determine whether DST is in effect at the
specified time.
and then update the value of tm_isdst accordingly:
tm_isdst is set (regardless of its initial value) to a positive value or to 0,
respectively, to indicate whether DST is or is not in effect at the specified time.
In other words, I'd check the tm_isdst value before and after the mktime() call.
One way I've dealt with this in the past is to
call mktime() with a known value of tm_isdst (e.g. zero or one)
call localtime() on the returned time_t value, then check tm_isdst on the struct tm pointer localtime() returns.
if the tm_isdst has been changed from the prior known value, change the original struct tm to use the new tm_isdt value then call mktime() again with it before trusting the time_t it returns.
It's definitely less efficient but it's possible to know when the DST change occurs by expecting it and checking for it.
Another option would be to set tm_isdst to -1 before calling mktime() and trusting its lookup of timezone and set tm_isdst appropriately.

Using Time::Piece with Apache::Log::Parser

I am using Apache::Log::Parser to parse Apache log files.
I extracted the date from log file using the following code.
my $parser = Apache::Log::Parser->new(fast=>1);
my $log = $parser->parse($data);
$t = $log->{date};
Now,I tried to use Time::Piece to parse dates, but I'm unable to do it.
print "$t->day_of_month";
But, it's not working. How to use Time::Piece to parse date?
You cannot call methods on objects inside of string interpolation. It will probably output something like this:
Sat Feb 18 12:44:47 2017->day_of_month
Remove the double quotes "" to call the method.
print $t->day_of_month;
Now the output is:
18
Note that you need to create a Time::Piece object with localtime or gmtime if you have an epoch value in your log, or using strptime if the date is some kind of timestamp.

dse pig datetime functions

Can someone give a full example of date time functions including the 'register' jar ? I have been trying to get CurrentTime() and ToDate() running without much success. I have the piggybank jar in classpath and registered the same. But it always says the function has to be defined before usage.
I read this question comparing datetime in pig before this.
Datetime functions can be easily implemented using native pig, you no need to go for piggybank jar.
Example:
In this example i will read set of dates from the input file, get the current datetime and calculate the total no of days between previous and current date
input.txt
2014-10-12T10:20:47
2014-08-12T10:20:47
2014-07-12T10:20:47
PigScript:
A = LOAD 'input.txt' AS (mydate:chararray);
B = FOREACH A GENERATE ToDate(mydate) AS prevDate,CurrentTime() AS currentDate,DaysBetween(CurrentTime(),ToDate(mydate)) AS diffDays;
DUMP B;
Output:
(2014-10-12T10:20:47.000+05:30, 2014-12-12T10:39:15.455+05:30, 61)
(2014-08-12T10:20:47.000+05:30, 2014-12-12T10:39:15.455+05:30, 122)
(2014-07-12T10:20:47.000+05:30, 2014-12-12T10:39:15.455+05:30, 153)
You can refer few examples from my old post
Human readable String date converted to date using Pig?
Storing Date and Time In PIG
how to convert UTC time to IST using pig

How to use mktime to change time with miliseconds info. retained?

for example
I want to add 13.29s to 2013-4-24 3:10:50.50
how to handle the milisecond ?
I've tried to use mktime and strftime, but it seems that can only deal with seconds...
awk is really a powerful tool, but I don't think awk was the best choice here, I would go with gnu date.
see the test with your example data:
#add 13.29s to date 2013-4-24 3:10:50.50
kent$ date -d'+13.29 second 2013-4-24 3:10:50.50' +"%F %T.%N"
2013-04-24 03:11:03.790000000
well I know that there are trailing zeros for nano seconds. but I think it wouldn't be problem for you if you want to remove them.
you can invoke external command from awk, if using awk is a must for you.
Not simple thing to do, but here we go:
time="2013-4-24 3:10:50.50"
echo "13.29" | awk '{split(v,a,"[ -:.]");t=mktime(a[1]" "a[2]" "a[3]" "a[4]" "a[5]" "a[6])+(a[7]/100)+$1;print strftime("%Y-%m-%d %H:%M:%S",t)"."(t-int(t))*100}' v="$time"
2013-04-24 03:11:03.79
With explanation
echo "13.29" | awk '
{
split(v,a,"[ -:.]") # Split the date string into separate parts
t=mktime(a[1]" "a[2]" "a[3]" "a[4]" "a[5]" "a[6])+(a[7]/100)+$1 # Convert to epoch time and add milliseconds and calcualte the new value
print strftime("%Y-%m-%d %H:%M:%S",t)"."(t-int(t))*100 # Convert back to normal time format and print it out
}
' v="$time" # Read the variable

Find timestamp of the latest version of file

For the latest file in a stream, how can I get the timestamp associated with the version? I tried accurev hist <elem>, but that returns the entire history and now I have to parse through it.
Edit:
When I tried accurev hist -t highest <fileName>
the result is:
element: /./a/b/c/Ver_2.xlsm
eid: 461
transaction 1335; promote; 2012/10/30 16:50:01 ; user: scrubbed
version 1/3 (46/1)
So extracting just the timestamp i.e. 2012/10/30 16:50:01 from this entire result seemed more work. So, my first question in comments was if we can just get the timestamp back i.e. 2012/10/30 16:50:01
After trying the new command accurev hist -fx -t highest -p mydepot Ver_2.xlsm, the return value is an xml value :
......
<transaction
id="1335"
type="promote"
time="1351630201"
user="scrubbed">
........
This time, the timestamp is returned as epoch value. I guess I can find a way to convert this to timestamp value, but if it is possible to have a return value of 2012/10/30 16:50:01, that would work best.
Try tossing in the "-t highest" flag for your hist command, that will retrieve only the latest transaction information for the file in that stream...
This is for latest version in a specific stream:
accurev hist -fx -t highest -s stream_name .\path_to_element
This is for the latest version in the depot:
accurev hist -fx -t highest -p depot_name .\path_to_element
After your edit, I now understand that you JUST want the timestamp value. There's no way to return a single attribute. I'd suggest you use the -fx option and parse for the correct attribute. To convert epoch time to a readable value, use this:
c:>perl -e "print scalar localtime(1334932836);"
Fri Apr 20 10:40:36 2012
Hope this helps.
~James