NAME
Time::Activated - Syntactic sugar over time activated code supporting DateTime and ISO8601 (a.k.a. "Javascript dates").
VERSION
Version 1.01
SYNOPSIS
use Time::Activated;
# simple statements
time_activated after_moment '1985-01-01T00:00:00' => execute_logic { print "New feature beginning Jan 1st 1985!" };
time_activated before_moment '1986-12-31T00:00:00' => execute_logic { print "This feature ends by 1986!" };
time_activated before_moment '2000' => execute_logic { print "Let's dance like its 1999!" };
time_activated
between_moments '2016-01-01T00:00:00' => '2016-12-31T23:59:59' =>
execute_logic { print "Business logic exception for 2016!" };
# combined statements a la try {} catch {} by Try::Tiny (tm)
time_activated
after_moment '1985-01T00:00:00-03:00' => execute_logic { print "New business logic!" }, # <-- Gotcha! it is a ,
before_moment '1986-12-31T00:00:00-03:00' => execute_logic { print "Old business logic!" };
# elements get evaluated in order
time_activated
before_moment '1986-12-31T00:00:00-03:00' => execute_logic { print "Old business logic!" }, # <-- Switch that ;
after_moment '1985-01-01T00:00:00-03:00' => execute_logic { print "New business logic!" }; # <-- Switch that ,
# overlapping allowed, all matching items get executed
time_activated
after_moment '2018', execute_logic { print "This is from 2018-01-01 and on." },
after_moment '2018-06-01', execute_logic { print "This is from 2018-06-01 and on. On top of the previuos." };
# Alternate syntax
time_activated
after_moment '2018', execute_logic { print "Welcome to new business process for 2018!" }, #=> is a ,
after_moment '2019', execute_logic { print "This is added on top of 2018 processes for 2019!" };
# DateTime objects can be used to define points in time
my $dt = DateTime->new(year=>2018, month=>10, day=>16);
time_activated after_moment $dt => execute_logic { print "This happens after 2018-10-16!" };
DESCRIPTION
This modules aims at managing and documenting time activated code such as that which may araise from migrations and planified process changes in a way that can be integrated and tested in advance.
You can use Time::Activated before
, after
and between
to state which parts of code will be executed on certain dates due to changing business rules, programmed web service changes in endpoints/contracts or other time related events.
USAGE
EXPORTS
By default Time::Activated exports time_activated
, before
, after
, between
and execute
.
If you need to rename the time_activated
, after
, before
, between
or executye
keyword consider using Sub::Import to get Sub::Exporter's flexibility.
If automatic exporting sound nasty: use Time::Activated qw();
SYNTAX
time_activated "CONDITION" "WHEN" "WHAT"
"CONDITION"
Can be any of after_moment
, before_moment
, between_moments
. after_moment
, accepts a parameters representing a point in time at and after which the execute_logic statement will be executed. before_moment
, accepts a parameters representing a point in time before, but not including, which the execute_logic statement will be executed. between_moments
, accepts two parameters representing a range in time between, both limits included, which the execute_logic statement will be executed.
"WHEN"
Is either a DateTime object or a scalar representing a iso8601 (a.k.a. Javascript date)
Expansion is supported so '2000', '2000-01', '2000-01-01' and '2000-01-01T00:00' all are equivalents to '2000-01-01T00:00:00'.
Timezones are supported and honored. Thus:
time_activated
after_moment '1999-12-31T23:00:00-01:00' => execute_logic { print('Matches from 2000-01-01T00:00:00 GMT!') },
after_moment '2000-01-01T00:00:00+01:00' => execute_logic { print('Matches from 1999-01-01T23:00:00 GMT!') };
after
includes the exact time which is used as parameter, before
does not. Thus using after
and before
with the same time parameter ensures that only one statement gets executed. i.e.:
time_activated
before_moment SOME_DATE => execute { print "Before!" },
after_moment SOME_DATE => execute { print "After!" };
"WHAT"
Is either an anonymous code block or a reference to subroutine Code that will be executed on a given conditions in many ways:
time_activated
after_moment '2001' => execute_logic \&my_great_new_feature; #No parameters can be passed with references...
time_activated
after_moment '2000' => execute_logic { print 'Y2K ready!' },
after_moment '2001' => execute_logic (\&my_great_new_feature), #References with multilines need ()
after_moment '2002' => execute_logic { &my_great_new_feature("We need parameters by 2002")};
CONSTANTS
It is cool to use constants documenting both time and intent.
use constants PROCESS_X_CUTOVER_DATE => '2017-01-01T00:00:00';
time_activated after_moment PROCESS_X_CUTOVER_DATE => execute_logic { &new_business_process($some_state) };
TESTING
Test::MockTime is your friend.
use Test::More tests => 1;
use Time::Activated;
use Test::MockTime;
Test::MockTime::set_absolute_time('1986-05-27T00:00:00Z');
time_activated after_moment '1985-01-01T00:00:00-03:00' => execute_logic { pass('Basic after') }; # this gets executed
Test::MockTime::set_absolute_time('1984-05-27T00:00:00Z');
time_activated after_moment '1985-01-01T00:00:00-03:00' => execute_logic { fail('Basic after') }; # this does not get executed
SUBROUTINES/METHODS
time_activated
time_activated
is both the syntactical placeholder for grammar in Time::Activated
and the internal implementation of the modules functionality.
Syntactically the structure is like so (note the ','s and ';'):
time_activated
after_moment ..., execute_logic ...,
before_moment ..., execute_logic ...,
between_moments ..., ... execute_logic ...;
Alternatively some can be changed for a => for a fancy syntax. This abuses anonymous hashes, some inteligent selections of prototypes (stolen from Try::Tiny) and probably other clever perl-ish syntactical elements that escape my understanding. Note '=>'s, ','s and ';':
time_activated
after_moment ... => execute_logic ...,
before_moment ... => execute_logic ...,
between_moments ... => ... => execute_logic ...; #Given. This does not look so fancy but more into the weird side...
before_moment
before_moment
defines a point in time before not including the exact point in time which code is executed.
This does not happen before January 1st 2018 at 00:00 but does happen from that exact point in time and on.
time_activated
before_moment '2018', execute_logic { print "We are awaiting for 1/1/2018..." };
Another fancy way to say do not do that before January 1st 2018 at 00:00.
ime_activated
before_moment '2018' => execute_logic { print "We are awaiting for 1/1/2018..." };
A fancy way to combine before statements.
time_activated
before_moment '2018' => execute_logic { print "We are awaiting for 1/1/2018..." },
before_moment '2019' => execute_logic { print "Not quite there for 1/1/2019..." };
after_moment
after_moment
defines a point in time after including the exact point in time which code is executed.
time_activated
after_moment '2018' => execute { print "Wea are either at 1/1/2018 or after it..." };
As with before_moment
statements can be combined with before_moment
, after_moment
and between_moments
with no limit.
between_moments
between_moments
defines two points in time between which code is executes including both exact points in time.
time_activated
between_moment '2018' => '2018-12-31T23:59:59' => execute_logic { print "This is 2018..." };
As with before_moments
statements can be combined with before_moment
, after_moment
and between_moment
with no limit.
execute_logic
Exists for the sole reason of verbosity. Accepts a single parameters that must be a subroutine or anonymous code block.
execute_logic { print "This is a verbose way of saying that this will be executed!" };
PRIVATES
_spawn_dt
_spawn_dt
is a private function defined in hopes that additional date formats can be used to define points in time.
DIAGNOSTICS
- time_activated
-
(F) time_activated() encountered an unexpected argument...
time_activated is not followed by either after_moment, before_moment or between_moments
time_activated wierd_sub(); #<- Plain weird but it could somehow happen
- after_moment before_moment between_moments
-
(F) Useless bare after_moment() (F) Useless bare before_moment() (F) Useless bare between_moments()
Use of xxxxx() with no time_activated before it. Generally the result of a ; instead of a ,.
time_activated after_moment '2018' {}; #<- mind the ; before_moment '2018' {}; #<- This one triggers a 'Useless bare before()' since it is not part of the time_activated call
BUGS AND LIMITATIONS
No known bugs, but you cannot have this syntax. Some , and/or => required:
time_activated
before_moment '2016-09-24' {}
after_moment '2016-10-24' {};
DEPENDENCIES
DateTime, DateTime::Format::ISO8601, Carp, Exporter, Sub::Name.
INCOMPATIBILITIES
Versions prior to 1.00 have collission with Moose. Naturally, Moose wins and compatibility breaks from 0.12 to 1.00.
Some old distributions that cannot set dates beyond 2038 fail some tests.
SEE ALSO
- Try::Tiny
-
A non related module that became the inspiration for Time::Activated.
VERSION CONTROL
http://github.com/gbarco/Time-Activated/
SUPPORT
Bugs may be submitted through the RT bug tracker (or bug-Time-Activated@rt.cpan.org).
AUTHOR
Gonzalo Barco <gbarco uy at gmail.com, no spaces>
LICENSE AND COPYRIGHT
Copyright 2016 Gonzalo Barco.
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 367:
You forgot a '=back' before '=head1'