The Perl Toolchain Summit 2025 Needs You: You can help 🙏 Learn more

#!perl
## no critic (InputOutput::RequireBriefOpen)
use 5.010;
use strict;
#use Log::Any '$log';
our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
our $DATE = '2023-02-18'; # DATE
our $DIST = 'App-datecalc'; # DIST
our $VERSION = '0.090'; # VERSION
sub get_options {
require Getopt::Long;
my %opts;
Getopt::Long::GetOptions(
'--help|h|?', \$opts{help},
'--version|v', \$opts{version},
);
if ($opts{help}) {
print <<_;
Usage:
datecalc [OPTIONS]
Options:
--help, -h, -?
--version, -v
_
exit 0;
} elsif ($opts{version}) {
say "datecalc version $::VERSION";
exit 0;
}
}
sub eval_loop {
require App::datecalc;
require File::HomeDir;
require IO::Stty;
require Term::ReadLine;
my $calc = App::datecalc->new;
my $term = Term::ReadLine->new('datecalc');
my $prompt = "> ";
my $OUT = $term->OUT || \*STDOUT;
my $histfile = File::HomeDir->my_home . "/.datecalc_history";
# load history from file
if ($term->Features->{setHistory} && (-r $histfile)) {
#$log->tracef("Loading history from %s ...", $histfile);
open(my $fh, '<', $histfile)
or die "Can't open history file $histfile: $!\n";
chomp(my @history = <$fh>);
$term->SetHistory(@history);
}
my $sub_save_hist = sub {
if ($term->Features->{getHistory}) {
my $fh;
if (open $fh, ">", $histfile) {
print $fh "$_\n" for
List::Util::Uniq::uniq_adj(
grep { length } $term->GetHistory
);
}
}
};
local $SIG{INT} = sub {
# save history when we are interrupted
$sub_save_hist->();
print STDERR "Interrupted\n";
if ($term->ReadLine eq 'Term::ReadLine::Gnu') {
IO::Stty::stty(\*STDIN, 'echo');
}
exit 1;
};
#local $SIG{__DIE__} = sub {
# IO::Stty::stty(\*STDIN, 'echo');
# die @_;
#};
# some workaround for Term::ReadLine
my $attribs = $term->Attribs;
if ($term->ReadLine eq 'Term::ReadLine::Gnu') {
# TR::Gnu traps our INT handler
$attribs->{catch_signals} = 0;
} elsif ($term->ReadLine eq 'Term::ReadLine::Perl') {
# TR::Perl messes up colors
# doesn't do anything?
#$term->ornaments(0);
#$attribs->{term_set} = ["", "", "", ""];
}
while ( defined ($_ = $term->readline($prompt)) ) {
my $res;
if ($_ eq 'help' || $_ eq '?') {
say "Type date expression into the prompt, e.g.: 2014-06-26 + 2 week.";
say "For more details on available features, 'man datecalc'.";
say "";
next;
} elsif ($_ eq 'exit' || $_ eq 'quit') {
last;
}
eval { $res = $calc->eval($_) };
if ($@) {
warn "Error: $@\n";
} else {
print $OUT $res, "\n";
}
# double?
#$term->addhistory($_) if /\S/;
}
$sub_save_hist->();
}
### main
get_options();
eval_loop();
# ABSTRACT: Date calculator
# PODNAME: datecalc
__END__
=pod
=encoding UTF-8
=head1 NAME
datecalc - Date calculator
=head1 VERSION
This document describes version 0.090 of datecalc (from Perl distribution App-datecalc), released on 2023-02-18.
=head1 SYNOPSIS
% datecalc
> today
2014-05-13#Tue
> tomorrow
2014-05-14#Wed
> today + 2 days
2014-05-15#Thu
> 2014-05-13 - 2014-02-14
P2M3W6D
> days(2014-05-13 - 2014-02-14)
4
> totdays(2014-05-13 - 2014-02-14)
88
> 2 months 3 weeks 6 days
P2M3W6D
> P10D
P1W3D
> 2014-05-13 + P2D
2014-05-15#Thu
> 2 * 2 days 10 hours
P4DT20H
> P10D / 2
P5D
> 6d + 8d + 13 min
P2WT13M
> month(today)
5
> days(P8D)
1
> weeks(P8D)
1
> P8D
P1W1D
=head1 DESCRIPTION
This is a command-line utility to perform date calculations.
For now, for more details, see L<App::datecalc>.
=head1 FAQ
=head2 Why is date addition/subtraction with fractional duration incorrect?
For example:
> 2001-01-01 + P1.5M
2001-02-01#Thu
One would expect something closer to C<2001-02-16>. But this is how
L<DateTime::Duration> works. Instead of using fractions in larger units, try
using smaller units instead. For example:
> 2001-01-01 + P1M2W
2001-02-15#Thu
=head1 FILES
=head2 ~/.datecalc_history
=head1 HOMEPAGE
Please visit the project's homepage at L<https://metacpan.org/release/App-datecalc>.
=head1 SOURCE
=head1 AUTHOR
perlancar <perlancar@cpan.org>
=head1 CONTRIBUTING
To contribute, you can send patches by email/via RT, or send pull requests on
GitHub.
Most of the time, you don't need to build the distribution yourself. You can
simply modify the code, then test via:
% prove -l
If you want to build the distribution (e.g. to try to install it locally on your
system), you can install L<Dist::Zilla>,
L<Dist::Zilla::PluginBundle::Author::PERLANCAR>,
L<Pod::Weaver::PluginBundle::Author::PERLANCAR>, and sometimes one or two other
Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond
that are considered a bug and can be reported to me.
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2023, 2018, 2016, 2015, 2014 by perlancar <perlancar@cpan.org>.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=head1 BUGS
Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=App-datecalc>
When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.
=cut