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.