NAME
Time::Activated - Syntactic sugar over time activated code supporting DateTime and ISO8601 (a.k.a. "Javascript dates").
VERSION
Version 0.10
SYNOPSIS
use Time::Activated;
# simple statements
time_activated after '1985-01-01T00:00:00', execute { print "A new feature has been activeted beginning Jan 1st 1985!" };
time_activated before '1986-12-31T00:00:00', execute { print "Support for this feature ends by 1986!" };
time_activated before '2000', execute { print "Let's dance like its 1999!" };
time_activated between '2016-01-01T00:00:00', '2016-12-31T23:59:59', execute { print "Business logic exception for 2016!" };
# combined statements a la try {} catch {} by Try::Tiny (tm)
time_activated
after '1985-01T00:00:00-03:00', execute { print "New business logic!" }, # <-- Gotcha! it is a ,
before '1986-12-31T00:00:00-03:00', execute { print "Old business logic!" };
# elements get evaluated in order
time_activated
before '1986-12-31T00:00:00-03:00', execute { print "Old business logic!" }, # <-- Switch that ;
after '1985-01-01T00:00:00-03:00', execute { print "New business logic!" }; # <-- Switch that ,
# all overlapping allowed, all matching gets executed
time_activated
after '2018', execute { print "This is from 2018-01-01 and on." },
after '2018-06-01', execute { print "This is from 2018-06-01 and on only, but on top of what we do after 2018-01-01." };
# FANCY and... cof... recommended syntax...
time_activated
after '2018' => execute { print "Welcome to new business process for 2018!" },
after '2019' => execute { 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 $dt => execute { 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.
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
, before
, between
. after
, accepts a parameters representing a point in time at and after which the execute statement will be executed. before
, accepts a parameters representing a point in time before, but not including, which the execute statement will be executed. between
, accepts two parameters representing a range in time between, both limits included, which the execute statement will be executed.
"WHEN"
Is either a DateTime object or a scalar representing a iso8601 (a.k.a. Javascript date)
Expension 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 '1999-12-31T23:00:00-01:00' => execute { print('Matches from 2000-01-01T00:00:00 GMT!') },
after '2000-01-01T00:00:00+01:00' => execute { 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 SOME_DATE => execute { print "Before!" },
after 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 '2001' => execute \&my_great_new_feature; #No parameters can be passed with references...
time_activated
after '2000' => execute { print 'Y2K ready!' },
after '2001' => execute (\&my_great_new_feature), #References with multilines need ()
after '2002' => execute { &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 PROCESS_X_CUTOVER_DATE => execute { &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 '1985-01-01T00:00:00-03:00' => execute { pass('Basic after') }; # this gets executed
Test::MockTime::set_absolute_time('1984-05-27T00:00:00Z');
time_activated after '1985-01-01T00:00:00-03:00' => execute { fail('Basic after') }; # this does not get executed
IMPLEMENTATION
time_activated
time_activated
is both the syntactical placeholder for gramar in Time::Activated
and the internal implementation of the modules functionality.
Syntactically the structure is like so (note the ','s and ';'):
time_activated
after ..., execute ...,
before ..., execute ...,
between ..., ... execute ...;
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 ... => execute ...,
before ... => execute ...,
between ... => ... => execute ...; #Given. This does not look so fancy but more into the weird side...
before
before
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 '2018', execute { 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 '2018' => execute { print "We are awaiting for 1/1/2018..." };
A fancy way to combine before statements.
time_activated
before '2018' => execute { print "We are awaiting for 1/1/2018..." },
before '2019' => execute { print "Not quite there for 1/1/2019..." };
after
after
defines a point in time after including the exact point in time which code is executed.
time_activated
after '2018' => execute { print "Wea are either at 1/1/2018 or after it..." };
As with before
statements can be combined with before
, after
and between
with no limit.
between
between
defines two points in time between which code is executes including both exact points in time.
time_activated
between '2018' => '2018-12-31T23:59:59' => execute { print "This is 2018..." };
As with before
statements can be combined with before
, after
and between
with no limit.
execute
Exists for the sole reason of verbosity. Accepts a single parameters that must be a subroutine or anonymous code block.
execute { print "This is a verbose way of saying that this will be executed!" };
INTERNALS
_spawn_dt
_spawn_dt
is a private function defined in hopes that additional date formats can be used to define points in time. Currently supported formats for all date time.
CAVEATS
You cannot have this syntax, some , and/or => required:
time_activated
before '2016-09-24' {}
after '2016-10-24' {};
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).
AUTHORS
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.