Rounding Date/Time

Rounding Date/Time

am 02.05.2011 18:46:42 von matt

Have a date:

2011-05-02-16:40:51

Using this to get it:

$tm = gmtime;
$time_stamp = sprintf "%04d-%02d-%02d-%02d:%02d:%02d",
$tm->year + 1900, $tm->mon + 1, $tm->mday, $tm->hour, $tm->min, $tm->sec;
print "$time_stamp\n";

I need to round it to nearest 5 minute point.

2011-05-02-16:40:51

needs rounded like so.

2011-05-02-16:00:00
2011-05-02-16:45:00
2011-05-02-16:50:00
2011-05-02-16:55:00

My thought is a bunch of if statements but that seems ugly. Is there
a better/easier way?

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Rounding Date/Time

am 02.05.2011 19:01:06 von Uri Guttman

>>>>> "M" == Matt writes:

M> Have a date:
M> 2011-05-02-16:40:51

M> Using this to get it:

M> $tm = gmtime;
M> $time_stamp = sprintf "%04d-%02d-%02d-%02d:%02d:%02d",
M> $tm->year + 1900, $tm->mon + 1, $tm->mday, $tm->hour, $tm->min, $tm->sec;
M> print "$time_stamp\n";

use POSIX strftime for that. i have seen experienced hacker code not
using that call. it provides dozens of time format outputs including all
the common ones and several groups of them too. same format as the date
unix command (which just wraps this call).

M> I need to round it to nearest 5 minute point.

M> 2011-05-02-16:40:51

M> needs rounded like so.

M> 2011-05-02-16:00:00
M> 2011-05-02-16:45:00
M> 2011-05-02-16:50:00
M> 2011-05-02-16:55:00

M> My thought is a bunch of if statements but that seems ugly. Is there
M> a better/easier way?

just zero out the seconds and do a simple round operation on the
minutes. you can use sprintf for the rounding (many examples in the list
archives).

and you can still use strftime. just put gmtime into an array (no reason
to use 9 vars), zero out the seconds slot, round the minutes slot, pass
the array to strftime.

uri

--
Uri Guttman ------ uri@stemsystems.com -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Rounding Date/Time

am 02.05.2011 19:19:11 von Jim Gibson

On 5/2/11 Mon May 2, 2011 9:46 AM, "Matt" scribbled:

> Have a date:
>
> 2011-05-02-16:40:51
>
> Using this to get it:
>
> $tm = gmtime;
> $time_stamp = sprintf "%04d-%02d-%02d-%02d:%02d:%02d",
> $tm->year + 1900, $tm->mon + 1, $tm->mday, $tm->hour, $tm->min, $tm->sec;
> print "$time_stamp\n";

That program fragment does not run on my system:

"Can't locate object method "year" via package "Mon May 2 17:16:09 2011"
(perhaps you forgot to load "Mon May 2 17:16:09 2011"?) at matt1.pl line
8."

The standard gmtime returns a date/time string in scalar context. You are
apparently using some other gmtime method that returns a blessed object.

It is always better to post complete programs so that people trying to help
you know don't have to figure out what you are doing.


> I need to round it to nearest 5 minute point.
>
> 2011-05-02-16:40:51
>
> needs rounded like so.
>
> 2011-05-02-16:00:00
> 2011-05-02-16:45:00
> 2011-05-02-16:50:00
> 2011-05-02-16:55:00
>
> My thought is a bunch of if statements but that seems ugly. Is there
> a better/easier way?

Rounding of times is best done using a numerical representation of the time,
as provided by the time() builtin function. Round that value as needed and
then display it using component values. Here is a sample program:

#!/usr/local/bin/perl
use strict;
use warnings;

my $five_min = 5 * 60;

my $t = time;
my $t5min = int($five_min * (int( ($t/$five_min) + 0.5 )));

print "t=$t, t5min=$t5min\n";
my @gmt = gmtime($t);
my @gmt5min = gmtime($t5min);

print "gmt=@gmt\ngmt5min=@gmt5min\n";

my $time_stamp = sprintf "%04d-%02d-%02d-%02d:%02d:%02d",
($gmt[5] + 1900), ($gmt[4] + 1), $gmt[3], $gmt[2], $gmt[1], $gmt[0];

my $time_stamp5min = sprintf "%04d-%02d-%02d-%02d:%02d:%02d",
($gmt5min[5] + 1900), ($gmt5min[4] + 1), $gmt5min[3],
$gmt5min[2], $gmt5min[1], $gmt5min[0];

