homepage Welcome to WebmasterWorld Guest from 54.166.10.100
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Visit PubCon.com
Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

    
Code challenge - how many minutes since the start of the week?
musicales




msg:4336962
 3:25 pm on Jul 8, 2011 (gmt 0)

I'm tryng to write some code that updates one of 10,000 products every minute - as there are 10080 minutes in a week it seems obvious to perform a function to work out how many minutes since, say 12am Monday morning and update the corresponding product - I want it to roll around the list each week rather than attempting to update them all in one go which uses a lot of resources. If we assign Monday to being day 1, then it should be some simple equation to get the current minute since 0.00 on day 1.

But I've made several attempts and I don't think they're right. Any brainiacs out there can help with this one?

 

HelenDev




msg:4336977
 3:43 pm on Jul 8, 2011 (gmt 0)

Be careful with daylight saving time - there are not always 10080 minutes in a week. I have a script a bit like this which got an unexpected number of seconds in a day the clocks changed and it fell over.

I resolved it by rounding up or down if it got a fraction of a day. Obviously your script may be a bit different, and as you have 80 minutes spare a week you should be able to factor in an hour less here or there ;)

g1smd




msg:4336985
 3:53 pm on Jul 8, 2011 (gmt 0)

Ignore time zones and daylight saving time.

Run the clock on UTC all year round.

There will always be 24 hours in every day. Sometimes there will be 61 or 59 seconds in a minute, but that won't be an issue.

httpwebwitch




msg:4336986
 3:55 pm on Jul 8, 2011 (gmt 0)

if you define time as "server time" in Unix seconds, then all the time zone and daylight saving stuff doesn't apply.

get the current Unix time.

$now = time();

define the number of seconds in a week

$seconds_per_week = 10080 * 60;

define an "origin point" which is some Monday midnight some time in the past.

$old_monday = 946944000;

number of seconds since that origin point:

$elapsed = $now - $old_monday;

Use a modulo to get the remainder when you subtract all those weeks gone by

$this_week_elapsed = $elapsed % $seconds_per_week;

and that's the number of seconds that have elapsed since Monday.

You can take it from there

musicales




msg:4336987
 3:57 pm on Jul 8, 2011 (gmt 0)

helendev - any chance you can share the code?

musicales




msg:4337010
 4:52 pm on Jul 8, 2011 (gmt 0)

beautiful, thanks httpwebwitch!

httpwebwitch




msg:4337065
 6:14 pm on Jul 8, 2011 (gmt 0)

no problem.

Modulo is an great weapon you can use liberally in many situations.

I assume you're going to put this thing on a cronjob, eh?

Another way to accomplish your goal - which doesn't require any math - is to start with the number "0" in a text file on the server. Once per minute, read it, and call it $previous. Query SQL to get the ID of the next product, and call it $next. Do stuff to it. Then write $next into the text file. Then the next time the cron runs (once per minute), get the $previous, and repeat.

Use file_get_contents() and file_put_contents()

Here I'm assuming your 10,000 products are in a database.
$query = "SELECT * FROM products WHERE id > ".$previous." ORDER BY id LIMIT 1";

A simple pointer like that will prevent you having to write some algorithm to figure out which product corresponds to which minute of the week, you can add and remove products without harming the script, and it won't fail if your product ID's aren't strictly sequential.

penders




msg:4337383
 2:04 pm on Jul 9, 2011 (gmt 0)

I would think that httpwebwitch's last method (with an incrementing counter/id in a text file) is perhaps the better solution. This would also avoid the situation that if (for some reason) your script didn't run for several minutes no products would be missed. Also, if the script did run more than once in any one minute you wouldn't update the same product twice, unless you checked for this.

Just going back to your original query about linking each minute of that week to a product... I don't think you need to even bother about weeks, as long as you have decided that it's 1 product per minute and it should loop continuously. Using httpwebwitch's modulus idea...

$product_number = (time() / 60) % $number_of_products;

If $number_of_products is 10,000 then $product_number will return a number between 0 and 9,999 based on the current time in minutes. This, however, will loop marginally shorter than 1 week if that is the major factor.

rocknbil




msg:4337420
 4:41 pm on Jul 9, 2011 (gmt 0)

