18 digit julian timestamp in perl - perl

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.

Related

Converting timestamps in Perl

I am looking to convert timestamps such as the following
2019-01-01T02:15:00+00:00
Into Australian Eastern Standard Time in Perl.
I have over 10,000 of these timestamps, any help would be really appreciated
I need to input them into a mysql DB with a format of YYYY-MM-DD hh:mm:ss
You would use the standard Perl module Time::Piece. It provides the standard strptime and strftime functions. The first allows you to parse a timestamp with a template and the second outputs a timestamp based on the same kind of template. To change timezones you would add or subtract the number of seconds difference.
$t = Time::Piece->strptime("2020-11-04T01:46:00", "%Y-%m-%dT%H:%M:%S");
$t += $offset;
print $t->strftime("%Y-%m-%dT%H:%M:%S");
Or if your current time is the current locale and you're always converting from GMT:
$t = Time::Piece->strptime("2020-11-04T01:46:00", "%Y-%m-%dT%H:%M:%S");
$l = localtime $t->epoch;
print $l->strftime("%Y-%m-%dT%H:%M:%S");
Now if you need to do something more complicated than that (daylight savings time, leap seconds), there is the DateTime module but it is correspondingly far more complicated to use.
See also How can I parse dates and convert time zones in Perl?
HTH

Error when dealing with old and historical dates in Perl Time::Piece

It seems Time:Piece gives me this error:
Error parsing time at /usr/lib/perl5/site_perl/Time/Piece.pm line 481.
after the line where I use strptime with some old dates.
My code contains this:
my $ddate = "$month / $day / $year";
my $tmp = Time::Piece->strptime( $ddate, "%m / %d / %Y");
and $$date takes dates from a database using DBI that contains historical and old dates (dates back to the 10th and 9th centuries AD). How can I deal with this if there is any solution?
You'll have to use something other than Time::Piece if you want to deal with timestamps before 1970.
If you want to use the Gregorian calendar, you can use DateTime.
If you want to use the Julian calendar, you can use DateTime::Calendar::Julian.
The Gregorian calendar was introduced in September, 1582, and it was used universally by 1918. In between, calendar usage varied by country.
$ perl -MDateTime::Calendar::Julian -E'
say
DateTime::Calendar::Julian->new(year => 1013, month => 2, day => 22)
->strftime("%a");
'
Sun
Alternatively, Date::Convert looks promising if you're just care about dates (not timestamps).

Calculating seconds since the Unix Epoch when there is no +"%s" option for the 'date' command available

I wanted to calculate the seconds since the Unix Epoch (1970-01-01 00:00:00). Usually I would use
date +"%s"
Now, on my system the +"%s" option is not available but I easily got around using some other 'date' options and parsed it using bc:
date -u +"scale=0;(((((%Y-1970)*365.2425+%j)*24+%H)*60+%M)*60+%S)/1" | bc
This is short for
years = year_now - 1970
days = years * 365.2425 + day_of_year_now
hours = days * 24 + hour_now
minutes = hours * 60 + minute_now
seconds = minutes * 60 + second_now
So far so good. Then I discovered that the result of this calculation does not match with the result of the +"%s" option. I needed to add a magic number:
date -u +"scale=0;(((((%Y-1970)*365.2425+%j)*24+%H)*60+%M)*60+%S-36936)/1" | bc
Why?
Additionally, several months later, this magic number has changed from -36936 to -99792.
Why?
I'm sure something is wrong with my maths. I do not need better solutions in other script languages but I'd appreciate if somebody could correct my maths, please. Maybe someone has the source code for date and could show me its internal algorithm for +"%s" ... ?
Here is a POSIX way that should then work on all Unix and Unix like systems:
awk 'BEGIN {srand();print srand()}'
If you use ksh93, this should also work:
printf "%(%s)T\n"
Most system will have perl installed:
perl -le 'print time'

Generating Dates between two date ranges in AWK

I need to create a list of days between a date interval.
Say for example from 2001-01-01 to 2009-12-31:
2001-01-01
2001-01-02
2001-01-03
..
2009-12-29
2009-12-30
2009-12-31
I know how to do it but maybe someone has a script already made?
If not, I will make such a script and upload it so others won't waste time on this when they need it.
I do not know awk from GnuWin32, but if the functions "mktime" and "strftime" are available, you can try the following code:
BEGIN {
START_DATE="2001-02-01"
END_DATE="2001-03-05"
S2=START_DATE
gsub("-"," ",S2)
T=mktime(S2 " 01 00 00")
if (T<0)
printf("%s is invalid.\n",START_DATE) >> "/dev/stderr"
else
{
for(S=START_DATE; END_DATE>S ;T+=86440) print S=strftime("%F",T)
}
}
The key is to convert the start date to a number meaning the seconds since the Epoch, add 86400 seconds (one day or 24 x 60 x 60) and convert back to the ISO date format.
After some trials I realized the mktime() function admits wrong dates as good (for instance, 2000-14-03).
Best regards

How can I get start of month in epoch form from random epoch timestamp in Perl?

I get some times from a database and I am trying to store them by month, using the epoch form.
So I could have some random times like:
1354120744
1328978360
1297388332
and for each one I want to find the epoch value which represents the 1st of that month
so for the last timestamp it would be:
1296518400 (using lovely epochconverter.com).
I know that I can use POSIX mktime to reduce the timestamp down to days, mins etc and change them accordingly etc as was the answer to a post I did a while ago: How to go back months in Perl taking account of different days in month?
The trouble I have with that is that while I can zero times, I'm worried that by changing the date the day of week will not match up, so essentially making an invalid date. This may be an unnecessary worry; I don't know if it would make a difference having the wrong day of week if the times are validated.
I couldn't see any other POSIX methods which seemed useful. Any help appreciated!
I stopped worrying about timestamp issues since I've met DateTime:
$ perl -MDateTime -E 'say DateTime->from_epoch(epoch => 1354120744)->truncate(to => "month")->epoch;'
1351728000
My first thought would be to use Time::Local to convert the localtime results back to epoch, with the appropriate values forced to 0 or 1 as needed. Note that day of week is not among the input values it expects, so you don't need to worry about what happens if you get that wrong.
$start_of_month_epoch = timelocal(0, 0, 0, 1, $month, $year);
The trouble I have with that is that while I can zero times, I'm worried that by changing the date the day of week will not match up, so essentially making an invalid date.
mktime(3) ignores the wday, yday and isdst fields for this exact reason. You can safely adjust the mday to 1 then call POSIX::mktime() again to turn it back to an epoch value.
my #t = localtime();
$t[0] = $t[1] = $t[2] = 0; # sec/min/hour
$t[3] = 1; # mday
my $epoch_start_of_month = mktime #t;
Or simpler
my $epoch = mktime 0, 0, 0, 1, (localtime)[4,5];