print " time stamp = $time_stamp\n";
print "time stamp 5 min = $time_stamp5min\n";


As Uri recommends, there are several good date/time modules to help you do
the display.



--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Rounding Date/Time

am 03.05.2011 13:10:28 von Rob Dixon

On 02/05/2011 17:46, Matt wrote:
> Have a date:
>
> 2011-05-02-16:40:51
>
> Using this to get it:
>
> $tm = gmtime;
> $time_stamp = sprintf "%04d-%02d-%02d-%02d:%02d:%02d",
> $tm->year + 1900, $tm->mon + 1, $tm->mday, $tm->hour, $tm->min, $tm->sec;
> print "$time_stamp\n";
>
> I need to round it to nearest 5 minute point.
>
> 2011-05-02-16:40:51
>
> needs rounded like so.
>
> 2011-05-02-16:00:00
> 2011-05-02-16:45:00
> 2011-05-02-16:50:00
> 2011-05-02-16:55:00
>
> My thought is a bunch of if statements but that seems ugly. Is there
> a better/easier way?

Hey Matt

It is a lot easier to round to the nearest five minutes while the time
is held in epoch seconds. Instead of letting gmtime() do an implicit
call to time(), you can do an explicit one, round the result, and pass
it to gmtime() for reformatting.

The code below shows my point.

HTH,

Rob


use strict;
use warnings;

use constant FIVE_MINS => 5 * 60;

my $t = time;
my $secs = $t % FIVE_MINS;
$t -= $secs;
$t += FIVE_MINS if $secs >= FIVE_MINS / 2;

my @time = reverse((gmtime($t))[0..5]); # Grab [ Y M D h m s ]
$time[0] += 1900; # Correct the year
$time[1] += 1; # And the month

printf "%04d-%02d-%02d-%02d:%02d:%02d", @time;

**OUTPUT**

2011-05-03-11:05:00

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Rounding Date/Time

am 03.05.2011 20:49:17 von derykus

On May 2, 9:46=A0am, lm7...@gmail.com (Matt) wrote:
> Have a date:
>
> 2011-05-02-16:40:51
>
> Using this to get it:
>
> $tm =3D gmtime;
> $time_stamp =3D sprintf "%04d-%02d-%02d-%02d:%02d:%02d",
> =A0$tm->year + 1900, $tm->mon + 1, $tm->mday, $tm->hour, $tm->min, $tm->s=
ec;
> print "$time_stamp\n";
>
> I need to round it to nearest 5 minute point.
>
> 2011-05-02-16:40:51
>
> needs rounded like so.
>
> 2011-05-02-16:00:00
> 2011-05-02-16:45:00
> 2011-05-02-16:50:00
> 2011-05-02-16:55:00
>
> My thought is a bunch of if statements but that seems ugly. =A0Is there
> a better/easier way?

Yet another way using the core module List::Util:

use Time::localtime;
use List::Util qw/reduce/;

my @rounded_5mins =3D grep { not $_ % 5 } 0..60;
my $curr_min =3D localtime->min;

my $round_min =3D reduce { $curr_min-$a < $b-$curr_min ? $a : $b }
@rounded_5mins;

etc...

--
Charles DeRykus


--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Rounding Date/Time

am 03.05.2011 20:54:55 von Shawn H Corey

On 11-05-03 02:49 PM, C.DeRykus wrote:
> my @rounded_5mins = grep { not $_ % 5 } 0..60;

my @rounded_5mins = map { $_ * 5 } 0..12;

# TIMTOWTDI


--
Just my 0.00000002 million dollars worth,
Shawn

Confusion is the first step of understanding.

Programming is as much about organization and communication
as it is about coding.

The secret to great software: Fail early & often.

Eliminate software piracy: use only FLOSS.

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Rounding Date/Time

am 03.05.2011 21:10:13 von derykus

On May 3, 11:54=A0am, shawnhco...@ncf.ca (Shawn H Corey) wrote:
> On 11-05-03 02:49 PM, C.DeRykus wrote:
>
> > my @rounded_5mins =3D grep { not $_ % 5 } 0..60;
>
> my @rounded_5mins =3D map { $_ * 5 } 0..12;
>
> # TIMTOWTDI
>

Make that: TIMTOWTDI++ # a much better way to do it

--
Charles DeRykus


--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Rounding Date/Time