define an "origin point" which is some Monday midnight some time in the past.


I write a timesheet application years ago and this was the key element - to get specific week days of anything past or future, I calculated it as "this day is X time from the beginning of the Unix epoch" - then you can use mySQL date math to calculate any day in reference to this day. Ex:

(Monday of last week)

Today is Saturday and the current second is X seconds from the beginning of the epoch, Monday of last week is 12 days ago (Which requires a little calculating depending on what week start your country uses.)

Y = X - (12 * 24 * 60 * 60)

Should give you the exact same hour and second from Monday the week before on which you apply date formatting or whatever.

rocknbil




msg:4337422
 4:43 pm on Jul 9, 2011 (gmt 0)

define an "origin point" which is some Monday midnight some time in the past.


I write a timesheet application years ago and this was the key element - to get specific week days of anything past or future, I calculated it as "this day is X time from the beginning of the Unix epoch" - then you can use mySQL date math to calculate any day in reference to this day. Ex:

(Monday of last week)

Today is Saturday and the current second is X seconds from the beginning of the epoch, Monday of last week is 12 days ago (Which requires a little calculating depending on what week start your country uses.)

Y = X - (12 * 24 * 60 * 60)

Should give you the exact same hour and second from Monday the week before on which you apply date formatting or whatever.

Another (easier) way to go is get date/time values from mysql then just apply date_sub() to them.

g1smd




msg:4337484
 8:31 pm on Jul 9, 2011 (gmt 0)

Since "number of products" will change, be sure that doesn't corrupt the process.

Should it instead be based on highest product number?

HelenDev




msg:4342204
 2:26 pm on Jul 21, 2011 (gmt 0)

As requested, here is the code. The actual app is a bit more complex than this and split over multiple files but I have tried to strip out the complexities and specifics and put it in one piece, hopefully it still works and is of use to someone!

The idea of this code is that it powers both the admin end where you can see the calendar of links, and the front end where you just see today's scheduled link.


<?php

//set the beginning of the current cycle - originally 19 July 2010 but can reset
$cycle_start = mktime(0, 0, 0, 11, 01, 2010);

//get today's date
$todays_date = mktime(0, 0, 0, date("m"), date("d"), date("Y"));

//86400 seconds = 1 day
$seconds_per_day = 86400;

//show at least the next two weeks (14 days) in the calendar
$min_calendar_duration = 14;

//today is how long after cycle start?
$days_into_cycle = ($todays_date - $cycle_start)/$seconds_per_day;
//round days into cycle in case daylight saving time shafts our calculations by returning a fraction!
$days_into_cycle = round($days_into_cycle);

//get all the link ids and put them in an array
while($link_row = mysql_fetch_array($all_links_result)){
$links_array[]= $link_row["id"];
}

//count the number of links for each section
$number_links = count($links_array);

//are there more links to display than the min calendar duration?
$max_calendar_duration = max($number_links, $min_calendar_duration);

//get complete range of calendar
$calendar_range = $days_into_cycle + $max_calendar_duration;

//assign each link to a date, starting from the beginning of the cycle
$daycount = 1;
while($daycount <= $calendar_range){
foreach($links_array as $key => $link_id){

$link_day = $cycle_start + ($daycount * $seconds_per_day);
$links_dates_array[$link_day]= $link_id;
$daycount++;
}
}

//get today's links from the array
$link_today = $links_dates_array[$todays_date];

//start from today
$daycount = $days_into_cycle;

while($daycount < $calendar_range){

//calculate the day
$calendar_day = $cycle_start + ($daycount * $seconds_per_day);

//get this day's links from the array
$link_today = $links_dates_array[$calendar_day];

//get this day's links info from the database
$link_today_info = getLink($link_today);

//put this day's info into an array to put in the view table
$links_table_row[] = array (
'link_date' => date("l d F Y",$calendar_day),
'link_id' => $slink_today_info["id"],
'link' => substr($link_today_info["link"], 0, 100),
'link_order' => $link_today_info["ordering"];

$daycount++;
}
?>



[edit reason]Apologies for the delay and gazillions of owner edits, I could not get this code to post until I had gone through it and weeded out one problematic line![/edit]

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved