1DateTime::Set(3) User Contributed Perl Documentation DateTime::Set(3)
2
3
4
6 DateTime::Set - Datetime sets and set math
7
9 use DateTime;
10 use DateTime::Set;
11
12 $date1 = DateTime->new( year => 2002, month => 3, day => 11 );
13 $set1 = DateTime::Set->from_datetimes( dates => [ $date1 ] );
14 # set1 = 2002-03-11
15
16 $date2 = DateTime->new( year => 2003, month => 4, day => 12 );
17 $set2 = DateTime::Set->from_datetimes( dates => [ $date1, $date2 ] );
18 # set2 = 2002-03-11, and 2003-04-12
19
20 $date3 = DateTime->new( year => 2003, month => 4, day => 1 );
21 print $set2->next( $date3 )->ymd; # 2003-04-12
22 print $set2->previous( $date3 )->ymd; # 2002-03-11
23 print $set2->current( $date3 )->ymd; # 2002-03-11
24 print $set2->closest( $date3 )->ymd; # 2003-04-12
25
26 # a 'monthly' recurrence:
27 $set = DateTime::Set->from_recurrence(
28 recurrence => sub {
29 return $_[0] if $_[0]->is_infinite;
30 return $_[0]->truncate( to => 'month' )->add( months => 1 )
31 },
32 span => $date_span1, # optional span
33 );
34
35 $set = $set1->union( $set2 ); # like "OR", "insert", "both"
36 $set = $set1->complement( $set2 ); # like "delete", "remove"
37 $set = $set1->intersection( $set2 ); # like "AND", "while"
38 $set = $set1->complement; # like "NOT", "negate", "invert"
39
40 if ( $set1->intersects( $set2 ) ) { ... # like "touches", "interferes"
41 if ( $set1->contains( $set2 ) ) { ... # like "is-fully-inside"
42
43 # data extraction
44 $date = $set1->min; # first date of the set
45 $date = $set1->max; # last date of the set
46
47 $iter = $set1->iterator;
48 while ( $dt = $iter->next ) {
49 print $dt->ymd;
50 };
51
53 DateTime::Set is a module for datetime sets. It can be used to handle
54 two different types of sets.
55
56 The first is a fixed set of predefined datetime objects. For example,
57 if we wanted to create a set of datetimes containing the birthdays of
58 people in our family.
59
60 The second type of set that it can handle is one based on the idea of a
61 recurrence, such as "every Wednesday", or "noon on the 15th day of
62 every month". This type of set can have fixed starting and ending
63 datetimes, but neither is required. So our "every Wednesday set" could
64 be "every Wednesday from the beginning of time until the end of time",
65 or "every Wednesday after 2003-03-05 until the end of time", or "every
66 Wednesday between 2003-03-05 and 2004-01-07".
67
69 * from_datetimes
70 Creates a new set from a list of datetimes.
71
72 $dates = DateTime::Set->from_datetimes( dates => [ $dt1, $dt2, $dt3 ] );
73
74 The datetimes can be objects from class "DateTime", or from a
75 "DateTime::Calendar::*" class.
76
77 "DateTime::Infinite::*" objects are not valid set members. How‐
78 ever, these datetimes are very useful as set boundaries.
79
80 * from_recurrence
81 Creates a new set specified via a "recurrence" callback.
82
83 $months = DateTime::Set->from_recurrence(
84 span => $dt_span_this_year, # optional span
85 recurrence => sub {
86 return $_[0]->truncate( to => 'month' )->add( months => 1 )
87 },
88 );
89
90 The "span" parameter is optional. It must be a "DateTime::Span"
91 object.
92
93 The span can also be specified using "begin" / "after" and "before"
94 / "end" parameters, as in the "DateTime::Span" constructor. In
95 this case, if there is a "span" parameter it will be ignored.
96
97 $months = DateTime::Set->from_recurrence(
98 after => $dt_now,
99 recurrence => sub {
100 return $_[0]->truncate( to => 'month' )->add( months => 1 );
101 },
102 );
103
104 The recurrence function will be passed a single parameter, a date‐
105 time object. The parameter can be an object from class "DateTime",
106 or from one of the "DateTime::Calendar::*" classes. The parameter
107 can also be a "DateTime::Infinite::Future" or a "DateTime::Infi‐
108 nite::Past" object.
109
110 The recurrence must return the next event after that object. There
111 is no guarantee as to what the returned object will be set to, only
112 that it will be greater than the object passed to the recurrence.
113 If there are no more datetimes after the given parameter, then the
114 recurrence function should return "DateTime::Infinite::Future".
115
116 It is ok to modify the parameter $_[0] inside the recurrence func‐
117 tion. There are no side-effects.
118
119 For example, if you wanted a recurrence that generated datetimes in
120 increments of 30 seconds, it would look like this:
121
122 sub every_30_seconds {
123 my $dt = shift;
124 if ( $dt->second < 30 ) {
125 return $dt->truncate( to => 'minute' )->add( seconds => 30 );
126 } else {
127 return $dt->truncate( to => 'minute' )->add( minutes => 1 );
128 }
129 }
130
131 Note that this recurrence takes leap seconds into account. You
132 should use datetime calendar methods whenever possible, in order to
133 avoid complicated arithmetic problems!
134
135 It is also possible to create a recurrence by specifying either or
136 both of 'next' and 'previous' callbacks.
137
138 The callbacks can return "DateTime::Infinite::Future" and "Date‐
139 Time::Infinite::Past" objects, in order to define bounded recur‐
140 rences. In this case, both 'next' and 'previous' callbacks must be
141 defined:
142
143 # "monthly from $dt until forever"
144
145 my $months = DateTime::Set->from_recurrence(
146 next => sub {
147 return $dt if $_[0] < $dt;
148 $_[0]->truncate( to => 'month' );
149 $_[0]->add( months => 1 );
150 return $_[0];
151 },
152 previous => sub {
153 my $param = $_[0]->clone;
154 $_[0]->truncate( to => 'month' );
155 $_[0]->subtract( months => 1 ) if $_[0] == $param;
156 return $_[0] if $_[0] >= $dt;
157 return DateTime::Infinite::Past->new;
158 },
159 );
160
161 Bounded recurrences are easier to write using "span" parameters.
162 See above.
163
164 See also "DateTime::Event::Recurrence" and the other "Date‐
165 Time::Event::*" factory modules for generating specialized recur‐
166 rences, such as sunrise and sunset times, and holidays.
167
168 * empty_set
169 Creates a new empty set.
170
171 $set = DateTime::Set->empty_set;
172 print "empty set" unless defined $set->max;
173
174 * clone
175 This object method returns a replica of the given object.
176
177 "clone" is useful if you want to apply a transformation to a set,
178 but you want to keep the previous value:
179
180 $set2 = $set1->clone;
181 $set2->add_duration( year => 1 ); # $set1 is unaltered
182
183 * add_duration( $duration )
184 This method adds the specified duration to every element of the
185 set.
186
187 $dt_dur = new DateTime::Duration( year => 1 );
188 $set->add_duration( $dt_dur );
189
190 The original set is modified. If you want to keep the old values
191 use:
192
193 $new_set = $set->clone->add_duration( $dt_dur );
194
195 * add
196 This method is syntactic sugar around the "add_duration()" method.
197
198 $meetings_2004 = $meetings_2003->clone->add( years => 1 );
199
200 * subtract_duration( $duration_object )
201 When given a "DateTime::Duration" object, this method simply calls
202 "invert()" on that object and passes that new duration to the
203 "add_duration" method.
204
205 * subtract( DateTime::Duration->new parameters )
206 Like "add()", this is syntactic sugar for the "subtract_duration()"
207 method.
208
209 * set_time_zone( $tz )
210 This method will attempt to apply the "set_time_zone" method to
211 every datetime in the set.
212
213 * set( locale => .. )
214 This method can be used to change the "locale" of a datetime set.
215
216 * min
217 * max
218 The first and last "DateTime" in the set. These methods may return
219 "undef" if the set is empty. It is also possible that these meth‐
220 ods may return a "DateTime::Infinite::Past" or "DateTime::Infi‐
221 nite::Future" object.
222
223 These methods return just a copy of the actual boundary value. If
224 you modify the result, the set will not be modified.
225
226 * span
227 Returns the total span of the set, as a "DateTime::Span" object.
228
229 * iterator / next / previous
230 These methods can be used to iterate over the datetimes in a set.
231
232 $iter = $set1->iterator;
233 while ( $dt = $iter->next ) {
234 print $dt->ymd;
235 }
236
237 # iterate backwards
238 $iter = $set1->iterator;
239 while ( $dt = $iter->previous ) {
240 print $dt->ymd;
241 }
242
243 The boundaries of the iterator can be limited by passing it a
244 "span" parameter. This should be a "DateTime::Span" object which
245 delimits the iterator's boundaries. Optionally, instead of passing
246 an object, you can pass any parameters that would work for one of
247 the "DateTime::Span" class's constructors, and an object will be
248 created for you.
249
250 Obviously, if the span you specify is not restricted both at the
251 start and end, then your iterator may iterate forever, depending on
252 the nature of your set. User beware!
253
254 The "next()" or "previous()" method will return "undef" when there
255 are no more datetimes in the iterator.
256
257 * as_list
258 Returns the set elements as a list of "DateTime" objects. Just as
259 with the "iterator()" method, the "as_list()" method can be limited
260 by a span.
261
262 my @dt = $set->as_list( span => $span );
263
264 Applying "as_list()" to a large recurrence set is a very expensive
265 operation, both in CPU time and in the memory used. If you really
266 need to extract elements from a large set, you can limit the set
267 with a shorter span:
268
269 my @short_list = $large_set->as_list( span => $short_span );
270
271 For infinite sets, "as_list()" will return "undef". Please note
272 that this is explicitly not an empty list, since an empty list is a
273 valid return value for empty sets!
274
275 * count
276 Returns a count of "DateTime" objects in the set. Just as with the
277 "iterator()" method, the "count()" method can be limited by a span.
278
279 defined( my $n = $set->count) or die "can't count";
280
281 my $n = $set->count( span => $span );
282 die "can't count" unless defined $n;
283
284 Applying "count()" to a large recurrence set is a very expensive
285 operation, both in CPU time and in the memory used. If you really
286 need to count elements from a large set, you can limit the set with
287 a shorter span:
288
289 my $count = $large_set->count( span => $short_span );
290
291 For infinite sets, "count()" will return "undef". Please note that
292 this is explicitly not a scalar zero, since a zero count is a valid
293 return value for empty sets!
294
295 * union
296 * intersection
297 * complement
298 These set operation methods can accept a "DateTime" list, a "Date‐
299 Time::Set", a "DateTime::Span", or a "DateTime::SpanSet" object as
300 an argument.
301
302 $set = $set1->union( $set2 ); # like "OR", "insert", "both"
303 $set = $set1->complement( $set2 ); # like "delete", "remove"
304 $set = $set1->intersection( $set2 ); # like "AND", "while"
305 $set = $set1->complement; # like "NOT", "negate", "invert"
306
307 The "union" of a "DateTime::Set" with a "DateTime::Span" or a
308 "DateTime::SpanSet" object returns a "DateTime::SpanSet" object.
309
310 If "complement" is called without any arguments, then the result is
311 a "DateTime::SpanSet" object representing the spans between each of
312 the set's elements. If complement is given an argument, then the
313 return value is a "DateTime::Set" object representing the set dif‐
314 ference between the sets.
315
316 All other operations will always return a "DateTime::Set".
317
318 * intersects
319 * contains
320 These set operations result in a boolean value.
321
322 if ( $set1->intersects( $set2 ) ) { ... # like "touches", "interferes"
323 if ( $set1->contains( $dt ) ) { ... # like "is-fully-inside"
324
325 These methods can accept a "DateTime" list, a "DateTime::Set", a
326 "DateTime::Span", or a "DateTime::SpanSet" object as an argument.
327
328 * previous
329 * next
330 * current
331 * closest
332 my $dt = $set->next( $dt );
333 my $dt = $set->previous( $dt );
334 my $dt = $set->current( $dt );
335 my $dt = $set->closest( $dt );
336
337 These methods are used to find a set member relative to a given
338 datetime.
339
340 The "current()" method returns $dt if $dt is an event, otherwise it
341 returns the previous event.
342
343 The "closest()" method returns $dt if $dt is an event, otherwise it
344 returns the closest event (previous or next).
345
346 All of these methods may return "undef" if there is no matching
347 datetime in the set.
348
349 These methods will try to set the returned value to the same time
350 zone as the argument, unless the argument has a 'floating' time
351 zone.
352
353 * map ( sub { ... } )
354 # example: remove the hour:minute:second information
355 $set = $set2->map(
356 sub {
357 return $_->truncate( to => day );
358 }
359 );
360
361 # example: postpone or antecipate events which
362 # match datetimes within another set
363 $set = $set2->map(
364 sub {
365 return $_->add( days => 1 ) while $holidays->contains( $_ );
366 }
367 );
368
369 This method is the "set" version of Perl "map".
370
371 It evaluates a subroutine for each element of the set (locally set‐
372 ting "$_" to each datetime) and returns the set composed of the
373 results of each such evaluation.
374
375 Like Perl "map", each element of the set may produce zero, one, or
376 more elements in the returned value.
377
378 Unlike Perl "map", changing "$_" does not change the original set.
379 This means that calling map in void context has no effect.
380
381 The callback subroutine may be called later in the program, due to
382 lazy evaluation. So don't count on subroutine side-effects. For
383 example, a "print" inside the subroutine may happen later than you
384 expect.
385
386 The callback return value is expected to be within the span of the
387 "previous" and the "next" element in the original set. This is a
388 limitation of the backtracking algorithm used in the "Set::Infi‐
389 nite" library.
390
391 For example: given the set "[ 2001, 2010, 2015 ]", the callback
392 result for the value 2010 is expected to be within the span "[ 2001
393 .. 2015 ]".
394
395 * grep ( sub { ... } )
396 # example: filter out any sundays
397 $set = $set2->grep(
398 sub {
399 return ( $_->day_of_week != 7 );
400 }
401 );
402
403 This method is the "set" version of Perl "grep".
404
405 It evaluates a subroutine for each element of the set (locally set‐
406 ting "$_" to each datetime) and returns the set consisting of those
407 elements for which the expression evaluated to true.
408
409 Unlike Perl "grep", changing "$_" does not change the original set.
410 This means that calling grep in void context has no effect.
411
412 Changing "$_" does change the resulting set.
413
414 The callback subroutine may be called later in the program, due to
415 lazy evaluation. So don't count on subroutine side-effects. For
416 example, a "print" inside the subroutine may happen later than you
417 expect.
418
419 * iterate ( sub { ... } )
420 deprecated method - please use "map" or "grep" instead.
421
423 Support is offered through the "datetime@perl.org" mailing list.
424
425 Please report bugs using rt.cpan.org
426
428 Flavio Soibelmann Glock <fglock@pucrs.br>
429
430 The API was developed together with Dave Rolsky and the DateTime Commu‐
431 nity.
432
434 Copyright (c) 2003, 2004 Flavio Soibelmann Glock. All rights reserved.
435 This program is free software; you can distribute it and/or modify it
436 under the same terms as Perl itself.
437
438 The full text of the license can be found in the LICENSE file included
439 with this module.
440
442 Set::Infinite
443
444 For details on the Perl DateTime Suite project please see <http://date‐
445 time.perl.org>.
446
447
448
449perl v5.8.8 2007-04-17 DateTime::Set(3)