am 04.05.2011 01:12:24 von Rob Dixon

On 03/05/2011 19:49, C.DeRykus wrote:
> On May 2, 9:46 am, lm7...@gmail.com (Matt) wrote:
>> Have a date:
>>
>> 2011-05-02-16:40:51
>>
>> Using this to get it:
>>
>> $tm = gmtime;
>> $time_stamp = sprintf "%04d-%02d-%02d-%02d:%02d:%02d",
>> $tm->year + 1900, $tm->mon + 1, $tm->mday, $tm->hour, $tm->min, $tm->sec;
>> print "$time_stamp\n";
>>
>> I need to round it to nearest 5 minute point.
>>
>> 2011-05-02-16:40:51
>>
>> needs rounded like so.
>>
>> 2011-05-02-16:00:00
>> 2011-05-02-16:45:00
>> 2011-05-02-16:50:00
>> 2011-05-02-16:55:00
>>
>> My thought is a bunch of if statements but that seems ugly. Is there
>> a better/easier way?
>
> Yet another way using the core module List::Util:
>
> use Time::localtime;
> use List::Util qw/reduce/;
>
> my @rounded_5mins = grep { not $_ % 5 } 0..60;
> my $curr_min = localtime->min;
>
> my $round_min = reduce { $curr_min-$a< $b-$curr_min ? $a : $b }
> @rounded_5mins;

Both this and Uri's earlier suggestion ignore the seconds field. I would
be surprised if it was acceptable to round 10:02:59
to 10:00:00 rather than 10:05:00.

Rob

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Rounding Date/Time

am 04.05.2011 19:14:26 von derykus

On May 3, 4:12=A0pm, rob.di...@gmx.com (Rob Dixon) wrote:
> On 03/05/2011 19:49, C.DeRykus wrote:
>
>
>
>
>
>
>
>
>
> > On May 2, 9:46 am, lm7...@gmail.com (Matt) wrote:
> >> Have a date:
>
> >> 2011-05-02-16:40:51
>
> >> Using this to get it:
>
> >> $tm =3D gmtime;
> >> $time_stamp =3D sprintf "%04d-%02d-%02d-%02d:%02d:%02d",
> >> =A0 $tm->year + 1900, $tm->mon + 1, $tm->mday, $tm->hour, $tm->min, $t=
m->sec;
> >> print "$time_stamp\n";
>
> >> I need to round it to nearest 5 minute point.
>
> >> 2011-05-02-16:40:51
>
> >> needs rounded like so.
>
> >> 2011-05-02-16:00:00
> >> 2011-05-02-16:45:00
> >> 2011-05-02-16:50:00
> >> 2011-05-02-16:55:00
>
> >> My thought is a bunch of if statements but that seems ugly. =A0Is ther=
e
> >> a better/easier way?
>
> > Yet another way using the core module List::Util:
>
> > use Time::localtime;
> > use List::Util qw/reduce/;
>
> > my @rounded_5mins =3D grep { not $_ % 5 } 0..60;
> > my $curr_min =3D localtime->min;
>
> > my $round_min =3D =A0reduce { $curr_min-$a< =A0$b-$curr_min ? $a : $b }
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 @rounde=
d_5mins;
>
> Both this and Uri's earlier suggestion ignore the seconds field. I would
> be surprised if it was acceptable to round 10:02:59
> to 10:00:00 rather than 10:05:00.
>

Depends on how precise the partition counts need to be...
maybe just determining the approx. spread of timestamps
in 5 min. increments suffices. And of course, if there's
some other criteria, maybe, even a biasing that causes
10:02:30 to fall into a 10:00:00 rather than a 10:05:00
slot, won't be acceptable either.

--
Charles DeRykus


--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Rounding Date/Time

am 05.05.2011 03:43:28 von Rob Dixon

On 04/05/2011 18:14, C.DeRykus wrote:
> On May 3, 4:12 pm, rob.di...@gmx.com (Rob Dixon) wrote:
>> On 03/05/2011 19:49, C.DeRykus wrote:
>>
>>> use Time::localtime;
>>> use List::Util qw/reduce/;
>>>
>>> my @rounded_5mins = grep { not $_ % 5 } 0..60;
>>> my $curr_min = localtime->min;
>>>
>>> my $round_min = reduce { $curr_min-$a< $b-$curr_min ? $a : $b } @rounded_5mins;
>>
>> Both this and Uri's earlier suggestion ignore the seconds field. I would
>> be surprised if it was acceptable to round 10:02:59
>> to 10:00:00 rather than 10:05:00.
>
> Depends on how precise the partition counts need to be... maybe just
> determining the approx. spread of timestamps in 5 min. increments
> suffices. And of course, if there's some other criteria, maybe, even
> a biasing that causes 10:02:30 to fall into a 10:00:00 rather than a
> 10:05:00 slot, won't be acceptable either.

