Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
Data::Range::Compare::UserbContributedePerlmDocumeCookbook::Recipe_DateTime(3)

NAME
       Data::Range::Compare::Cookbook::Recipe_DateTime - DateTime Range	HOWTO

SYNOPSIS
	 use DateTime;
	 use Data::Range::Compare;

	my @vpn_a=
	(
	  # start
	  DateTime->new(qw(year	2010 month 01 day 02 hour 10 minute 01 second 59))
	  ,
	  # end
	  DateTime->new(qw(year	2010 month 01 day 02 hour 10 minute 05 second 47))
	  ,

	  # start
	  DateTime->new(qw(year	2010 month 05 day 02 hour 07 minute 41 second 32))
	  ,
	  # end
	  DateTime->new(qw(year	2010 month 05 day 02 hour 08 minute 00 second 16))
	 );

	 my @vpn_b= (
	  # start
	  DateTime->new(qw(year	2010 month 05 day 02 hour 07 minute 41 second 32))
	  ,
	  # end
	  DateTime->new(qw(year	2010 month 05 day 02 hour 07 minute 58 second 13))
	  ,

	  # start
	  DateTime->new(qw(year	2010 month 01 day 02 hour 10 minute 03 second 59))
	  ,
	  # end
	  DateTime->new(qw(year	2010 month 01 day 02 hour 10 minute 04 second 37))
	 );

	 my @vpn_c=
	 (
	   DateTime->new(qw(year 2010 month 01 day 02 hour 10 minute 03	second 59))
	   ,
	   DateTime->new(qw(year 2010 month 01 day 02 hour 10 minute  04 second	37))

	   ,
	   DateTime->new(qw(year 2010 month 05 day 02 hour 07 minute 41	second 32))
	   ,
	   DateTime->new(qw(year 2010 month 05 day 02 hour 07 minute 58	second 13))

	   ,
	   DateTime->new(qw(year 2010 month 05 day 02 hour 07 minute 59	second 07))
	   ,
	   DateTime->new(qw(year 2010 month 05 day 02 hour 08 minute 00	second 16))

	   ,
	   DateTime->new(qw(year 2010 month 06 day 18 hour 10 minute 58	second 21))
	   ,
	   DateTime->new(qw(year 2010 month 06 day 18 hour 22 minute 06	second 55))
	 );

	 my %helper;

	 # create a simple function to handle comparing	dates
	 sub cmp_values	{ DateTime->compare( $_[0],$_[1] ) }

	 # Now set cmp_values in %helper
	 $helper{cmp_values}=\&cmp_values;

	 # create a simple function to calculate the next second
	 sub add_one { $_[0]->clone->add(seconds=>1) }

	 # Now set add_one in %helper
	 $helper{add_one}=\&add_one;

	 # create a simple function to calculate the previous second
	 sub sub_one { $_[0]->clone->subtract(seconds=>1) }

	 # quick and dirty formatting tool
	 sub format_range ($) {
	   my $s=$_[0];
	   join	' - '
	     ,$s->range_start->strftime('%F %T')
	     ,$s->range_end->strftime('%F %T')
	 }

	 # load	the outage timestamps and output a little info
	 my @parsed;
	 my @vpn_name=qw(vpn_a vpn_b vpn_c);
	 foreach my $outages (\@vpn_a,\@vpn_b,\@vpn_c) {
	   my $id=shift	@vpn_name;
	   my $row=[];
	   push	@parsed,$row;
	   print "\nVPN_ID $id\n";
	   while(my ($dt_start,$dt_end)=splice(@$outages,0,2)) {
	     my	$range=Data::Range::Compare->new(\%helper,$dt_start,$dt_end);
	     print format_range($range),"\n";
	     push @$row,$range;
	   }
	 }

	 # now compare our outages
	 my $sub=Data::Range::Compare->range_compare(\%helper,\@parsed);

	 while(my ($vpn_a,$vpn_b,$vpn_c)=$sub->()) {
	   next	unless
	     !$vpn_a->missing
	      &&
	     !$vpn_b->missing
	      &&
	     !$vpn_c->missing;
	   my $common=Data::Range::Compare->get_common_range(
	     \%helper
	     ,[$vpn_a,$vpn_c,$vpn_b]
	   );

	   my $common=Data::Range::Compare->get_common_range(
	     \%helper
	     ,[$vpn_a,$vpn_c,$vpn_b]
	   );

	   print "\nCommon outage range: "
	     ,format_range($common)
	     ,"\n"
	     ,"Total Downtime: Months: $outage->{months}"
	     ,"	Days: $outage->{days} Minutes: $outage->{minutes}"
	     ,"	Seconds: $outage->{seconds}\n"
	     ,'vpn_a '
	     ,format_range($vpn_a)
	     ,'	'
	     ,($vpn_a->missing ? 'up' :	'down')
	     ,"\n"
	     ,'vpn_b '
	     ,format_range($vpn_b)
	     ,'	'
	     ,($vpn_b->missing ? 'up' :	'down')
	     ,"\n"

	     ,'vpn_c '
	     ,format_range($vpn_c)
	     ,'	'
	     ,($vpn_c->missing ? 'up' :	'down')
	     ,"\n";
	 }

       Output

	 VPN_ID	vpn_a
	 2010-01-02 10:01:59 - 2010-01-02 10:05:47
	 2010-05-02 07:41:32 - 2010-05-02 08:00:16

	 VPN_ID	vpn_b
	 2010-05-02 07:41:32 - 2010-05-02 07:58:13
	 2010-01-02 10:03:59 - 2010-01-02 10:04:37

	 VPN_ID	vpn_c
	 2010-01-02 10:03:59 - 2010-01-02 10:04:37
	 2010-05-02 07:41:32 - 2010-05-02 07:58:13
	 2010-05-02 07:59:07 - 2010-05-02 08:00:16
	 2010-06-18 10:58:21 - 2010-06-18 22:06:55

	Common outage range: 2010-01-02	10:03:59 - 2010-01-02 10:04:37
	Total Downtime:	Months:	0 Days:	0 Minutes: 0 Seconds: 38
	vpn_a 2010-01-02 10:01:59 - 2010-01-02 10:05:47	down
	vpn_b 2010-01-02 10:03:59 - 2010-01-02 10:04:37	down
	vpn_c 2010-01-02 10:03:59 - 2010-01-02 10:04:37	down

	Common outage range: 2010-05-02	07:41:32 - 2010-05-02 07:58:13
	Total Downtime:	Months:	0 Days:	0 Minutes: 16 Seconds: 41
	vpn_a 2010-05-02 07:41:32 - 2010-05-02 08:00:16	down
	vpn_b 2010-05-02 07:41:32 - 2010-05-02 07:58:13	down
	vpn_c 2010-05-02 07:41:32 - 2010-05-02 07:58:13	down

