line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Time::Activated; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
## no critic (ProhibitSubroutinePrototypes, ProhibitAutomaticExportation) |
4
|
|
|
|
|
|
|
|
5
|
10
|
|
|
10
|
|
927137
|
use strict; |
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
279
|
|
6
|
10
|
|
|
10
|
|
41
|
use warnings; |
|
10
|
|
|
|
|
10
|
|
|
10
|
|
|
|
|
239
|
|
7
|
|
|
|
|
|
|
|
8
|
10
|
|
|
10
|
|
148
|
use 5.8.8; |
|
10
|
|
|
|
|
29
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=pod |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=encoding UTF-8 |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=cut |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 NAME |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
Time::Activated - Syntactic sugar over time activated code supporting DateTime and ISO8601 (a.k.a. "Javascript dates"). |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=head1 VERSION |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
Version 1.01 |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=cut |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
our $VERSION = 1.01; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=head1 SYNOPSIS |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
use Time::Activated; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# simple statements |
33
|
|
|
|
|
|
|
time_activated after_moment '1985-01-01T00:00:00' => execute_logic { print "New feature beginning Jan 1st 1985!" }; |
34
|
|
|
|
|
|
|
time_activated before_moment '1986-12-31T00:00:00' => execute_logic { print "This feature ends by 1986!" }; |
35
|
|
|
|
|
|
|
time_activated before_moment '2000' => execute_logic { print "Let's dance like its 1999!" }; |
36
|
|
|
|
|
|
|
time_activated |
37
|
|
|
|
|
|
|
between_moments '2016-01-01T00:00:00' => '2016-12-31T23:59:59' => |
38
|
|
|
|
|
|
|
execute_logic { print "Business logic exception for 2016!" }; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# combined statements a la try {} catch {} by Try::Tiny (tm) |
41
|
|
|
|
|
|
|
time_activated |
42
|
|
|
|
|
|
|
after_moment '1985-01T00:00:00-03:00' => execute_logic { print "New business logic!" }, # <-- Gotcha! it is a , |
43
|
|
|
|
|
|
|
before_moment '1986-12-31T00:00:00-03:00' => execute_logic { print "Old business logic!" }; |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# elements get evaluated in order |
46
|
|
|
|
|
|
|
time_activated |
47
|
|
|
|
|
|
|
before_moment '1986-12-31T00:00:00-03:00' => execute_logic { print "Old business logic!" }, # <-- Switch that ; |
48
|
|
|
|
|
|
|
after_moment '1985-01-01T00:00:00-03:00' => execute_logic { print "New business logic!" }; # <-- Switch that , |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# overlapping allowed, all matching items get executed |
51
|
|
|
|
|
|
|
time_activated |
52
|
|
|
|
|
|
|
after_moment '2018', execute_logic { print "This is from 2018-01-01 and on." }, |
53
|
|
|
|
|
|
|
after_moment '2018-06-01', execute_logic { print "This is from 2018-06-01 and on. On top of the previuos." }; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# Alternate syntax |
56
|
|
|
|
|
|
|
time_activated |
57
|
|
|
|
|
|
|
after_moment '2018', execute_logic { print "Welcome to new business process for 2018!" }, #=> is a , |
58
|
|
|
|
|
|
|
after_moment '2019', execute_logic { print "This is added on top of 2018 processes for 2019!" }; |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# DateTime objects can be used to define points in time |
61
|
|
|
|
|
|
|
my $dt = DateTime->new(year=>2018, month=>10, day=>16); |
62
|
|
|
|
|
|
|
time_activated after_moment $dt => execute_logic { print "This happens after 2018-10-16!" }; |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=head1 DESCRIPTION |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
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 |
67
|
|
|
|
|
|
|
integrated and tested in advance. |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
You can use Time::Activated C<before>, C<after> and C<between> to state which parts of code will be executed on certain dates due to changing business rules, |
70
|
|
|
|
|
|
|
programmed web service changes in endpoints/contracts or other time related events. |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=head1 USAGE |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=cut |
77
|
|
|
|
|
|
|
|
78
|
10
|
|
|
10
|
|
36
|
use Exporter 5.57 'import'; |
|
10
|
|
|
|
|
152
|
|
|
10
|
|
|
|
|
725
|
|
79
|
|
|
|
|
|
|
our @EXPORT = our @EXPORT_OK = qw(time_activated before_moment after_moment between_moments execute_logic); |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=head1 EXPORTS |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
By default Time::Activated exports C<time_activated>, C<before>, C<after>, C<between> and C<execute>. |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
If you need to rename the C<time_activated>, C<after>, C<before>, C<between> or C<executye> keyword consider using L<Sub::Import|Sub::Import> to |
86
|
|
|
|
|
|
|
get L<Sub::Exporter|Sub::Exporter>'s flexibility. |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
If automatic exporting sound nasty: use Time::Activated qw(); |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=head1 SYNTAX |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
time_activated "CONDITION" "WHEN" "WHAT" |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
=head2 "CONDITION" |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
Can be any of C<after_moment>, C<before_moment>, C<between_moments>. |
97
|
|
|
|
|
|
|
C<after_moment>, accepts a parameters representing a point in time B<at and after> which the execute_logic statement will be executed. |
98
|
|
|
|
|
|
|
C<before_moment>, accepts a parameters representing a point in time B<before, but not including>, which the execute_logic statement will be executed. |
99
|
|
|
|
|
|
|
C<between_moments>, accepts two parameters representing a range in time B<between, both limits included>, which the execute_logic statement will be executed. |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=head2 "WHEN" |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
Is either a DateTime object or a scalar representing a iso8601 (a.k.a. Javascript date) |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
Expansion is supported so '2000', '2000-01', '2000-01-01' and '2000-01-01T00:00' all are equivalents to '2000-01-01T00:00:00'. |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
Timezones are supported and honored. Thus: |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
time_activated |
110
|
|
|
|
|
|
|
after_moment '1999-12-31T23:00:00-01:00' => execute_logic { print('Matches from 2000-01-01T00:00:00 GMT!') }, |
111
|
|
|
|
|
|
|
after_moment '2000-01-01T00:00:00+01:00' => execute_logic { print('Matches from 1999-01-01T23:00:00 GMT!') }; |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
C<after> includes the exact time which is used as parameter, C<before> does not. |
114
|
|
|
|
|
|
|
Thus using C<after> and C<before> with the same time parameter ensures that only one statement gets executed. |
115
|
|
|
|
|
|
|
i.e.: |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
time_activated |
118
|
|
|
|
|
|
|
before_moment SOME_DATE => execute { print "Before!" }, |
119
|
|
|
|
|
|
|
after_moment SOME_DATE => execute { print "After!" }; |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=head2 "WHAT" |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
Is either an anonymous code block or a reference to subroutine |
125
|
|
|
|
|
|
|
Code that will be executed on a given conditions in many ways: |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
time_activated |
128
|
|
|
|
|
|
|
after_moment '2001' => execute_logic \&my_great_new_feature; #No parameters can be passed with references... |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
time_activated |
131
|
|
|
|
|
|
|
after_moment '2000' => execute_logic { print 'Y2K ready!' }, |
132
|
|
|
|
|
|
|
after_moment '2001' => execute_logic (\&my_great_new_feature), #References with multilines need () |
133
|
|
|
|
|
|
|
after_moment '2002' => execute_logic { &my_great_new_feature("We need parameters by 2002")}; |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=head2 CONSTANTS |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
It is cool to use constants documenting both time and intent. |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
use constants PROCESS_X_CUTOVER_DATE => '2017-01-01T00:00:00'; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
time_activated after_moment PROCESS_X_CUTOVER_DATE => execute_logic { &new_business_process($some_state) }; |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=cut |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=head1 TESTING |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
L<Test::MockTime|Test::MockTime> is your friend. |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
use Test::More tests => 1; |
150
|
|
|
|
|
|
|
use Time::Activated; |
151
|
|
|
|
|
|
|
use Test::MockTime; |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
Test::MockTime::set_absolute_time('1986-05-27T00:00:00Z'); |
154
|
|
|
|
|
|
|
time_activated after_moment '1985-01-01T00:00:00-03:00' => execute_logic { pass('Basic after') }; # this gets executed |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
Test::MockTime::set_absolute_time('1984-05-27T00:00:00Z'); |
157
|
|
|
|
|
|
|
time_activated after_moment '1985-01-01T00:00:00-03:00' => execute_logic { fail('Basic after') }; # this does not get executed |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=cut |
160
|
|
|
|
|
|
|
|
161
|
10
|
|
|
10
|
|
65
|
use Carp; |
|
10
|
|
|
|
|
26
|
|
|
10
|
|
|
|
|
787
|
|
162
|
|
|
|
|
|
|
$Carp::Internal{ __PACKAGE__ }++; |
163
|
|
|
|
|
|
|
|
164
|
10
|
|
|
10
|
|
4135
|
use Sub::Name 0.08; |
|
10
|
|
|
|
|
4806
|
|
|
10
|
|
|
|
|
525
|
|
165
|
10
|
|
|
10
|
|
8088
|
use DateTime; |
|
10
|
|
|
|
|
3533943
|
|
|
10
|
|
|
|
|
500
|
|
166
|
10
|
|
|
10
|
|
6714
|
use DateTime::Format::ISO8601; |
|
10
|
|
|
|
|
405729
|
|
|
10
|
|
|
|
|
6449
|
|
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=head1 SUBROUTINES/METHODS |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=head2 time_activated |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
C<time_activated> is both the syntactical placeholder for grammar in C<Time::Activated> and the internal implementation of the modules functionality. |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
Syntactically the structure is like so (note the ','s and ';'): |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
time_activated |
177
|
|
|
|
|
|
|
after_moment ..., execute_logic ..., |
178
|
|
|
|
|
|
|
before_moment ..., execute_logic ..., |
179
|
|
|
|
|
|
|
between_moments ..., ... execute_logic ...; |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
Alternatively some can be changed for a => for a fancy syntax. This abuses anonymous hashes, some inteligent selections of prototypes (stolen from L<Try::Tiny|Try::Tiny>) and probably |
182
|
|
|
|
|
|
|
other clever perl-ish syntactical elements that escape my understanding. Note '=>'s, ','s and ';': |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
time_activated |
185
|
|
|
|
|
|
|
after_moment ... => execute_logic ..., |
186
|
|
|
|
|
|
|
before_moment ... => execute_logic ..., |
187
|
|
|
|
|
|
|
between_moments ... => ... => execute_logic ...; #Given. This does not look so fancy but more into the weird side... |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=cut |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# Blatantly stolen from Try::Tiny since it really makes sence and changing it produces headaches. |
192
|
|
|
|
|
|
|
# Need to prototype as @ not $$ because of the way Perl evaluates the prototype. |
193
|
|
|
|
|
|
|
# Keeping it at $$ means you only ever get 1 sub because we need to eval in a list |
194
|
|
|
|
|
|
|
# context & not a scalar one |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub time_activated (@) { |
197
|
49
|
|
|
49
|
1
|
104
|
my (@stanzas) = @_; |
198
|
49
|
|
|
|
|
67
|
my $activations = 0; |
199
|
|
|
|
|
|
|
|
200
|
49
|
|
|
|
|
138
|
my $now = DateTime->now(); |
201
|
49
|
|
|
|
|
10300
|
foreach my $stanza (@stanzas) { |
202
|
99
|
100
|
|
|
|
765
|
if (ref($stanza) eq 'Time::Activated::Before') { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
203
|
26
|
100
|
|
|
|
95
|
if ($now < $stanza->{before}) { |
204
|
16
|
|
|
|
|
1910
|
$stanza->{code}(); |
205
|
16
|
|
|
|
|
4510
|
$activations++; |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
} elsif (ref($stanza) eq 'Time::Activated::After') { |
208
|
41
|
100
|
|
|
|
385
|
if ($now >= $stanza->{after}) { |
209
|
33
|
|
|
|
|
4729
|
$stanza->{code}(); |
210
|
33
|
|
|
|
|
10362
|
$activations++; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
} elsif (ref($stanza) eq 'Time::Activated::Between') { |
213
|
32
|
100
|
|
|
|
125
|
if ($stanza->{after} > $stanza->{before}) { |
214
|
11
|
|
|
|
|
611
|
my $before = $stanza->{after}; |
215
|
11
|
|
|
|
|
18
|
$stanza->{after} = $stanza->{before}; |
216
|
11
|
|
|
|
|
14
|
$stanza->{before} = $before; |
217
|
|
|
|
|
|
|
} |
218
|
32
|
100
|
66
|
|
|
1207
|
if ($now >= $stanza->{after} && $now <= $stanza->{before}) { |
219
|
26
|
|
|
|
|
6594
|
$stanza->{code}(); |
220
|
26
|
|
|
|
|
7524
|
$activations++; |
221
|
|
|
|
|
|
|
}; |
222
|
|
|
|
|
|
|
} else { |
223
|
0
|
0
|
|
|
|
0
|
croak('time_activated() encountered an unexpected argument (' . ( defined $stanza ? $stanza : 'undef' ) . ') - perhaps a missing semi-colon?' ); |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
} |
226
|
49
|
|
|
|
|
2724
|
return $activations; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
=head2 before_moment |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
C<before_moment> defines a point in time before B<not including the exact point in time> which code is executed. |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
This does not happen before January 1st 2018 at 00:00 but does happen from that exact point in time and on. |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
time_activated |
236
|
|
|
|
|
|
|
before_moment '2018', execute_logic { print "We are awaiting for 1/1/2018..." }; |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
Another fancy way to say do not do that before January 1st 2018 at 00:00. |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
ime_activated |
241
|
|
|
|
|
|
|
before_moment '2018' => execute_logic { print "We are awaiting for 1/1/2018..." }; |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
A fancy way to combine before statements. |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
time_activated |
246
|
|
|
|
|
|
|
before_moment '2018' => execute_logic { print "We are awaiting for 1/1/2018..." }, |
247
|
|
|
|
|
|
|
before_moment '2019' => execute_logic { print "Not quite there for 1/1/2019..." }; |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=cut |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub before_moment ($$;@) { |
252
|
26
|
|
|
26
|
1
|
51
|
my ( $before, $block, @rest ) = @_; |
253
|
|
|
|
|
|
|
|
254
|
26
|
50
|
|
|
|
70
|
croak 'Useless bare before_moment()' unless wantarray; |
255
|
|
|
|
|
|
|
|
256
|
26
|
|
|
|
|
39
|
my $caller = caller; |
257
|
26
|
|
|
|
|
158
|
subname("${caller}::before_moment{...} " => $block); |
258
|
|
|
|
|
|
|
|
259
|
26
|
|
|
|
|
58
|
return (bless({before => _spawn_dt($before), code => $block},'Time::Activated::Before'), @rest); |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=head2 after_moment |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
C<after_moment> defines a point in time after B<including the exact point in time> which code is executed. |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
time_activated |
267
|
|
|
|
|
|
|
after_moment '2018' => execute { print "Wea are either at 1/1/2018 or after it..." }; |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
As with C<before_moment> statements can be combined with C<before_moment>, C<after_moment> and C<between_moments> with no limit. |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
=cut |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
sub after_moment ($$;@) { |
274
|
41
|
|
|
41
|
1
|
124
|
my ( $after, $block, @rest ) = @_; |
275
|
|
|
|
|
|
|
|
276
|
41
|
50
|
|
|
|
118
|
croak 'Useless bare after_moment()' unless wantarray; |
277
|
|
|
|
|
|
|
|
278
|
41
|
|
|
|
|
62
|
my $caller = caller; |
279
|
41
|
|
|
|
|
248
|
subname("${caller}::after _moment{...} " => $block); |
280
|
|
|
|
|
|
|
|
281
|
41
|
|
|
|
|
78
|
return (bless({after => _spawn_dt($after), code => $block},'Time::Activated::After'), @rest); |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=head2 between_moments |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
C<between_moments> defines two points in time between which code is executes B<including both exact points in time>. |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
time_activated |
289
|
|
|
|
|
|
|
between_moment '2018' => '2018-12-31T23:59:59' => execute_logic { print "This is 2018..." }; |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
As with C<before_moments> statements can be combined with C<before_moment>, C<after_moment> and C<between_moment> with no limit. |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=cut |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
sub between_moments ($$$;@) { |
296
|
32
|
|
|
32
|
1
|
107
|
my ( $after, $before, $block, @rest ) = @_; |
297
|
|
|
|
|
|
|
|
298
|
32
|
50
|
|
|
|
115
|
croak 'Useless bare between_moments()' unless wantarray; |
299
|
|
|
|
|
|
|
|
300
|
32
|
|
|
|
|
73
|
my $caller = caller; |
301
|
32
|
|
|
|
|
184
|
subname("${caller}::between_moments{...} " => $block); |
302
|
|
|
|
|
|
|
|
303
|
32
|
|
|
|
|
62
|
return (bless({before => _spawn_dt($before), after => _spawn_dt($after), code => $block},'Time::Activated::Between'), @rest); |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=head2 execute_logic |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
Exists for the sole reason of verbosity. |
309
|
|
|
|
|
|
|
Accepts a single parameters that must be a subroutine or anonymous code block. |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
execute_logic { print "This is a verbose way of saying that this will be executed!" }; |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=cut |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
sub execute_logic(&) { |
316
|
99
|
|
|
99
|
1
|
120931
|
my ($code) = @_; |
317
|
99
|
|
|
|
|
444
|
return $code; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=head2 PRIVATES |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=head3 _spawn_dt |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
C<_spawn_dt> is a private function defined in hopes that additional date formats can be used to define points in time. |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
=cut |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
sub _spawn_dt { |
329
|
131
|
|
|
131
|
|
166
|
my ($iso8601_or_datetime) = @_; |
330
|
|
|
|
|
|
|
|
331
|
131
|
100
|
66
|
|
|
791
|
my $dt = ref $iso8601_or_datetime && $iso8601_or_datetime->isa('DateTime') |
332
|
|
|
|
|
|
|
? $iso8601_or_datetime |
333
|
|
|
|
|
|
|
: DateTime::Format::ISO8601->parse_datetime($iso8601_or_datetime); |
334
|
|
|
|
|
|
|
|
335
|
131
|
|
|
|
|
46612
|
return $dt; |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
1; |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
__END__ |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=head1 DIAGNOSTICS |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
=over 4 |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
=item time_activated |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
(F) time_activated() encountered an unexpected argument... |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
time_activated is not followed by either after_moment, before_moment or between_moments |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
time_activated wierd_sub(); #<- Plain weird but it could somehow happen |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
=item after_moment before_moment between_moments |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
(F) Useless bare after_moment() |
357
|
|
|
|
|
|
|
(F) Useless bare before_moment() |
358
|
|
|
|
|
|
|
(F) Useless bare between_moments() |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
Use of xxxxx() with no time_activated before it. |
361
|
|
|
|
|
|
|
Generally the result of a ; instead of a ,. |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
time_activated |
364
|
|
|
|
|
|
|
after_moment '2018' {}; #<- mind the ; |
365
|
|
|
|
|
|
|
before_moment '2018' {}; #<- This one triggers a 'Useless bare before()' since it is not part of the time_activated call |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
=head1 BUGS AND LIMITATIONS |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
No known bugs, but you cannot have this syntax. |
370
|
|
|
|
|
|
|
Some , and/or => required: |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
time_activated |
373
|
|
|
|
|
|
|
before_moment '2016-09-24' {} |
374
|
|
|
|
|
|
|
after_moment '2016-10-24' {}; |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
=head1 DEPENDENCIES |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
L<DateTime|DateTime>, L<DateTime::Format::ISO8601|DateTime::Format::ISO8601>, L<Carp|Carp>, L<Exporter|Exporter>, L<Sub::Name|Sub::Name>. |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
=head1 INCOMPATIBILITIES |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
Versions prior to 1.00 have collission with Moose. |
383
|
|
|
|
|
|
|
Naturally, Moose wins and compatibility breaks from 0.12 to 1.00. |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
Some old distributions that cannot set dates beyond 2038 fail some tests. |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
=head1 SEE ALSO |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
=over 4 |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
=item L<Try::Tiny|Try::Tiny> |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
A non related module that became the inspiration for Time::Activated. |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
=back |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
=head1 VERSION CONTROL |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
L<http://github.com/gbarco/Time-Activated/> |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
=head1 SUPPORT |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Time-Activated> |
404
|
|
|
|
|
|
|
(or L<bug-Time-Activated@rt.cpan.org|mailto:bug-Time-Activated@rt.cpan.org>). |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
=head1 AUTHOR |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
=over 4 |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
=item * |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
Gonzalo Barco <gbarco uy at gmail.com, no spaces> |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
=back |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
Copyright 2016 Gonzalo Barco. |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
421
|
|
|
|
|
|
|
under the terms of either: the GNU General Public License as published |
422
|
|
|
|
|
|
|
by the Free Software Foundation; or the Artistic License. |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
See http://dev.perl.org/licenses/ for more information. |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
=cut |