In a site I am creating, I want to store member data and in that data I have a start/join date which is easy to get, but I want to automatically calculate the expiry date which I'm having problems with..
Basically all new members will expire on the last day of February each year, so if I join on say 1st Feb 2013 my expiry will be on 28/02/2014, if I join on 1/03/13 or 20/12/13 my expiry will still be on 28/02/2014. ((I don't mind too much about the 1 day that appears on leap years))
Does anyone know how I can work this out - I know it's probably something obvious but I just cant seem to grasp it! :/
(I'll be doing this in php)
Many thanks in advance,
Chris
Assuming that you have (or can get) their registration date in a Unix timestamp format, you could do the following:
function calculateExpiry($reg_date)
{
$next_year = strtotime('+1 year', $reg_date);
$feb_days = ((($next_year % 4) == 0) && ((($next_year % 100) != 0) || (($next_year % 400) == 0))) ? 29 : 28;
return strtotime($feb_days.' February '.$next_year);
}
This will always return the last day of February for the following year in a Unix timestamp, so you can format it how you like. I think this logic is suitable, see the following use cases:
Register: 01/01/2013, Returns: 28/02/2014
Register: 09/10/2013, Returns: 28/02/2014
Register: 31/12/2013, Returns: 28/02/2014
Register: 01/01/2014, Returns: 28/02/2015
This should do the trick too :).
function calculate_expiry( $rawDate ) {
// Convert data into usable timestamp
$signupDate = strtotime( $signupDate );
$cutoffYear = date('Y', $signupDate) + 1;
// Set the expiry to be the last day of Feb (the first day of March -1)
$expiryDate = new DateTime();
$expiryDate->setTimestamp( mktime( 0, 0, 0, 3, 1, $cutoffYear ) );
$expiryDate->sub( new DateInterval('P1D') );
}
Well, we will get the current signup date by doing...
$signup_date = date("m-d-Y"); // or time()
And then offset it by another year
$expire_date = date("m-d-Y", strtotime("+1 year"))
Related
I'm not trying to do this with MySQL as I see is common. I am merely trying to create a PHP Script that will display information like this using the servers time and date as a reference:
Monday 2:30am to Tuesday 2:29am - Content A
Tuesday 2:30am to Wednesday 2:29am - Content B
Wednesday 2:30am to Thursday 2:29am - Content C
and so on....
Until every day of the week in covered, for some reason I can't seem to nail this and there doesn't seem to be and examples to build from. Is this for some reason not possible?
Edit
I've used the following code and it's proving to not be as reliable as it should be.
function isInTimeWindow($dayName, $startHour, $startMinute, $endHour, $endMinute)
{
$dayName = ucfirst($dayName);
list($dayNow, $timeNow) = explode('|', date('l|Hi'));
return (
ucfirst($dayName) == $dayNow and
$timeNow >= sprintf('%02d%02d', $startHour, $startMinute) and
$timeNow <= sprintf('%02d%02d', $endHour, $endMinute)
);
}
// tuesdays during day
if(isInTimeWindow('tuesday', 02, 30, 23, 00)) {
?>
CONTENT
<?php } ?>
you could use date(l) php manual date() function function to get the actual weekday in words (Monday, Tuesday, ... ) so you can check the weekday.
Use mktime function php manual mktime() function to convert your times ( Monday, 2:30am for example ) into timestamps and check if it is between current time by using time function php manual time() function
EDIT: Here's an example:
$today_start = mktime(2, 30, 0, date('m'), date('d'), date('Y'));
$today_end = mktime(2, 29, 0, date('m'), (date('d') + 1), date('Y'));
if ( $today_start < time() && $today_end > time() )
// code
mktime works like this: mktime( hour, minutes, seconds, month, day, year )
So long as you're happy using the server's time rather than the client's time this can be done using the getdate() function.
For example, if you just wanted to do it based on day of the week:
<?php
$now = getdate();
switch($now['wday']) {
case 0:
?>
Content A
<?
break;
etc.
Edit: here is how to do it in more detail:
getdate() provides you with information about the hour and minute parts too.
You could have a function like :
// Get's the 0-indexed day of the week offset so each "day" starts and 2:30am
function get_offset_day() {
$now = getdate();
if ($now['hours']*60 + $now['minutes'] < 150) { // less 2h 30m after midnight => still "yesterday"
$answer = $now['wday']-1;
}
else {
$answer = $now['wday'];
}
if ($answer < 0) return 6;
return $answer;
}
I am trying to get stripe to set a end_trial date on the next occurrence of whatever day of the month the user chooses. i.e. If today is the 16th and the user chooses the 15th I need the unix timestamp for the 15th of the next month. However if today was the 14th I need the timestamp for tomorrow.
I tried the solution found on this SO question Find the date for next 15th using php .
When i ran the code suggested in that question and substituted 15 for 31
$nextnth = mktime(0, 0, 0, date('n') + (date('j') >= 31), 31);
echo date('Y-m-d', $nextnth);
The result is 2013-03-03
I also tried this one Get the date of the next occurrence of the 18th .
The second one would actually give me 2013-03-31 when i ran it one 2013-1-31.
Both had unexpected results. Is february the problem? Any guidance will be much appreciated.
Here is a way to do it.
function nextDate($userDay){
$today = date('d'); // today
$target = date('Y-m-'.$userDay); // target day
if($today <= $userDay){
$return = strtotime($target);
}
else{
$thisMonth = date('m') + 1;
$thisYear = date('Y');
if($userDay >= 28 && $thisMonth == 2){
$userDay = 28;
}
while(!checkdate($thisMonth,$userDay,$thisYear)){
$thisMonth++;
if($thisMonth == 13){
$thisMonth = 1;
$thisYear++;
}
}
$return = strtotime($thisYear.'-'.$thisMonth.'-'.$userDay);
}
return $return;
}
// usage
echo date('Y-m-d',nextDate(29));
We get the user's choice and compare it today.
If today is less than or equal to user choice, we return the timestamp for this month.
If today is greater than user choice, we loop through dates, adding a month (or a year if it's $thisMonth hits 13). Once this date does exist again, we have our answer.
We check the dates using php's checkdate function, strtotime and date.
I really don't understand the question completely. You can easily determine the date for next 30 days for example
$next_ts = time() + 30 * 86400; // add 30 days to current timestamp
$next = date('Y-m-d', $next_ts); // format string as Y-m-d
echo $next;
If that is not what you need, please explain the problem.
I have a script that was working, well is working but not properly. The function is suppose to work out the time difference between two dates/times.
The First date is the Current Date and Time (Date + Hr:Min) and the second date is chosen by a user.
The purpose is to show error when the current date/time is within 24 hours from the user chosen date. i.e. if today is 23/20/2012 16:00 and the user chooses 24/10/2012 15:00 (this mean its within 24 hours) but if user chooses 26/10/2012 19:00 then its passed 24 hours.
Now this works fine but when the date changes its year (when user selected any date after 31st Dec 2012.. it assumes its still within 24 hours.. and im quite baffled how this happens.. can anyone shed some light what I've done wrong?
$dt = $_GET['dt']; $tm = $_GET['tm'];
// Current Date an time (Hrs & Mins)
$date1 = date("Y-m-d H:i");
// Chosen Date/Time
$date2 = date("Y-m-d", strtotime( "$dt" ) );
$diff = strtotime($date2." $tm") + - strtotime($date1);
if($diff/3600 < 24)
echo "0";
else
echo "1";
The following is the corresponding Ajax that makes th call
function getAjaxTime()
{
xmlHttp=GetXmlHttpObject();
if (xmlHttp==null)
{
alert ("Your browser does not support AJAX!");
return;
}
dt = document.frm.arrival_date.value;
tm = document.frm.arrival_hour.value +':'+document.frm.arrival_min.value;
xmlHttp.open("GET","<?php echo $base_dir;?>/admin/get/timediff.php?dt="+encodeURI(dt)+"&tm="+encodeURI(tm),false);
xmlHttp.send(null);
return xmlHttp.responseText;
}
I would try something like this:
function isDateWithin24Hours($targetDate, $currentDate = 'now') {
$targetDate = new DateTime($targetDate);
$currentDate = new DateTime($currentDate);
$interval = $targetDate->diff($currentDate);
//%a = total number of days
if ($interval->format('%a') > 1) {
return (int) false;
}
return (int) true;
}
echo isDateWithin24Hours('2012-10-24 19:00:00');
echo isDateWithin24Hours('2012-10-24 19:00:00', '2012-10-23 18:00:00');
According to the php manual - http://us3.php.net/manual/en/datetime.formats.date.php - your date is not a valid format:
24/10/2013 // with / as deliminators
These would be valid
24-10-2013 // with - as deliminators
10/24/2013 // with / as deliminators and as m/d/Y
Update-
Also, the following format is invalid in strtotime & date-
Thursday, 10 May, 2012 00:30
But this would be valid -
Thursday, May 10, 2012 00:30
Update #2
In fact once your $_GET['dt'] is in a valid php format, you could simplify your code to-
$dt = $_GET['dt']; $tm = $_GET['tm'];
// Current Date an time (Hrs & Mins)
$date1 = date("Y-m-d H:i");
$diff = strtotime($dt." ".$tm) + - strtotime($date1);
if($diff/3600 < 24)
echo "0";
else
echo "1";
Dates in PHP are a nightmare for me so please help me out fellow coders... I want to notify customers about the day their order will be delivered. It works like this:
I have 2 shipping zones, A & B. Orders for zone A are delivered each Monday, Wednesday & Friday, whereas zone B is on Tuesday, Thursday, Saturday. For each order, the delivery day is scheduled for the NEXT AVAILABLE day, depending on the zone. Please consider that if someone places an order on Monday the goods will be delivered on the NEXT available date, that would be Tuesday for zone B and Wednesday for zone A.
How can I calculate the NEXT AVAILABLE delivery date and notify the customer?
Thanks.
This will certainly not be the fastest or most clever answer, but it's going to be a pleasure to read the code.
Assuming we are shipping in zone A:
$dates = array(
new DateTime('next monday'), // magic!
new DateTime('next wednesday'),
new DateTime('next friday'),
);
// Seems to work because since PHP 5.2.2 DateTime objects
// can be compared with the < and > operators
$shippingDate = min($dates);
echo $shippingDate->format('Y-m-d');
You might want to take a look at the relative date formats available in PHP, this is the part where the "next monday" magic happens. For information on what you can do with $shippingDate, see the documentation on class DateTime.
Update
For completeness, here is a more old-school version which does not need PHP 5.3 and should also be faster (although speed is practically irrelevant here). I don't like it as much, because it's not easy to verify that it works correctly. In contrast to the version above, this one had a bug when I first wrote it. Simple is good.
$today = date('w');
// These values are from http://www.php.net/manual/en/function.date.php
$shippingDays = array(
1, // mon
3, // wed
5, // fri
);
// Each of these weekdays is how many days into the future?
foreach($shippingDays as &$day) {
$day = (7 + $day - $today) % 7;
}
// Get the earliest one, but not if it's today
// array_filter is used to remove a possible 0
$daysInFuture = min(array_filter($shippingDays));
$shippingDate = new DateTime('+'.$daysInFuture.' days');
echo $shippingDate->format('Y-m-d');
See it in action.
Try this:
// Info
$date = array(date("d"), date("m"), date("Y"));
$zone = "A";
// ------
$zones = array("A" => array(1 => "Monday",
3 => "Wednesday",
5 => "Friday")
,"B" => array(2 => "Tuesday",
4 => "Thursday",
6 => "Saturday"));
$found = false;
$days_plus = 1; // always next day
// Retrieve last day from the zone
end($zones[$zone]);
$last_day = key($zones[$zone]);
do {
$mk = mktime(0, 0, 0, $date[1], ($date[0] + $days_plus), $date[2]);
$week = date("w", $mk);
// if week not passed last day of zone
if ($week <= $last_day)
{
if (!isset($zones[$zone][$week]))
{
$days_plus++;
}
else
{
$found = true;
}
}
else
{
$days_plus++;
}
} while (!$found);
echo "Next date: " . date("d/m/Y - l", $mk);
$timestamp = strtotime('next Monday');
$date = date('Y-m-d', $timestamp);
Is there a painless way to convert unix timestamps, MySQL timestamps, MySQL datetimes (or any other standard date and time format) into strings in the following form:
Today, 6:00pm
Tomorrow, 12:30pm
Wednesday, 4:00pm
Next friday, 11:00am
I'm not sure what to call these - I guess conversational-style, current time sensitive date formats?
As best I can tell, there is no native function for this. I have created (the start of) a function to do what you are wanting.
function timeToString( $inTimestamp ) {
$now = time();
if( abs( $inTimestamp-$now )<86400 ) {
$t = date('g:ia',$inTimestamp);
if( date('zY',$now)==date('zY',$inTimestamp) )
return 'Today, '.$t;
if( $inTimestamp>$now )
return 'Tomorrow, '.$t;
return 'Yesterday, '.$t;
}
if( ( $inTimestamp-$now )>0 ) {
if( $inTimestamp-$now < 604800 ) # Within the next 7 days
return date( 'l, g:ia' , $inTimestamp );
if( $inTimestamp-$now < 1209600 ) # Within the next 14, but after the next 7 days
return 'Next '.date( 'l, g:ia' , $inTimestamp );
} else {
if( $now-$inTimestamp < 604800 ) # Within the last 7 days
return 'Last '.date( 'l, g:ia' , $inTimestamp );
}
# Some other day
return date( 'l jS F, g:ia' , $inTimestamp );
}
Hope that helps.
You should read the docs for strftime and strtotime
An example of converting UNIX timestamp to your format:
$time = time(); // UNIX timestamp for current time
echo strftime("%A, %l:%M %P"); // "Thursday, 12:41 pm"
To get a MySQL datetime value, assuming it comes out of the database as "2010-07-15 12:42:34", try this:
$time = "2010-07-15 12:42:34";
echo strftime("%A, %l:%M %P"); // "Thursday, 12:42 pm"
Now, in order to print the word "today" instead of the day name you will have to do some additional logic to check if the date is today:
$time = "2010-07-15 12:42:34";
$today = strftime("%Y-%m-%d");
// compare if $time strftime's to the same date as $today
if(strftime("%Y-%m-%d", $time) == $today) {
echo strftime("Today, %l:%M %P", $time);
} else {
echo strftime("%A, %l:%M %P", $time);
}
The strtotime shoule be useful for that.
Example:
echo date('d, h:i:sa', strtotime($date_orig));
PHP date funcs are kind of messy because they have so many different ways, and even new classes were built over the old ones. For that type of formatting, what I call human-friendly formatting, you're going to have to write your own function that does it.
For conversion, you can use strtotime() as mentioned, but if you're dealing with epoch times and need utc GMT times, heres some functions for that. strtotime() would convert the epoch time to the local server time... this was something I don't want on my projects.
/**
* Converts a GMT date in UTC format (ie. 2010-05-05 12:00:00)
* Into the GMT epoch equivilent
* The reason why this doesnt work: strtotime("2010-05-05 12:00:00")
* Is because strtotime() takes the servers timezone into account
*/
function utc2epoch($str_date)
{
$time = strtotime($str_date);
//now subtract timezone from it
return strtotime(date("Z")." sec", $time);
}
function epoch2utc($epochtime, $timezone="GMT")
{
$d=gmt2timezone($epochtime, $timezone);
return $d->format('Y-m-d H:i:s');
}
If you are pulling this type of data out of your database
$time = "2010-07-15 12:42:34";
then do this
$this->db->select('DATE_FORMAT(date, "%b %D %Y")AS date');
Look here for info to display your data any way you want in human form
http://www.w3schools.com/SQL/func_date_format.asp
The above code is in codeigniter format, but you can just convert it to a SELECT statement for MYSQL
$query = "SELECT `title`,`post`, DATE_FORMAT(date, "%a, %d %b %Y %T") AS date FROM `posts` LIMIT 0, 8 ";
You will want to change the %a letters to fit your needs.
you will get exact result::
output // 28 years 7 months 7 days
function getAge(dateVal) {
var
birthday = new Date(dateVal.value),
today = new Date(),
ageInMilliseconds = new Date(today - birthday),
years = ageInMilliseconds / (24 * 60 * 60 * 1000 * 365.25 ),
months = 12 * (years % 1),
days = Math.floor(30 * (months % 1));
return Math.floor(years) + ' years ' + Math.floor(months) + ' months ' + days + ' days';
}