I'm hoping that my concern will be answered as soon as possible. :) So here it is: I'm having a hard time solving this problem, as shown below:
$beg_week = "2014 - 49"; //yyyy - w
$stop_wk = "2015 - 5"
while($beg_week <= $stop_wk)
{
/* do logic to add week in the format "yyyy - w", but also
* have to consider the year */
$beg_week = '';
}
So, how can I add a week in a 'yyyy - w' format, without using strtotime()?
Convert your start and end times to timestamps using date_parse_from_format() and mktime(). Alternatively, use an SQL function like MySQL's UNIX_TIMESTAMP() if retrieving data from a datetime field.
Use date_parse_from_format() to break the date into its components.
Use mktime() to get a timestamp
Add a week's worth of seconds (60 * 60 * 24 * 7)
Use date() to output the next week.
Note: date_parse*() won't log/store an error in the returned array if you have more than 29 or 28 days in February (for a leap or regular year, respectively). This might/might not matter, depending on what you're using it for.
There is no need to jump through hoops with date() and mktime() for this. The DateTime classes can handle it simply and cleanly, something like this should work for you:-
$beg_week = (new \DateTime())->setISODate(2014, 49);
$stop_week = (new \DateTime())->setISODate(2015, 5);
$interval = new \DateInterval('P7D');
while($beg_week < $stop_week){
echo $beg_week->format('Y-m-d') . "<br/>\n";
$beg_week->add($interval);
}
Sorry it took so long before I am able to solved and share the method/approach that I used for this matter, since I've got an additional project than this. So what i did was:
First, build a function that gets the max week of a year(thanks to #salathe),
function getIsoWeekYear($year)
{
$date = new DateTime;
$date->setISODate($year,53);
return ($date->format("W") === "53" ? 53 : 52);
}
Then to increment the value of a week, considering also the given year,
$beg_week = "2014 - 50"; //just a sample and not actually a string
$end_week = "2015 - 05";
while($beg_week<=$end_week)
(
$out_data[] = $beg_week;
$b_week_exp = explode(" - ",$beg_week);
$b_yr_temp = $b_week_exp[0];
$b_wk_temp = $b_week_exp[1];
$max_wk_of_yr = getIsoWeeksInYear($b_yr_temp);
$out_year = $b_yr_temp;
$out_week_no = $b_wk_temp+1;
if($out_week_no > $max_wk_of_yr)
{
$out_year = $b_yr_temp+1;
$out_week_no = "1";
}
$beg_week = $out_year." - ".sprintf("%02s", $out_week_no);
)
That's it, if you will print_r the $out_data, you will have an array of,
2014 - 50
2014 - 51
2014 - 52
2015 - 01
2015 - 02
2015 - 03
2015 - 04
2015 - 05
Well, this logic is what I want, to have loop from $beg_week up to $end_week, because there's also a logic that I am executing in it. A very simple trick, for this very simple problem! :) Sorry, SOMETIMES I am that sluggish not to answer my own question/problem. I hope this one will help to anyone who'll also encounter this same scenario. Thank you!
Related
I have data coming from the database in a 2 digit year format 13 I am looking to convert this to 2013 I tried the following code below...
$result = '13';
$year = date("Y", strtotime($result));
But it returned 1969
How can I fix this?
$dt = DateTime::createFromFormat('y', '13');
echo $dt->format('Y'); // output: 2013
69 will result in 2069. 70 will result in 1970. If you're ok with such a rule then leave as is, otherwise, prepend your own century data according to your own rule.
One important piece of information you haven't included is: how do you think a 2-digit year should be converted to a 4-digit year?
For example, I'm guessing you believe 01/01/13 is in 2013. What about 01/01/23? Is that 2023? Or 1923? Or even 1623?
Most implementations will choose a 100-year period and assume the 2-digits refer to a year within that period.
Simplest example: year is in range 2000-2099.
// $shortyear is guaranteed to be in range 00-99
$year = 2000 + $shortyear;
What if we want a different range?
$baseyear = 1963; // range is 1963-2062
// this is, of course, years of Doctor Who!
$shortyear = 81;
$year = 100 + $baseyear + ($shortyear - $baseyear) % 100;
Try it out. This uses the modulo function (the bit with %) to calculate the offset from your base year.
$result = '13';
$year = '20'.$result;
if($year > date('Y')) {
$year = $year - 100;
}
//80 will be changed to 1980
//12 -> 2012
Use the DateTime class, especially DateTime::createFromFormat(), for this:
$result = '13';
// parsing the year as year in YY format
$dt = DateTime::createFromFormat('y', $result);
// echo it in YYYY format
echo $dt->format('Y');
The issue is with strtotime. Try the same thing with strtotime("now").
Simply prepend (add to the front) the string "20" manually:
$result = '13';
$year = "20".$result;
echo $year; //returns 2013
This might be dumbest, but a quick fix would be:
$result = '13';
$result = '1/1/20' . $result;
$year = date("Y", strtotime($result)); // Returns 2013
Or you can use something like this:
date_create_from_format('y', $result);
You can create a date object given a format with date_create_from_format()
http://www.php.net/manual/en/datetime.createfromformat.php
$year = date_create_from_format('y', $result);
echo $year->format('Y')
I'm just a newbie hack and I know this code is quite long. I stumbled across your question when I was looking for a solution to my problem. I'm entering data into an HTML form (too lazy to type the 4 digit year) and then writing to a DB and I (for reasons I won't bore you with) want to store the date in a 4 digit year format. Just the reverse of your issue.
The form returns $date (I know I shouldn't use that word but I did) as 01/01/01. I determine the current year ($yn) and compare it. No matter what year entered is if the date is this century it will become 20XX. But if it's less than 100 (this century) like 89 it will come out 1989. And it will continue to work in the future as the year changes. Always good for 100 years. Hope this helps you.
// break $date into two strings
$datebegin = substr($date, 0,6);
$dateend = substr($date, 6,2);
// get last two digits of current year
$yn=date("y");
// determine century
if ($dateend > $yn && $dateend < 100)
{
$year2=19;
}
elseif ($dateend <= $yn)
{
$year2=20;
}
// bring both strings back into one
$date = $datebegin . $year2 . $dateend;
I had similar issues importing excel (CSV) DOB fields, with antiquated n.american style date format with 2 digit year. I needed to write proper yyyy-mm-dd to the db. while not perfect, this is what I did:
//$col contains the old date stamp with 2 digit year such as 2/10/66 or 5/18/00
$yr = \DateTime::createFromFormat('m/d/y', $col)->format('Y');
if ($yr > date('Y')) $yr = $yr - 100;
$md = \DateTime::createFromFormat('m/d/y', $col)->format('m-d');
$col = $yr . "-" . $md;
//$col now contains a new date stamp, 1966-2-10, or 2000-5-18 resp.
If you are certain the year is always 20 something then the first answer works, otherwise, there is really no way to do what is being asked period. You have no idea if the year is past, current or future century.
Granted, there is not enough information in the question to determine if these dates are always <= now, but even then, you would not know if 01 was 1901 or 2001. Its just not possible.
None of us will live past 2099, so you can effectively use this piece of code for 77 years.
This will print 19-10-2022 instead of 19-10-22.
$date1 = date('d-m-20y h:i:s');
If it's 2am in London, how can I find the GMT offsets in seconds where the local time is between 7am and 7pm?
I have database records with a GMT offset column (-3600, -14400, 28000 etc) . I'd like to be able to select by those with offsets falling roughly within local daytime hours. Right now, which of these offsets are in daytime hours? I'm totally at a loss for how to approach this.
This is easier that in looks. If you have the time passed since UTC midnight, in seconds, like here
$gmtSecondsSinceMidnight = (gmmktime() - gmmktime(0,0,0));
then timezones should be within 60*60*7 and 60*60*19 seconds distance from that, relative to GMT. 19 is 7pm in 24h notation.
$remoteTZStartZ1 = 7*$hour - $gmtSecondsSinceMidnight;
$remoteTZEndZ1 = 19*$hour - $gmtSecondsSinceMidnight;
This would suffice to formulate a query like
echo "SELECT name FROM timezones WHERE
(offsetSeconds > $remoteTZStartZ1 AND offsetSeconds < $remoteTZEndZ1);";
However, you'll need to construct two additional brackets if the remoteTZ variables go beyond a 12h offset. Otherwise you might try to select timezones with an offset greater than 12h or below -12h. To make it "wrap around", copy the offsets to ±24h:
$remoteTZStartZ2 = $remoteTZStartZ1 - 24*$hour;
$remoteTZEndZ2 = $remoteTZEndZ1 - 24*$hour;
$remoteTZStartZ3 = $remoteTZStartZ1 + 24*$hour;
$remoteTZEndZ3 = $remoteTZEndZ1 + 24*$hour;
and use a query like this
echo "SELECT name FROM timezones WHERE
(offsetSeconds > $remoteTZStartZ1 AND offsetSeconds < $remoteTZEndZ1) OR
(offsetSeconds > $remoteTZStartZ2 AND offsetSeconds < $remoteTZEndZ2) OR
(offsetSeconds > $remoteTZStartZ3 AND offsetSeconds < $remoteTZEndZ3);";
likeitlikeit's answer helped to refine my efforts, the only thing missing really was anchoring in an actual timestamp. I crudely solved the problem this way, though this could be vastly improved:
date_default_timezone_set('Europe/London');
$currentTimestamp = time();
$startHour = strtotime("7am");
$endHour = $startHour+50400; //9pm
$start = ($startHour>$currentTimestamp) ? ($startHour - $currentTimestamp) : -1 * abs($currentTimestamp - $startHour);
$end = ($endHour>$currentTimestamp) ? ($endHour - $currentTimestamp) : -1 * abs($currentTimestamp - $endHour);
PHP has this function for version 5.2+ DateTimeZone::getOffset
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
strtotime date weird result
I am trying to compare two times for an attendance system, i am trying to get the accurate time for Arkansas,USA but im not being to able to get the correct time. Please, guide me in the right direction if i am doing something wrong, part of my code:
$curTime =DATE("H:i A", strtotime('GMT-6'));
foreach($res as $r)
{
$crs_id =$r['course_id'];
$query1 = "select * from tbl_course_time where course_id='$crs_id'";
$res1 = $obj->querySelect($query1);
$start_time = DATE("H:i", STRTOTIME($res1[0]['start_time']));
$end_time = DATE("H:i", STRTOTIME($res1[0]['end_time']));
if ($curTime > $start_time && $curTime < $end_time)
{
$qry="insert into tbl_attendance set stud_id='$id',attd_date='$curDateForDB',attd_time='$curTimeForDB',course_id='$attd_courseId'";
$res=$obj->queryInsert($qry);
$result1 = "taken";
}
}
It's giving me incorrect time's is it the GMT time im getting wrong or something else
Any help would be greatly appreciated, Thank you
Don't use strtotime('GMT-6') because GMT-6 is not a time; it's a time zone.
// gets the UTC time using gmdate() instead of date()
$utc_str = gmdate("M d Y H:i:s", time());
// get the UTC timestamp, should you need it
$utc = strtotime($utc_str);
If you're in PHP 5, the DateTime class is a very clean way to get times and also deal with time zone conversions.
Also, I encourage you to set your database up using UTC time, and convert the output to the user's time zone.
You're doing the gmt-6 business wrong. The following is on a server that's in GMT-6 already:
echo date('r'); // Thu, 13 Dec 2012 02:40:00 -0600
echo date('r', strtotime('gmt-6')); // Thu, 13 Dec 2012 08:40:17 -0600
Note the 6 hour difference (and 17 seconds while I was typing up the strtotime bits). Doing the gmt-6 bit in strtotime forces PHP to apply a 6 hour difference to a string that's already in some timezone already.
I need to create functions in PHP that let me step up/down given datetime units. Specifically, I need to be able to move to the next/previous month from the current one.
I thought I could do this using DateTime::add/sub(P1M). However, when trying to get the previous month, it messes up if the date value = 31- looks like it's actually trying to count back 30 days instead of decrementing the month value!:
$prevMonth = new DateTime('2010-12-31');
Try to decrement the month:
$prevMonth->sub(new DateInterval('P1M')); // = '2010-12-01'
$prevMonth->add(DateInterval::createFromDateString('-1 month')); // = '2010-12-01'
$prevMonth->sub(DateInterval::createFromDateString('+1 month')); // = '2010-12-01'
$prevMonth->add(DateInterval::createFromDateString('previous month')); // = '2010-12-01'
This certainly seems like the wrong behavior. Anyone have any insight?
Thanks-
NOTE: PHP version 5.3.3
(Credit actually belongs to Alex for pointing this out in the comments)
The problem is not a PHP one but a GNU one, as outlined here:
Relative items in date strings
The key here is differentiating between the concept of 'this date last month', which, because months are 'fuzzy units' with different numbers of dates, is impossible to define for a date like Dec 31 (because Nov 31 doesn't exist), and the concept of 'last month, irrespective of date'.
If all we're interested in is the previous month, the only way to gaurantee a proper DateInterval calculation is to reset the date value to the 1st, or some other number that every month will have.
What really strikes me is how undocumented this issue is, in PHP and elsewhere- considering how much date-dependent software it's probably affecting.
Here's a safe way to handle it:
/*
Handles month/year increment calculations in a safe way,
avoiding the pitfall of 'fuzzy' month units.
Returns a DateTime object with incremented month/year values, and a date value == 1.
*/
function incrementDate($startDate, $monthIncrement = 0, $yearIncrement = 0) {
$startingTimeStamp = $startDate->getTimestamp();
// Get the month value of the given date:
$monthString = date('Y-m', $startingTimeStamp);
// Create a date string corresponding to the 1st of the give month,
// making it safe for monthly/yearly calculations:
$safeDateString = "first day of $monthString";
// Increment date by given month/year increments:
$incrementedDateString = "$safeDateString $monthIncrement month $yearIncrement year";
$newTimeStamp = strtotime($incrementedDateString);
$newDate = DateTime::createFromFormat('U', $newTimeStamp);
return $newDate;
}
Easiest way to achieve this in my opinion is using mktime.
Like this:
$date = mktime(0,0,0,date('m')-1,date('d'),date('Y'));
echo date('d-m-Y', $date);
Greetz Michael
p.s mktime documentation can be found here: http://nl2.php.net/mktime
You could go old school on it and just use the date and strtotime functions.
$date = '2010-12-31';
$monthOnly = date('Y-m', strtotime($date));
$previousMonth = date('Y-m-d', strtotime($monthOnly . ' -1 month'));
(This maybe should be a comment but it's to long for one)
Here is how it works on windows 7 Apache 2.2.15 with PHP 5.3.3:
<?php $dt = new DateTime('2010-12-31');
$dt->sub(new DateInterval('P1M'));
print $dt->format('Y-m-d').'<br>';
$dt->add(DateInterval::createFromDateString('-1 month'));
print $dt->format('Y-m-d').'<br>';
$dt->sub(DateInterval::createFromDateString('+1 month'));
print $dt->format('Y-m-d').'<br>';
$dt->add(DateInterval::createFromDateString('previous month'));
print $dt->format('Y-m-d').'<br>'; ?>
2010-12-01
2010-11-01
2010-10-01
2010-09-01
So this does seem to confirm it's related to the GNU above.
Note: IMO the code below works as expected.
$dt->sub(new DateInterval('P1M'));
Current month: 12
Last month: 11
Number of Days in 12th month: 31
Number of Days in 11th month: 30
Dec 31st - 31 days = Nov 31st
Nov 31st = Nov 1 + 31 Days = 1st of Dec (30+1)
I have a simple situation where I have a user supplied week number X, and I need to find out that week's monday's date (e.g. 12 December). How would I achieve this? I know year and week.
Some code based mainly on previous proposals:
$predefinedYear = 2009;
$predefinedWeeks = 47;
// find first mоnday of the year
$firstMon = strtotime("mon jan {$predefinedYear}");
// calculate how much weeks to add
$weeksOffset = $predefinedWeeks - date('W', $firstMon);
// calculate searched monday
$searchedMon = strtotime("+{$weeksOffset} week " . date('Y-m-d', $firstMon));
An idea to get you started:
take first day of year
add 7 * X days
use strtodate, passing in "last Monday" and the date calculated above.
May need to add one day to the above.
Depending on the way you are calculating week numbers and the start of the week this may sometimes be out. (i.e. if the monday in the first week of the year was actually in the previous year!)
TEST THIS THOROUGHLY - but I've used a similar approach for similar calcualtions in the past.
This will solve the problem for you. It mainly derives from Mihail Dimitrov's answer, but simplifies and condenses this somewhat. It can be a one-line solution if you really want it to be.
function getMondaysDate($year, $week) {
if (!is_numeric($year) || !is_numeric($week)) {
return null;
// or throw Exception, etc.
}
$timestamp = strtotime("+$week weeks Monday January $year");
$prettyDate = date('d M Y');
return $prettyDate;
}
A couple of notes:
As above, strtotime("Monday January $year") will give you the timestamp of the first Monday of the year.
As above +X weeks will increment a specified date by that many weeks.
You can validate this by trying:
date('c',strtotime('Sunday Jan 2018'));
// "2018-01-07T00:00:00+11:00" (or whatever your timezone is)
date('c',strtotime('+1 weeks Sunday Jan 2018'));
// "2018-01-14T00:00:00+11:00" (or whatever your timezone is)
date('c',strtotime('+52 weeks Sunday Jan 2018'));
// "2019-01-06T00:00:00+11:00"
Due to reputation restriction i can't post multiple links
for details check
http://php.net/manual/en/function.date.php and http://php.net/manual/en/function.mktime.php
you can use something like this :
use mktime to get a timestamp of the week : $stamp = mktime(0,0,0,0,<7*x>,) {used something similar a few years back, so i'm not sure it works like this}
and then use $wDay = date('N',$stamp). You now have the day of the week, the timestamp of the monday should be
mktime(0,0,0,0,<7*x>-$wDay+1,) {the 'N' parameter returns 1 for monday, 6 for sunday}
hope this helps
//To calculate 12 th Monday from this Monday(2014-04-07)
$n_monday=12;
$cur_mon=strtotime("next Monday");
for($i=1;$i<=$n_monday;$i++){
echo date('Y-m-d', $cur_mon);
$cur_mon=strtotime(date('Y-m-d', strtotime("next Monday",$cur_mon)));
}
Out Put
2014-04-07
2014-04-14
2014-04-21
2014-04-28
2014-05-05
2014-05-12
2014-05-19
2014-05-26
2014-06-02
2014-06-09
2014-06-16
2014-06-23