3 #=======================================================================
5 # File ID: efffd138-8a3f-11e5-8010-7927c6c13cb1
7 # Print timestamp when a specific goal will be reached.
10 # ©opyleft 2015– Øyvind A. Holm <sunny@sunbase.org>
11 # License: GNU General Public License version 2 or later, see end of
12 # file for legal stuff.
13 #=======================================================================
18 use Time
::HiRes
qw{ gettimeofday
};
35 $progname =~ s/^.*\/(.*?)$/$1/;
36 our $VERSION = '0.5.0';
38 Getopt
::Long
::Configure
('bundling');
41 'current-time|c=s' => \
$Opt{'current-time'},
42 'frac|F' => \
$Opt{'frac'},
43 'help|h' => \
$Opt{'help'},
44 'quiet|q+' => \
$Opt{'quiet'},
45 'verbose|v+' => \
$Opt{'verbose'},
46 'version' => \
$Opt{'version'},
48 ) || die("$progname: Option error. Use -h for help.\n");
50 $Opt{'verbose'} -= $Opt{'quiet'};
51 $Opt{'help'} && usage
(0);
52 if ($Opt{'version'}) {
62 if (!defined($ARGV[3])) {
63 warn("$progname: Missing arguments\n");
66 my ($begintime, $beginval, $endval, $currval) = @ARGV;
69 if ($begintime =~ /^(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d(\.\d+)?)$/) {
70 $begin_ep = timegm
($6, $5, $4, $3, $2-1, $1);
72 warn("$progname: Invalid date format, " .
73 "must be \"YYYY-MM-DD HH:MM:SS[.sssss]\"\n");
76 msg
(2, "begin_ep = '$begin_ep'");
78 if (length($Opt{'current-time'})) {
79 if ($Opt{'current-time'} =~
80 /^(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d(\.\d+)?)$/
82 $now = timegm
($6, $5, $4, $3, $2-1, $1);
84 warn("$progname: Invalid date format in -c/--current-time\n");
88 $now = gettimeofday
();
90 if ($beginval == $currval) {
91 warn("$progname: Current value must be different from start value\n");
94 my $end_ep = goal_x
($endval, $begin_ep, $beginval, $now, $currval);
95 msg
(2, "end_ep = '$end_ep'");
97 sec_to_interval
($end_ep - $now),
98 sec_to_string
($end_ep),
106 # Return x when y, x0, y0, x1 and y1 are known {{{
107 my ($y, # Goal to find timestamp for
114 # Avoid division by zero
117 my $x = $x0 + ($y - $y0) / ($y1 - $y0) * ($x1 - $x0);
123 # Print program version {{{
124 print("$progname $VERSION\n");
129 sub sec_to_interval
{
131 my $origsecs = shift;
132 my $secs = 1.0 * abs($origsecs);
133 my $rem = 1.0 * $secs;
134 my $frac = sprintf("%.6f", 1.0 * $rem - int($rem));
137 } elsif ($frac =~ /^1/) {
139 $rem = int($rem) + 1;
144 my $days = 1.0 * int($rem / 86400.0);
145 $rem -= 1.0 * $days * 86400.0;
146 my $hours = 1.0 * int($rem / 3600.0);
147 $rem -= 1.0 * ($hours * 3600.0);
148 my $minutes = 1.0 * int($rem / 60.0);
149 $rem -= 1.0 * ($minutes * 60.0);
150 my $seconds = 1.0 * $rem;
151 my $retval = sprintf("%s%ud:%02u:%02u:%02u%s",
152 $origsecs < 0 ?
"-" : "",
153 $days, $hours, $minutes, $seconds, $Opt{'frac'} ?
$frac : '');
156 } # sec_to_interval()
159 # Convert seconds since 1970 to "yyyy-mm-dd hh:mm:ss[.frac]Z" {{{
160 my ($Seconds, $Sep) = @_;
161 length($Seconds) || return('');
162 ($Seconds =~ /^-?(\d*)(\.\d+)?$/) || return(undef);
163 my $Secfrac = ($Seconds =~ /^([\-\d]*)(\.\d+)$/) ?
1.0*$2 : "";
166 defined($Sep) || ($Sep = " ");
167 my @TA = gmtime($Seconds);
168 my($DateString) = sprintf("%04u-%02u-%02u %02u:%02u:%02u%sZ",
169 $TA[5]+1900, $TA[4]+1, $TA[3],
170 $TA[2], $TA[1], $TA[0], $Opt{'frac'} ?
$Secfrac : '');
176 # Send the help message to stdout {{{
179 if ($Opt{'verbose'}) {
185 Print timestamp when a specific goal will be reached.
187 Usage: $progname [options] begin_date begin_val end_val current_val
189 All timestamps use UTC, and the date format must be specified as
190 "YYYY-MM-DD HH:MM:SS[.sssss]".
194 -c DATE, --current-time DATE
195 Use DATE as current time.
197 Use fractional seconds.
201 Be more quiet. Can be repeated to increase silence.
203 Increase level of verbosity. Can be repeated.
205 Print version information.
213 # Print a status message to stderr based on verbosity level {{{
214 my ($verbose_level, $Txt) = @_;
216 if ($Opt{'verbose'} >= $verbose_level) {
217 print(STDERR
"$progname: $Txt\n");
225 # This program is free software; you can redistribute it and/or modify
226 # it under the terms of the GNU General Public License as published by
227 # the Free Software Foundation; either version 2 of the License, or (at
228 # your option) any later version.
230 # This program is distributed in the hope that it will be useful, but
231 # WITHOUT ANY WARRANTY; without even the implied warranty of
232 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
233 # See the GNU General Public License for more details.
235 # You should have received a copy of the GNU General Public License
236 # along with this program.
237 # If not, see L<http://www.gnu.org/licenses/>.
239 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :