strptime and timeformat in for loop - unix-timestamp

I'm quite new to Python. I'm trying to convert a string object into a UNIX timestamp using strptime and mktime.
When I run my script in Python Shell, I get no errors - so the Date/Time format strptime gets as an argument must be OK. But when I try to implement the code into my full code (into a for loop) I get an error:
ValueError: time data 'Wed Mar 09 00:07:38 2016' does not match format '%a %b %d %H:%M:%S %Y'.
This is quite weird, knowing that the format is OK.
This is the script I tested in Python Shell:
import time
import datetime
datetimestring = 'Wed Mar 09 00:07:38 2016'
timestamp = time.mktime(time.strptime(datetimestring, '%a %b %d %H:%M:%S %Y'))
print timestamp
This is the code that doesn't work in my larger full code:
for row in rows:
report = str(getattr(row, 'answerTime'))
print report
timestamp = time.mktime(time.strptime(report, '%a %b %d %H:%M:%S %Y'))
print timestamp

Related

Convert filetime to GMT in Perl

I am working on some training material for new programmers where I am talking about the HTTP Header, so I am trying to set the Last-Modified manually. I have everything worked out except for getting the file time to GMT. Below is what I have so far:
The question is: giving stat($fh)->mtime which could be running in any timezone, what code needs to be added to convert to GMT?
my $scriptFilename = $ENV{'SCRIPT_FILENAME'};
my $timestamp;
my $fh = FileHandle->new;
if ($fh->open("< ${scriptFilename}")) {
$timestamp = time2str("%a, %e %b %Y %X %Z", stat($fh)->mtime);
$fh->close;
}
#Last-Modified: Tue, 15 Oct 2019 12:45:26 GMT
print <<"END";
Content-type: text/html; charset=iso-8859-1
Last-Modified: $timestamp
<html>
...
</html>
time2str from the Date::Format package (I assume that's where time2str comes from) takes an optional 3rd argument to specify the timezone.
$timestamp = time2str("%a, %e %b %Y %X %Z", stat($fh)->mtime, 'UTC');
There seems to be some confusion here: the result of mtime is not in any time zone, it is in seconds since the epoch which is a fixed point in time (barring leap seconds which are ignored). Thus all you need to do is represent it in the time zone you want, which is UTC. Another answer mentioned how to do this with the function you had been using, but the usual function to format a time into a string is strftime, which is provided by a couple core modules.
use strict;
use warnings;
use POSIX 'strftime';
# gmtime interprets the mtime seconds in UTC
my $timestamp = strftime "%a, %e %b %Y %X %Z", gmtime $mtime;
use Time::Piece 'gmtime';
my $timestamp = gmtime($mtime)->strftime("%a, %e %b %Y %X %Z");
But your use case is actually a specific date format, the one the HTTP protocol uses, and which will always be in GMT/UTC. There is a module for that: HTTP::Date
use strict;
use warnings;
use HTTP::Date 'time2str';
my $timestamp = time2str $mtime;
Basically
my $dt = DateTime->new(
year => 2000,
month => 5,
day => 10,
hour => 15,
minute => 15,
time_zone => 'America/Los_Angeles',
);
print $dt->hour; # prints 15
$dt->set_time_zone( 'America/Chicago' );
print $dt->hour; # prints 17
See here for how to format the output.

Perl convert localtime to unix (epoch) time

using perl, I am trying to estimate the time since a file was created.
I would like to convert the local time to unix time (epoch), then take unix time of the file & subtract.
The problem I face is that when I convert localtime to unixtime , it is converted incorrectly!
my $current = str2time (localtime(time));
print $current;
The results I get are
2768504400 = Sun, 23 Sep 2057 21:00:00 GMT
2421349200 = Sun, 23 Sep 2046 21:00:00 GMT
Do I have to feed str2time with a specific date format?
You're doing something bizarre here - localtime(time) takes - the epoch time (time) and converts it to a string.
And then you convert it back.
Just use time()
Or perhaps better yet -M which tells you how long ago a file was modified. (In days, so you'll have to multiply up).
e.g.:
my $filename = "sample.csv";
my $modification = -M $filename;
print $modification * 84600;
But if you really want to take the time and convert it back again - you'll need to look at how localtime(time) returns the result.
If you do:
print localtime(time);
You get:
5671624811542661
Because localtime is being evaluated in a list context, and so returning an array of values. (Which you can use without needing to parse).
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);
If you do it in a scalar context, it returns a string denoting the time:
print "".localtime(time);
Gives:
Thu Sep 24 16:09:33 2015
But note - that might vary somewhat depending on your current locale. That's probably why str2time is doing odd things - because it makes certain assumptions about formats that don't always apply. The big gotcha is this:
When both the month and the date are specified in the date as numbers they are always parsed assuming that the month number comes before the date. This is the usual format used in American dates.
You would probably be better off instead using Time::Piece and strftime to get a fixed format:
e.g.
use Time::Piece;
print localtime(time) -> strftime ( "%Y-%m-%d %H:%M:%S" );
Note - Time::Piece overloads localtime so you can actually use it (fairly) transparently. Of course, then you can also do:
print localtime(time) -> epoch;
And do without all the fuss of converting back and forth.
You have missed requesting localtime to produce scalar (string) instead of array.
use Date::Parse;
my $current = str2time (scalar(localtime(time)));
print $current, "\n";
print scalar(localtime($current)),"\n";
perldoc -f localtime
Converts a time as returned by the time function to a 9-element
list with the time analyzed for the local time zone. Typically
used as follows:
# 0 1 2 3 4 5 6 7 8
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
...
In scalar context, "localtime()" returns the ctime(3) value:
$now_string = localtime; # e.g., "Thu Oct 13 04:54:34 1994"

Perl Date String Parsing with Time::Piece

For some reason I am having a lot of trouble parsing date strings using Time::Piece.
So this works:
my $t = Time::Piece->strptime( 'Sunday, November 4, 2012 10:25:15 PM -0000' , "%A, %B %d, %Y %I:%M:%S %p %z" );
print $t;
But this does not:
my $temp_time = Time::Piece->strptime('7/23/2014 5:24:22 PM', "%-m/%-d/%Y %l:%M:%S %p");
print $temp_time;
I have also used '%D %r' as the format string but that also does not work. Do any of you have insight as to why this might be? For reference , the hour is 1-12 (not 01-12) and the month is 1-12 (not 0-12).
Thanks!
Change
"%-m/%-d/%Y %l:%M:%S %p"
to
"%m/%d/%Y %l:%M:%S %p"

How to compare dates using perl?

How can i compare two dates in the format using Perl:
"dd mon yyyy hh:mm:ss GMT"
e.g.: 12 May 2013 10:10:20 GMT
I cannot install any external Perl modules.
Please advice.
If you have Perl v5.9.5 or newer, you can use Time::Piece core module. Here's a simple demonstration of relevant operations
Convert the dates from string to Time::Piece object
my $date = "12 May 2013 10:10:20 GMT";
my $tp1 = Time::Piece->strptime($date, "%d %B %Y %T %Z");
my $tp2 = ...
Find the difference between the 2 time
my $diff = $tp2 - $tp1;
which gives you a Time::Seconds object.
Finally, display the difference in units of seconds (or something else).
print $diff->seconds;
Or you could just compare the two directly (thanks stevenl)
$tp2 > $tp1
References:
Time::Seconds
Time::Piece
man strftime for format string to use with Time::Piece->strptime
man strptime for format string to use with $tp->strftime
Note that only format characters aAbBcdHIjmMpSUwWxXyYZ% are safe if you're using non-Unix system (for example, Window's Perl doesn't support the %e specifier).
Convert the dates to the format yyyymmddhhmmss (e.g. 20130512101020) and compare as strings. Handling the time zones might get tricky without modules, though.
One of the most popular date modules is DateTime. It has a FAQ which may help you get started.
sub to_comparable {
my ($date) = #_;
my ($H,$M,$S,$d,$m,$Y) = $date =~ m{^([0-9]{2}):([0-9]{2}):([0-9]{2}), ([0-9]{2})/([0-9]{2})/([0-9]{4})\z}
or die;
return "$Y$m$d$H$M$S";
}
if (to_comparable($date2) < to_comparable($date1)) {
...
} else {
...
}

How to parse string in perl having timezone of format GMT[+/-]hh:mm?

I have a string of date and time of format:
Day, Month DAY_OF_MONTH, Year HH:MM:SS AM/PM GMT[+/-]hh:mm .
But I am unable to parse it. I have used this:
Time::Piece->strftime($string, "%A, %B %d, %Y %I:%M:%S %p %Z%z");
I have converted the string into the format : Day, Month DAY_OF_MONTH, Year HH:MM:SS AM/PM [+/-]hhmm . But still its not working for me with
Time::Piece->strftime($string, "%A, %B %d, %Y %I:%M:%S %p %z");
The string is getting parsed but the time zone is not considered in the Time::Piece object as tzoffset is 0000 and the HH of the date has the same value as that in the string. Please anyone help.
Eg: String to be parsed: Friday, July 25, 2008 12:15:57 PM GMT-0700
If Time::Piece doesn't work, try using Date::Parse.
And as oalders mentioned, do include an actual date string example in your question.
Perhaps the following will help:
use strict;
use warnings;
use Time::Piece;
my $string = 'Sunday, November 4, 2012 10:25:15 PM -0000';
my $t = Time::Piece->strptime( $string, "%A, %B %d, %Y %I:%M:%S %p %z" );
print $t;
Output:
Sun Nov 4 22:25:15 2012