Maybe, anything is possible, I am just saying I think it is highly
unlikely. If precision is not an issue and the data just needs to be
bundled into intervals then why not just truncate to the preceding
five-minute mark? And if there is to be any attempt at finding
a near value then rounding 40% of the data upward and 60% of it downward
is a bizarre requirement.

Rob

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Rounding Date/Time

am 05.05.2011 18:01:33 von Pete Smith

On May 2, 9:46 am, lm7...@gmail.com (Matt) wrote:
>>>> Have a date:
>>
>>>> 2011-05-02-16:40:51
>>
>>>> Using this to get it:
>>
>>>> $tm = gmtime;
>>>> $time_stamp = sprintf "%04d-%02d-%02d-%02d:%02d:%02d",
>>>> $tm->year + 1900, $tm->mon + 1, $tm->mday, $tm->hour, $tm->min, $tm->sec;
>>>> print "$time_stamp\n";
>>
>>>> I need to round it to nearest 5 minute point.
>>
>>>> 2011-05-02-16:40:51
>>
>>>> needs rounded like so.
>>
>>>> 2011-05-02-16:00:00
>>>> 2011-05-02-16:45:00
>>>> 2011-05-02-16:50:00
>>>> 2011-05-02-16:55:00
>>
>>>> My thought is a bunch of if statements but that seems ugly. Is there
>>>> a better/easier way?

The Modern Perl suggestion when dealing with dates and times is to use
DateTime. It is well tested and should handle edge cases you may not
have considered. After all, what do you do when you want to round up
from 2011-12-24 23:58:00?

You can use Math::Round to do the rounding for you.

Cheers,
Pete

use DateTime;
use DateTime::Duration;
use Math::Round 'nearest';

# create a DateTime object for now - see the docs:
# http://search.cpan.org/perldoc?DateTime
my $dt = DateTime->now;

# you should set time zone as you may be in DST
$dt->set_time_zone( 'Europe/London' );

# create a DateTime::Duration of nearest 5 minutes
my $duration = DateTime::Duration->new(
minutes => nearest(5, $dt->minute)
);

# this truncates the time to the hour - you can truncate to any unit of
# time
$dt->truncate(to => 'hour');

# you can add durations to DateTime objects using addition and
# subtraction operators
$dt += $duration;

# DateTime objects can be printed in scalar context
print $dt, "\n";


NET-A-PORTER.COM
Irresistible fashion at your fingertips

____________________________________________________________ __________

CONFIDENTIALITY NOTICE
The information in this email is confidential and is intended solely for the addressee. Access to this email by anyone else is unauthorised. If you are not the intended recipient, you must not read, use or disseminate the information. Any views expressed in this message are those of the individual sender, except where the sender specifically states them to be the views of Net a Porter Ltd.

Net A Porter Ltd is a company registered in England & Wales Number: 3820604 Registered Office: 1 The Village Offices, Westfield, Ariel Way, London, W12 7GF
____________________________________________________________ _________

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Rounding Date/Time

am 06.05.2011 15:19:06 von Peter Scott

On Mon, 02 May 2011 11:46:42 -0500, Matt wrote:

> Have a date:
>=20
> 2011-05-02-16:40:51
[...]
>=20
> I need to round it to nearest 5 minute point.
>=20
> 2011-05-02-16:40:51

If you care about things like daylight savings time adjustments, calendar=
=20
changes, or leap seconds, the answer requires considerably more thought=20
(use DateTime and do only one arithmetic operation to adjust the time). =20
People who spend much time learning about time peculiarities tend to=20
think of those considerations constantly. They only matter to you if you=
=20
don't want to accidentally generate a time that didn't exist in your=20
locale, e.g. 2am on a day that the clocks advanced.

--=20
Peter Scott
http://www.perlmedic.com/ http://www.perldebugged.com/
http://www.informit.com/store/product.aspx?isbn=3D0137001274
http://www.oreillyschool.com/courses/perl3/

--=20
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/