DESCRIPTION
       This Recipe provides an example based on	DateTime object	manipulation.

       Lets say	we have	a bank with 3 vpns to its data center.	When all of
       the vpns	are off	line the bank itself is	unable to process customer
       transactions.  This example shows how to	calculate the exact time the
       bank is completely disconnected from the	data center and	when it	comes
       back online.

Ingredients
       This example relies on DateTime.

   Creating %helper
       Data::Range::Compare relies on %helper to do its	internal work.	This
       section explains	how to populate	%helper	to work	with DateTime.

       Create a	hash %helper.

       Example

	 my %helper

       o   Creating the	"cmp_values" callback

	   "cmp_values"	represents comparing 2 objects in the standard cmp or
	   <=> way; lucky for us DateTime provides a comparative interface.

	   Example

	     # create a	simple function	to handle comparing dates
	     sub cmp_values { DateTime->compare( $_[0],$_[1] ) }

	     # Now set cmp_values in %helper
	     $helper{cmp_values}=\&cmp_values

       o   Creating the	"add_one" callback

	   "add_one" represents	the next value:	 With that in mind we have to
	   decide if our next increment	is just	adding 1 or moving to the next
	   Year, Month,	Day, Hour, Min,	Sec etc.

	   In our example we will be using the concept of next second.	This
	   makes "add_one" a fairly simple function to implement.

	   Example

	     # create a	simple function	to calculate the next second
	     sub add_one { $_[0]->clone->add(seconds=>1) }

	     # Now set add_one in %helper
	     $helper{add_one}=\&add_one

       o   Creating the	"sub_one" callback

	   "add_one" represents	the previous value.  With that in mind we have
	   to decide if	our next decrement is just removing 1 or moving	to the
	   previous Year, Month, Day, Hour, Min, Sec etc.

	   In our example we will be using the concept of previous second.
	   This	makes "sub_one"	a fairly simple	function to implement.

	   Example

	     # create a	simple function	to calculate the previous second
	     sub sub_one { $_[0]->clone->subtract(seconds=>1) }

	     # Now set sub_one in our %helper
	     $helper{sub_one}=\&sub_one

   Creating our	Objects	to Compare
       The constructor call to "new
       Data::Range::Compare(\%helper,$start,$end)" represents the creation of
       a new instance.	Although this may be an	over generalized concept, what
       $start and $end can contain is not.

       In this example we are creating our Date::Range::Compare	Objects	with a
       $start and $end value made from 2 DateTime objects.  Prior examples
       used letters of the alphabet, and the default values are	integers, but
       in this case we are doing something special; we are creating an object
       that represents a range based on	other objects: DateTime	in particular.

       Lets examine the	loop that pulls	the vpn	arrays apart.

       o   my @parsed;

	   Not to be overlooked, but this list will contain all	of the data we
	   intend to compare.  Once a range has	been created in	our loop we
	   push	our range onto the selective anonymous hash.

	     foreach my	$outages (\@vpn_a,\@vpn_b,\@vpn_c) {
	       my $row=[];
	       push @parsed,$row;

	   Since our input data	sets are just flat lists, we just need to pull
	   out our ranges in pairs.

	       while(my	($dt_start,$dt_end)=splice(@$outages,0,2)) {
		 my $range=Data::Range::Compare->new(\%helper,$dt_start,$dt_end);
		 push @$row,$range;

   Calculating our outages
       Now we really get down to the details of	the outage.  So	lets examine
       this code a little further.

       o   my $sub=Data::Range::Compare->range_compare(\%helper,\@parsed);

	   This	is where the process for comparison starts.  We	created	the
	   object that will compare and	iterate	through	our @parsed ranges.

	   Ok, that said let's take a look at the logic	of our while loop.

	     while(my ($vpn_a,$vpn_b,$vpn_c)=$sub->()) {

	   If you look back at the foreach call	we made, you will notice our
	   iteration through each set of outage	related	data.  Each anonymous
	   array @parsed represents in order: @vpn_a @vpn_b @vpn_c.

	   Our call to $sub->()	is only	slightly different than	the data in
	   @parsed.  The variables in $vpn_a,$vpn_b,$vpn_c may not even	exist
	   in @parsed and that's because they represent	ranges not found in a
	   given list data source which	brings us to the ->missing checks.

	     next unless
	       !$vpn_a->missing
		&&
	       !$vpn_b->missing
		&&
	       !$vpn_c->missing;

	   This	is a some what awkward way of looking at the data, but in
	   reality it makes sense.  We want to skip rows when some vpns	are
	   online.  The	reason for this	is simple:  when ranges	are missing
	   they	represent that vpn being online.

       o   my $common=Data::Range::Compare->get_common_range( \%helper
	   ,[$vpn_a,$vpn_c,$vpn_b] );

	   We are using	Data::Range::Compare->get_common_range to calculate
	   the smallest	common range given all of our current ranges.  We only
	   care	about the shared down time from	every single range.

       o   my $outage=$common->range_end->subtract_datetime(
	   $common->range_start	); This	is a feature of	DateTime itself	and we
	   used	it to fetch the	duration of the	outage.

	   The final operation in our loop simply outputs all the data we
	   wanted to see.

	     print "\nCommon outage range: "
	       ,format_range($common)
	       ,"\n"
	       ,"Total Downtime: Months: $outage->{months}"
	       ," Days:	$outage->{days}	Minutes: $outage->{minutes}"
	       ," Seconds: $outage->{seconds}\n"
	       ,'vpn_a '
	       ,format_range($vpn_a)
	       ,' '
	       ,($vpn_a->missing ? 'up'	: 'down')
	       ,"\n"
	       ,'vpn_b '
	       ,format_range($vpn_b)
	       ,' '
	       ,($vpn_b->missing ? 'up'	: 'down')
	       ,"\n"

	       ,'vpn_c '
	       ,format_range($vpn_c)
	       ,' '
	       ,($vpn_c->missing ? 'up'	: 'down')
	       ,"\n";

AUTHOR
       Michael Shipper

COPYRIGHT
       Copyright 2010 Michael Shipper.	All rights reserved.

       This library is free software; you can redistribute it and/or modify it
       under the same terms as Perl itself.

SEE ALSO
       Data::Range::Compare::Cookbook

perl v5.32.1		    Data::Range::Compare::Cookbook::Recipe_DateTime(3)

NAME | SYNOPSIS | DESCRIPTION | Ingredients | AUTHOR | COPYRIGHT | SEE ALSO

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=Data::Range::Compare::Cookbook::Recipe_DateTime&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help