3v4l.org

run code in 300+ PHP versions simultaneously
<?php class Prorate { // source and destination prices will be expressed internally as price per day once set. private $source_price = 0; private $destination_price = 0; // source expiry is what you're pro-rating. destination expiry is what you're converting. private $source_expiry; private $destination_expiry; // today defaults to the current date, but can be set to an arbitrary value using Prorate::set_today() private $today; // terms are important! they allow us to calculate the current price per day private $source_term = 12; private $destination_term = 12; // source price is what you're pro-rating. Destination_price is what you're converting. Source and destination terms // follow the same rules. public function __construct($source_price = NULL, $destination_price = NULL, $source_term = 12, $destination_term = 12) { if ($source_price != NULL) { $this->set_source_price($source_price, $source_term); } if ($destination_price != NULL) { $this->set_destination_price($destination_price, $destination_term); } $this->source_expiry = new DateTime(); $this->destination_expiry = new DateTime(); $this->today = new DateTime(); $this->source_term = $source_term; $this->destination_term = $destination_term; } // set the source expiry date. Valid inputs are either a DateTime object, or a string format listed at // http://php.net/manual/en/datetime.formats.php public function set_source_expiry($date) { if(is_object($date) && is_a($date, 'DateTime')) { $this->source_expiry = $date; } else { $this->source_expiry = new DateTime($date); } return $this; } public function get_source_expiry() { return $this->source_expiry; } // set the destination expiry date. Valid inputs are either a DateTime object, or a string format listed at // http://php.net/manual/en/datetime.formats.php public function set_destination_expiry($date) { if(is_object($date) && is_a($date, 'DateTime')) { $this->destination_expiry = $date; } else { $this->destination_expiry = new DateTime($date); } return $this; } public function get_destination_expiry() { return $this->destination_expiry; } // returns the number of (positive) days remaining between a source date in the future, and today private function days_remaining($date) { return $this->diff_days($date, $this->today); } // determines the daily value of a given price over a given number of months. // 30.44 is 365 days / 12 months private function value_per_day($price_in_cents, $term_in_months) { $value_per_day = $price_in_cents / $term_in_months / 30.44; return ceil($value_per_day) / 100; } // Allows you to change what "today" is defined as. Defaults to the current date. Valid values are // a DateTime object, or a string representation of a date in one of the formats listed at: // http://php.net/manual/en/datetime.formats.php public function set_today($date = NULL) { if(is_object($date) && is_a($date, 'DateTime')) { $this->today = $date; } else { if (is_null($date)) { $this->today = new DateTime(); } else { $this->today = new DateTime($date); } } } // sets the source price (the thing you're pro-rating) // valid inputs are a price in cents, and a term expressed in months public function set_source_price($price_in_cents, $term_in_months) { $this->source_price = $this->value_per_day($price_in_cents, $term_in_months); return $this; } public function get_source_price() { return $this->source_price; } // sets the target price (the thing you're converting) // valid inputs are a price in cents, and a term expressed in months public function set_destination_price($price_in_cents, $term_in_months) { $this->destination_price = $this->value_per_day($price_in_cents, $term_in_months); return $this; } public function get_destination_price() { return $this->destination_price; } // calculates the target value based on the current calculated price per day and time // remaining on expiry public function target_value() { return $this->days_remaining($this->destination_expiry) * $this->destination_price; } // calculates the number of days to pro-rate. this does not include the number of days // remaining on the source. public function add_days() { return ceil($this->target_value() / $this->source_price); } // DateTime diff implementation for systems that are not new enough for PHP's regular DateTime::diff() method // if there is a partial day, it is rounded up to count as a full day. private function diff_days(DateTime $x, DateTime $y) { $y = strtotime($y->format('Y-m-d')); $x = strtotime($x->format('Y-m-d')); $diff = $x - $y; if ($diff <= 0) return 0; return ceil($diff / 86400); } // Call this once all your values are set. Returns an associative array containing the number of days // remaining on the source, the number of days to add to the source, the total number of days (source + add) // and a DateTime object representing the value defined as "today" plus the total days to add. public function pro_rate() { $days = $this->diff_days($this->source_expiry, $this->today); $result = array(); $add = $this->add_days(); $total_add = $days + $add; $today = $this->today->format('Y-m-d'); $source = $this->source_expiry->format('Y-m-d'); $dest = $this->destination_expiry->format('Y-m-d'); $result['current_days'] = $days; $result['pro_rate_days'] = $add; $result['total_days'] = $total_add; $tmp = clone $this->today; $result['date'] = $tmp->modify("+{$result['total_days']} days"); return $result; } } $prorate = new Prorate(19990, 19995); $prorate->set_source_expiry('2014-07-23'); $prorate->set_destination_expiry('19-01-2014'); $result = $prorate->pro_rate(); var_dump($result);

preferences:
45.24 ms | 402 KiB | 5 Q