I wanted to get system time in nano seconds in Perl. I tried Time::HiRes module and it's supporting only until micro seconds.
The Time::HiRes module supports up to microseconds. As #MarcoS answered in the today common hardware is nonsense to use nanosecond precision counted by software.
Two subsequent calls, getting the current microseconds and print both afterwards
perl -MTime::HiRes=time -E '$t1=time; $t2=time; printf "%.6f\n", $_ for($t1, $t2)'
results (on my system)
1411630025.846065
1411630025.846069
e.g. only getting the current time two times and nothing between costs 3-4 microseconds.
If you want some "nanosecond numbers", simply print the time with 9digit precision, like:
perl -MTime::HiRes=time -E '$t1=time;$t2=time; printf "%.9f\n", $_ for($t1, $t2)'
you will get like:
1411630910.582282066
1411630910.582283974
pretty nanosecond times ;)
Anyway, you can sleep with reasonable nanosecond precision. From the doc
nanosleep ( $nanoseconds )
Sleeps for the number of nanoseconds (1e9ths of a second) specified.
Returns the number of nanoseconds actually slept (accurate
only to microseconds, the nearest thousand of them).
...
Do not expect nanosleep() to be exact down to one nanosecond.
Getting even accuracy of one thousand nanoseconds is good.
The time resolution depends on harwdware clock frequency, of course.
For example, an AMD 5200 has a 2.6Ghz clock, which has 0.4ns interval. The cost of gettimeofday with RDTSCP is 221 cycles: that equals 88ns at best. The minimal cost of a Perl routine will be hundreds times...
So, the final answer is:
On today's hardware, forget nano seconds. With Perl and with any high level language... You can get in that proximity just with assembler, but forget to count single nanoseconds, with software...
Perl get Time
useing Time::HiRes
c:\Code>perl -MDateTime::HiRes -E "while (1) {say DateTime::HiRes->now()->strftime('%F %T.%N');}"
or
use Time::HiRes qw(time);
use POSIX qw(strftime);
my $t = time;
my $date = strftime "%F %T.%N", localtime $t;
$date .= sprintf ".%03d", ($t-int($t))*1000; # without rounding
print $date, "\n";
The fundamental issue is that Perl's Time::HiRes uses an ordinary floating point value to represent the timestamp, usually implemented as a native C double, which on many platforms is a 64-bit IEEE float, with a 53-bit mantissa.
That means that timestamps are recorded to a resolution that varies with how far from 1970 they are:
approximate date range
resolution
13 Nov 1969 ~ 18 Feb 1970
less than 0.93ns
nanosecond resolution available
25 Sep 1969 ~ 08 Apr 1970
1.86ns
20 Jun 1969 ~ 14 Jul 1970
3.73ns
08 Dec 1968 ~ 24 Jan 1971
7.45ns
16 Nov 1967 ~ 16 Feb 1972
14.9ns
Jul 1961 ~ Jun 1978
29.8ns
1978~1986 & 1953~1961
59.6ns
1987~2003 & 1936~1952
0.119µs
►
2004~2037 & 1902~1935
0.238µs
◄
2038~2105 & 1834~1901
0.477µs
2106~2242 & 1698~1833
0.954µs
before 1697 or after 2243
worse than microsecond resolution
The "forget nanoseconds" people are all wrong: perl on normal machines now often returns the same microseconds in subsequent calls, so while atual nanosecond resolution might not (yet) be achievable, you absolutely do need nanoseconds now because microseconds are to coarse.
The above answers are wrong - fudging more digits from the imprecision of floats is NOT giving more precision:-
perl -MTime::HiRes=time -E 'while(1){my $now=sprintf("%.9f",time); die if($now==$last);$last=$now}'
That code does this:
Died at -e line 1.
Related
I need to get 18-digit Julian Timestamp in my perl script. Could anyone help me in this? However I have written a subroutine to achieve this but it does not look good to me since it always gives me a number ending with 6 zeroes. Please help to get a proper 18-digit J-timestamp.
sub GetJulianTimestamp()
{
my $t = `perl -e 'print time, "\n"'`;
return (($t * 1000000 ) + 210866803200000000);
}
Based on the comments, you appear to be asking how to obtain the number of microseconds since the unix epoch.
use Time::HiRes qw( );
my $microsec_time = int( Time::HiRes::time() * 1_000_000 );
return 210866803200000000 + $microsec_time;
I agree with the answer given by ikegami, except the amount to be added to the unix epoch needs to be changed. The value 210866803200000000 corresponds to November 24, 4714 BC, 00:00 Universal Time, Gregorian proleptic calendar. But the epoch of Julian dates is at noon, not midnight. So the amount to be added should be 210,866,760,000,000,000. And of course there is no official name for a Julian date that has been converted to microseconds, so anyone using such a number would have to provide an explanation to anyone who is receiving the data.
I'm faced a weird problem.
I have date in form of Tue Feb 25 00:20:13 2014.
my task is to calculate the week number and the week day.
I tried the following
use Time::Piece;
my $date="Tue Feb 25 00:20:13 2014";
my $db_date=Time::Piece->strptime($date, "%a %b %d %H:%M:%S %Y");
my $ww=$db_date->strftime("%W.%w-%Y);
print $ww;
When I run the script I get the output as
08.2-2014
which is wrong, the expected output is
09.2-2014
I want to know where did i go wrong?
pls help...
You're using the "%W" strftime() conversion. Time::Piece doesn't specify the meaning of "%W", but the documentation for the equivalent C function says that "%W" starts counting with the first week that contains a Monday. It sounds like you want the ISO 8601 week number, which starts counting with the first week that contains at least four days, in which case the "%V" conversion should do what you want.
I tried this code in linux machines,
my $sysdate = strftime "%Y%m%d%T", (localtime);
my $daylight_saving_time = strftime '%z', (localtime);
i get below output,
sysdate = 2013051402:12:02
daylight_saving_time = -0400
I tried same in solaries machines, i got this
sysdate = 2013051402:12:02
daylight_saving_time = %z
Anyone know the change to be done to get the daylight saving in solaries machines.
Thanks in Advance.
The issue is that POSIX::strftime just calls your system's strftime(3), so
you get whatever that is - or - is not. %z is not part of the POSIX.1 standard
and is not consistent across systems. On other older versions of OSes, like HPUX, %z, is
the same as %Z (time zone name). This is only for older versions.
On Solaris 8, 9 strftime does not support %z - with Solaris 10 it does.
This holds on more moderns versions Solaris 10 & Solaris 11:
%z Replaced by offset from UTC in ISO 8601:2000 standard format
(+hhmm or -hhmm), or by no characters if no time zone is deter-
minable. For example, "-0430" means 4 hours 30 minutes behind UTC
(west of Greenwich). If tm_isdst is zero, the standard time off-
set is used. If tm_isdst is greater than zero, the daylight sav-
ings time offset if used. If tm_isdst is negative, no characters
are returned.
So, this a C library function issue, perl sits on top of those libraries. I do not have a workaround.
Maybe the Date::Manip::TZ works on Solaris:
use Date::Manip::TZ;
my $tz = new Date::Manip::TZ;
say "tz: $tz";
I need to convert my TCL script to perl, i know bit of perl but not much:
I needed to convert this line to perl:
set current [clock format [clock scan "1 hour ago" -base [clock seconds]] -format "%Y-%m-%d %H"]
It prints the current date and 1 hour behind( Since the server returns EST, i want CST).
For example if today's date was 07/31/2012 and the time was 4:20pm(5:20pm EST) it would print
2012-07-31 16
The server returns eastern time, therefore I want it to print 1 hour ago to adjust to central time.
Note : it should not print 16:20.
Try this:
use POSIX qw/strftime/;
print strftime('%Y-%m-%d %H', localtime);
# prints 2012-07-31 14 for me, currently
EDIT: If you have to get this format for one hour ago, then do this instead:
use POSIX qw/strftime/;
my $hour_ago = time() - (60*60);
print strftime('%Y-%m-%d %H', localtime($hour_ago));
# prints 2012-07-31 13 for me, currently
And if it's a time zone issue, you might want consider dealing with the time zone explicitly, rather than assuming a one hour offset. Here's an article on handling time zones in Perl.
In Perl, localtime takes a Unix timestamp and gives back year/month/day/hour/min/sec etc. I'm looking for the opposite of localtime: I have the parts, and I'd like to build a unix timestamp from them.
You can use the timelocal function in the Time::Local CPAN module.
NAME
Time::Local - efficiently compute time
from local and GMT time
SYNOPSIS
$time = timelocal($sec,$min,$hour,$mday,$mon,$year);
$time = timegm($sec,$min,$hour,$mday,$mon,$year);
DESCRIPTION
This module provides functions that
are the inverse of built-in perl
functions localtime() and gmtime().
They accept a date as a six-element
array, and return the corresponding
time(2) value in seconds since the
system epoch (Midnight, January 1,
1970 GMT on Unix, for example). This
value can be positive or negative,
though POSIX only requires support for
positive values, so dates before the
system's epoch may not work on all
operating systems.
It is worth drawing particular
attention to the expected ranges for
the values provided. The value for the
day of the month is the actual day (ie
1..31), while the month is the number of months since January (0..11). This
is consistent with the values returned
from localtime() and gmtime().
Note: POSIX::mktime is a just a wrapper around your C library's mktime() function. Time::Local is a pure-Perl implementation, and always returns results matching Perl's localtime. Also, Time::Local offers gmtime, while mktime only works in local time. (Well, you could try changing $ENV{TZ}, but that doesn't work on some systems.)
POSIX::mktime
DateTime on CPAN might of of some use. It also has a lot of time manipulation/translation methods.
Just create the DateTime using your parts and call $datetime->formatter("%s") ;