I have the following types of strings:
17082011T1015
In other words: day month year T hours minutes.
What would be an efficient way to parse these strings in such a way that I end with something like a MySQL-like date:
`2011-08-17 10:15`
(There's no MySQL involved here by the way)
It's for Windows PHP < 5.3 so strptime() and date_parse_from_format()/DateTime::createFromFormat() are NOT an option.
It's just rearranging a string.
$date = "17082011T1015";
$day = substr($date, 0, 2);
$month = substr($date, 2, 2);
$year = substr($date, 4, 4);
$hour = substr($date, 9, 2);
$minute = substr($date, 11, 2);
echo $year . '-' . $month . '-' . $day . ' ' . $hour . ':' . $minute;
I think I'll end up using this solution:
sscanf( '17082011T1015', '%02s%02s%04sT%02s%02s', $day, $month, $year, $hours, $minutes );
$datetime = $year . '-' . $month . '-' . $day . ' ' . $hours . ':' . $minutes;
Before asking the question I didn't realize I could utilize the optional arguments to sscanf() to my advantage, and thought I would have to resort to something like this:
$parsed = sscanf( '17082011T1015', '%02s%02s%04sT%02s%02s' );
$datetime = $parsed[ 2 ] . '-' . $parsed[ 1 ] . '-' . $parsed[ 0 ] . ' ' . $parsed[ 3 ] . ':' . $parsed[ 4 ];
Not too bad either, but I like to be pretty clear as possible with named variables, so that it's obvious what this little routine does.
If you are using PHP >= 5.3.0, you may use DateTime::createFromTimeFormat to create ordinary DateTime object from that string.
Should be something like:
$str = "17082011T1015";
$date = DateTime::createFromFormat($str,'DDMMYYYYThhII');
echo $date->format("Y-m-d H:i:s");
Can't test it here, only have PHP 5.2. But I think you could figure the right format yourself.
Related
I'm getting date and time by HTTP GET and trying to write a php code to insert these to MYSQL db but getting error.
My date and time are coming like this:
date=260117
time=180205.000
$year= "20" . substr($date, 4,2);
$month= substr($date, 2,2);
$day= substr($month, 0,2);
$dateformatted= $year . "-" . $month. "-" . $day;
$hour= substr($time, 0,2) + 3;
$min = substr($time, 2,2);
$sec = substr($time, 4,2);
$timeformatted = $hour . ":" . $min . ":" . $sec;
$datetime = $dateformatted . " " . $timeformatted;
$datetime = strtotime($datetime);
My error is like that:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '21:02:05)' at line 2
SQL:
$sql = "INSERT INTO pt_position (date) VALUES ($datetime)";
Remove this line.
$datetime = strtotime($datetime);
If you run this line, the return value is PHP's DateTime type.
$datetime = $dateformatted . " " . $timeformatted;
After this code, you can run the sql query....
I want to filter the result of the records within the period, but i can't find any example of how to use the where clause to get the exact range of data.
These are the data posted from form:
[monthRangeStart] => 12
[yearRangeStart] => 2013
[monthRangeEnd] => 12
[yearRangeEnd] => 2013
and the following is the format of updated_at timestamp
2013-12-18 07:22:34
How should i finish the line of code
$trans = Transaction::where('updated_at', )
In my opinion if you decided to use some framework you should use tools it provides in order to create better solutions. Laravel has very beautiful Carbon class for date manipulation. This is solution I came to:
$trans = Transaction::whereBetween('updated_at', [
\Carbon\Carbon::createFromDate(Input::get('yearRangeStart'), Input::get('monthRangeStart'))->startOfMonth(),
\Carbon\Carbon::createFromDate(Input::get('yearRangeEnd'), Input::get('monthRangeEnd'))->endOfMonth()
])->get();
In this case you will never go wrong with number of days in any specific month.
You may try something like this
$start = Input::get('yearRangeStart') . '-' . Input::get('monthRangeStart');
$end = Input::get('yearRangeEnd') . '-' . Input::get('monthRangeEnd') . '-' . '31';
$trans = Transaction::whereBetween('updated_at', array($start, $end))->get();
Update :
$start = Input::get('yearRangeStart') . '-' . Input::get('monthRangeStart');
$endYear = Input::get('yearRangeEnd');
$endMonth = Input::get('monthRangeEnd');
$endDays = cal_days_in_month(CAL_GREGORIAN, $endMonth, $endYear);
$end = $endYear . '-' . $endMonth . '-' . $endDays;
$trans = Transaction::whereBetween('updated_at', array($start, $end))->get();
This should do it...
$trans = Transaction::where('updated_at', '>', "$yearRangeStart-$monthRangeStart-00 00:00:00")
->where('updated_at', '<', "$yearRangeEnd-$monthRangeEnd-31 99:99:99")
->get();
If you decide you need to filter on the days/hours/minutes/seconds as well, you can replace those as you go.
I am getting from Facebook Graph API the last 3 months page views information from all the accounts that I am admin with the following method:
$since_date = date('Y-m-d', strtotime('-3 months'));
$until_date = date('Y-m-d');
$page_views = $facebook->api('/' . $account['id'] . '/insights/page_views?since=' . $since_date . '&until=' . $until_date . '','GET');
After that I am using a php foreach loop (actually two) to get the desired information (page views and the date) in a required format (an array) like this:
foreach ($page_views['data'] as $page_view) {
$i = 0;
$len = count($page_view['values']);
foreach($page_view['values'] as $key => $page_view_values) {
$end_time = strval($page_view_values['end_time']);
$value = intval($page_view_values['value']);
echo '[\'' . substr($end_time, 0, -14) . '\', ' . $value . ']';
if ($i == $len - 1) {
continue;
} else {
echo ', ';
}
$i++;
}
Which output for further needs the following array:
(.....],['2013-04-02', 21], ['2013-04-03', 7], ['2013-04-04', 2], ['2013-04-05', 0], ['2013-04-06', 2], ['2013-04-07', 3], ['2013-04-08', 1], ['2013-04-09', 2], ['2013-04-10', 5], ['2013-04-11', 1], ['2013-04-12', 11], ['2013-04-13', 0],[.....)
All is working like it should, with the above array. I render a very nice chart but I want to filter it if I could based on days of the week. For exemple: I want an array like the one above with only the dates from Monday or Tuesday and so on... I need to filter somewhere in the second php foreach to return only the days that I want but how? What condition is used for this kind of needs? Or I should use other method, for example, query something else from the Facebook Graph Api? Any guidance is more than welcomed.
You could do for example a switch case based on the 3-letter code of the week day, and do something like this for each day:
$tempDate = '2012-07-10';
echo date('D', strtotime( $tempDate));
It will output: Tue
This will allow you to filter by the week day. For example, you would only add to the array if the weekday code is Tue. All others will be skipped.
Added #arraintxo note:
date('N', strtotime($tempDate))
would return a numeric value of the week day (1 to 7, 1 being Monday and 7 Sunday), easier to compare.
I'd suggest something similar to the current reply, with slight adjustments:
$first=false; $cache=array(); $conv=new \Date('2000-01-01T00:00:00Z');
foreach ($page_views['data'] as $page_view) {
foreach($page_view['values'] as $key => $page_view_values) {
$end_time = strval($page_view_values['end_time']);
$ds=substr($end_time, 0, -14);
$value = intval($page_view_values['value']);
if(!isset($cache[$ds])
$cache[$ds]=(int)$conv->modify($ds)->format('N');
if($first){ echo ', '; $first=false; }
echo '[\'' . $ds . '\', ' . $value . ', '.$cache[$ds].']';
}
}
The day indices are now present as the third items of the arrays. Notice 1: a cache is used so that you look up every date only once. Notice 2: using a bool to not add leading separators is much cheaper than counting down from a count which is in turn cheaper than counting up to a count (what you did in the first place). Notice 3: This modifies the $conv object again and again, because I don't like creating many objects, and this ought to perform at least as well as the procedural style (date() and strtotime()).
In the first place I want to thank you all for the prompt replies, it was a great help received and I am very grateful for it. Based on your guidelines I solve my "issue" in the following manner:
$since_date = date('Y-m-d', strtotime('-3 months'));
$until_date = date('Y-m-d');
$page_views = $facebook->api('/' . $account['id'] . '/insights/page_views?since=' . $since_date . '&until=' . $until_date . '','GET');
foreach ($page_views['data'] as $page_view) {
$i = 0;
foreach($page_view['values'] as $key => $page_view_values) {
$end_time = strval($page_view_values['end_time']);
$ds = substr($end_time, 0, -14);
$value = intval($page_view_values['value']);
if (date('N', strtotime($ds)) != 1) {
continue;
} else {
if ($i==1) {
echo ', ';
}
$i=1;
echo '[\'' . $ds . '\', ' . $value . ']';
}
}
}
I can do this for every day of the week by using date('N', strtotime($ds)) for the corresponding number of the day. I receive the array that I want but if I can, i want to know if is possible to sum the numbers in the variables called $page_view_values['value'] (i want to make a comparison between the days in the week).
Right now i am the month, day, and year of a user seperated in three db fields titled month, day, year.
When i display it i am doing:
$month = $row['month'];
$day = $row['day'];
$year = $row['year'];
then to echo it:
$month/$day/$year
The problem is that the PHP is doing mathematics here and dividing the numbers... What can i do to not make that happen and let it simply display the dates..
Thanks
try this out :
echo "{$month}/{$day}/{$year}";
echo $month.'/'.$day.'/'.$year;
date('m/d/Y',strtotime($month . ' ' . $day . ' ' . $year));
The advantage of this is that you can choose how to format the date independent of how it is stored in your database: http://php.net/manual/en/function.date.php
echo $month . "/" . $day . "/" . $year;
Doing string concatenation.
or
echo "{$month}/{$day}/{$year}";
Doing string interpolation.
See the difference/performance of the two here.
I have this string from eBay Web-Service.
// 2Days 23Hours 37Minutes 50Seconds
$string = P2DT23H37M50S
I was using the following code to extract and time and date:
$daysLeft = substr($string, 1, 1) . " Days";
$hoursLeft = substr($string, 4, 2) . " Hours";
$minutesLeft = substr($string, 7, 2) . " Minutes";
$secondsLeft = substr($string, 10, 2) . " Seconds";
But the problem is, When the hours, minutes and dates are only 1 Digit, the strings gets all messed up, I had it working initially, but I'm kind of stuck to find a simple way to do it, I was going to write it in a bunch of If statements, but really want a more simple way to do this.
How about using sscanf (the opposite of sprintf)?
list($daysLeft, $hoursLeft, $minutesLeft, $secondsLeft) = sscanf($string, "P%dDT%dH%dM%DS ");
If you now that all fields always is there, just preg_split the string on non-numbers:
$fields = preg_split('[^0-9]+', $string);
$daysLeft = $fields[1] . " Days";
$hoursLeft = $fields[2] . " Hours";
$minutesLeft = $fields[3] . " Minutes";
$secondsLeft = $fields[4] . " Seconds";