Check whether day is specified in a date string - php

Test case scenario - User clicks on one of two links: 2012/10, or 2012/10/15.
I need to know whether the DAY is specified within the link. I am already stripping the rest of the link (except above) out of my URL, am I am passing the value to an AJAX request to change days on an archive page.
I can do this in either JS or PHP - is checking against the regex /\d{4}\/\d{2}\/\d{2}/ the only approach to seeing if the day was specified or not?

You can also do this if you always get this format: 2012/10 or 2012/10/15
if( str.split("/").length == 3 ) { }
But than there is no guaranty it will be numbers. If you want to be sure they are numbers you do need that kind of regex to match the String.

You could explode the date by the "/" delimiter, then count the items:
$str = "2012/10";
$str2 = "2012/10/5";
echo count(explode("/", $str)); // 2
echo count(explode("/", $str2)); // 3
Or, turn it into a function:
<?php
function getDateParts($date) {
$date = explode("/", $date);
$y = !empty($date[0]) ? $date[0] : date("Y");
$m = !empty($date[1]) ? $date[1] : date("m");
$d = !empty($date[2]) ? $date[2] : date("d");
return array($y, $m, $d);
}
?>

I would personally use a regex, it is a great way of testing this sort of thing. Alternatively, you can split/implode the string on /, you will have an array of 3 strings (hopefully) which you can then test. I'd probably use that technique if I was going to do work with it later.

The easiest and fastest way is to check the length of the string!
In fact, you need to distinguish between: yyyy/mm/dd (which is 10 characters long) and yyyy/mm (which is 7 characters).
if(strlen($str) > 7) {
// Contains day
}
else {
// Does not contain day
}
This will work EVEN if you do not use leading zeros!
In fact:
2013/7/6 -> 8 characters (> 7 -> success)
2013/7 -> 6 characters (< 7 -> success)
This is certainly the fastest code too, as it does not require PHP to iterate over the whole string (as using explode() does).

Related

In PHP stristr search and return surrounding characters each side

In PHP I am using stristr search but I also want to return and display the surrounding characters each side of the found string, like concordancer. About 9 or 10 characters should be enough, for example:
'below' is the string I have found, but then I want to display context for my users, like this:
'if I sat below the deck'
My current code is
if (stristr($order, $en[$i])) {
$lit= "".$en[$i]."";
$order = str_replace($en[$i], $lit, $order, $count);
$total = $total + $count;
$sub[$loc[$i]] = $sub[$loc[$i]] + $count;
$carreau[$loc[$i]] = $carreau[$loc[$i]]."".$lit." ";
}
Thank you so much for any help.
You want something like $context = substr($order,from,length)
How to calculate from and length?
Use stripos (and arithmetic) to calculate from. Beware it isn't less than 0. Review substr doc for the why).
Use strlen (of the "needle") and arithmetic to determine the length.

Regex matching a date and time

I'm trying to match a specific datetime format in PHP's regex:
dd-mm-YYYY HH:ii:ss
It should always be in that format. Meaning that for example when it is the first day of the month there must be a leading zero. E.g.:
01-01-2013 01:01:01
I tried it with the following pattern:
^[0-12]{2}-[0-31]{2}-[0-9]{4} [0-23]{2}:[0-59]{2}:[0-59]{2}$
But the above pattern fails on timestamps like: 09-05-2013 19:45:10.
http://rubular.com/r/eGBAhwiNCR
I understand this may not be the correct approach to validate a date time like this, but I really want to know what is wrong with the above.
[0-12]{2} matches not the numbers 0 till 12. Instead it's a character class allowing 0 to 1 and also the number 2. The subsequent quantifier just allows the repetition of those, meanding 0,1 or 2 repeated two times.
Your other placeholders follow the same non-functioning scheme.
It's best to resort to \d{2} or \d{4} if you can't google a better regex. Even better yet, just use DateTime to verify the format.
The problem is when you are checking the "ranges", for example [0-12] at the beginning. That is a character class, and it is telling the regex to match 0 through 1, and then 2. So if you added more numbers in after the 1st one, it isn't working as you are expecting. Changing your regex slightly (focused on the [0-12] initial), [0-319]{2}-[0-12]{2}-[0-9]{4} [0-23]{2}:[0-59]{2}:[0-59]{2}$, would match 09-01-2011 11:11:10.
Ensuring there are valid numbers for each of those spaces requires a little thinking outside the box. The regex:
(0[1-9]|[12][\d]|3[0-2])-(0[1-9]|1[0-2])-[\d]{4} (0[1-9]|1[\d]|2[0-3]):(0[1-9]|[1-5][\d]):(0[1-9]|[1-5][\d])$
will work for what you are expecting with the regex you attempted.
If you break it down into smaller pieces it makes sense (it looks really scary at the beginning). Looking at the first piece (0-31 for "days").
(0[1-9]|[12][\d]|3[0-2])
This is using an or to handle 3 different cases.
0[1-9] - a zero followed by any number between 1-9. We don't want [0-9]{2} since that will allow numbers like 00. So a number is valid if it starts with 0 and has any other number after it (for single digit days).
[12][\d] - a 1 or 2 followed by any digit. This allows the numbers 10-29 to be valid.
3[0-2] - a 3 followed by anything 0 through 2 matching 30, 31, and 32.
Broken down, it's not too bad but this pattern is then carried out for each "field" in your date. So this regex validates on each field being valid... but a better way to confirm valid dates maybe needed. This doesn't get into the complexity of checking if you can have 30-02 for example, where February doesn't have 30 days.
^[0-9]{2}-[0-9]{2}-[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}$
The example of validation is in php but the regex is standard
/*pass the date you wanna validate as parameter to the function.
The function returns true if it is valid and false if the date passed is not valid
*/
function DateValid($date){
//format will be fr if the date is in french format and en if the date is in en format
$format='';
//regex that tests if the date is in french format or english, if not in one of these two then it is not valid
if(preg_match("#^(\d{1,2})[\-./ ](\d{1,2})[\-./ ](\d{4})(?: (\d{1,2})(?:[ .-](\d{1,2})){1,2})?$#",$date,$m)){
$format='fr';
}elseif (preg_match('#^(\d{4})[-. ](\d{1,2})[-. ](\d{1,2})(?: (\d{1,2})(?:[ .-](\d{1,2})){1,2})?$#', $date, $m)) {
$format='en';
}else{
echo '<p style="font-size:150px">not english nor french</p>';
return false;
}
//If it is french format or English then check if the date is correct
if($format=='fr'){
if (checkdate($m[2], $m[1], $m[3]) == false || $m[4] >= 24 || $m[5] >= 60 || $m[6] >= 60) {
echo '<p style="font-size:150px">Not valid french</p>';
return false;
}else{
echo '<p style="font-size:150px">Valid french</p>';
return true;
}
}elseif($format=='en'){
if (checkdate($m[2], $m[3], $m[1]) == false || $m[4] >= 24 || $m[5] >= 60 || $m[6] >= 60) {
echo '<p style="font-size:150px">Not valid english</p>';
return false;
}else{
echo '<p style="font-size:150px">Valid english</p>';
return true;
}
}
}

How to convert a "decimal string" into an integer without the period in PHP

If I have, say, 8.1 saved as a string/plaintext, how can I change that into the integer (that I can do addition with) 81? (I've got to remove the period and change it into an integer. I can't seem to figure it out even though I know it should be simple. Everything I try simply outputs 1.)
You can also try this
$str = '8.1';
$int = filter_var($str, FILTER_SANITIZE_NUMBER_INT);
echo $int; // 81
echo $int+1; // 82
DEMO.
If you're dealing with whole numbers (as you said), you could use the intval function that is built into PHP.
http://php.net/manual/en/function.intval.php
So basically, once you have your string parsed and setup as a whole number you can do something like:
intval("81");
And get back the integer 81.
Example:
$strNum = "81";
$intNum = intval($strNum);
echo $intNum;
// "81"
echo getType($intNum);
// "integer"
Since php does auto-casting, this should work:
<?php
$str="8432.145522";
$val = str_replace('.','', $str);
print $str." : ".$val;
?>
Output:
8432.145522 : 8432145522
Not sure if this will work. But if you always have something.something,(like 1.1 or 4.2), you can multiply by 10 and do intval('string here'). But if you have something.somethingsomething or with more somethings(like 1.42 and 5.234267, etc.), I don't know what to say. Maybe a function to keep multiplying by ten until it's an integer with is_int()?
Sources:
http://php.net/manual/en/function.intval.php
http://php.net/manual/en/function.is-int.php
Convert a string to a double - is this possible?

preg_match for mysql date format

im trying to validate a date to see if it matchs the mysql format
this is the code
$match = "/^\d{4}-\d{2}-\d{2} [0-2][0-3]:[0-5][0-9]:[0-5][0-9]$/";
$s = $this->input->post("report_start"). " " . $this->input->post("report_start_time").":00";
$e = $this->input->post("report_end"). " " . $this->input->post("report_end_time").":59";
if($this->input->post("action") != "")
{
echo trim($s). " => " . preg_match($match, trim($s));
echo "<br>";
echo trim($e). " => " . preg_match($match, trim($e));
}
the date format goes into $s and $e are
$s = 2011-03-01 00:00:00
$e = 2011-03-01 23:59:59
and they both return false (0).
i tested the pattern on http://www.spaweditor.com/scripts/regex/index.php and it returns true (1)
http://pastebin.com/pFZSKYpj
however if i manual inter the date strings into preg_match like
preg_match($match, "2011-03-01 00:00:00")
it works.
i have no idea what im doing wrong
======================
now that i think about it, i only need to validate the houre:min part of the datetime string.
im manually adding the seconds and the date is forced by a datepicker and users cant edit it
You're making your work harder that it needs to be. In php there are many date handling functions that mean you don't have to treat dates like strings. So, rather than test that your input dates are in the correct format, just insist on the correct format:
$adate= date_create('January 6, 1983 1:30pm'); //date format that you don't want
$mysqldate= $adate->format("Y-m-d h:i:s");//date format that you do want
There are also functions to check that a date is a real date, like checkdate.
ok heres wat i did.
since im forcing the date format and the ending seconds of the time part
i just validated the hour:mini part using "/^2[0-3]|[01][0-9]:[0-5][0-9]$";
and if that returns true i put everything together end reconstructed the final datetime string
$match = "/^2[0-3]|[01][0-9]:[0-5][0-9]$/";
$s_d = $this->input->post("report_start");
$s_t = $this->input->post("report_start_time");
$e_d = $this->input->post("report_end");
$e_t = $this->input->post("report_end_time");
if($this->input->post("action") != "")
{
if(
( preg_match($match , trim($s_d." ".$s_t.":00")) )
&& ( preg_match($match , trim($e_d." ".$e_t.":59")) )
)
{
$r = $this->model_report->client_hours_logged(array($s,$e));
$data['report'] = $r;
var_dump($r);
//$this->load->view("report/client_hours_per_client",$data);
}
}
Watch out:
[0-2][0-3] is not a good regex for hour values - it will match 01, 12, 23 and others, but it will fail 04 through 09 and 14 through 19.
Better use (2[0-3]|[01][0-9]) instead.
I use this to validate a 'Y-m-d H:i:s' format date string:
match = '/^[12][0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[01]) ([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/';
You could use strtotime and date to parse and format the date properly.
Why not just simply force the date into the format you want:
$e = '2011-03-01 00:00:00';
$mysqlFormat = date('Y-m-d H:i:s', strtotime($e));
Also, there is a bit of an error in your regex [0-2][0-3]:[0-5][0-9]:[0-5][0-9] will only match the hours of 00,01,02,03,10,11,12,13,20,21,22,23 so it will never match 4am, or 3pm among others. That aside I looked over your RegEx and I don't see any problems with it matching the test cases you've offered. I would check to make sure there is not extra whitespace on either side of date string with trim().
I concur with Tim : MySQL behaves in quirks mode and always tries to go easy on DATE and DATE_TIME column types. You can omit certain parts of your input and it still will try to compensate and achieve that goal successfully to some degree... That's why, most numbers your Reg-ex considers as invalid, MySQL will accept as valid.

How to convert some character into numeric in php?

I need help to change a character in php.
I got some code from the web:
char dest='a';
int conv=(int)dest;
Can I use this code to convert a character into numeric? Or do you have any ideas?
I just want to show the result as a decimal number:
if null == 0
if A == 1
Use ord() to return the ascii value. Subtract 96 to return a number where a=1, b=2....
Upper and lower case letters have different ASCII values, so if you want to handle them the same, you can use strtolower() to convert upper case to lower case.
To handle the NULL case, simply use if($dest). This will be true if $dest is something other than NULL or 0.
PHP is a loosely typed language, so there is no need to declare the types. So char dest='a'; is incorrect. Variables have $ prefix in PHP and no type declaration, so it should be $dest = 'a';.
Live Example
<?php
function toNumber($dest)
{
if ($dest)
return ord(strtolower($dest)) - 96;
else
return 0;
}
// Let's test the function...
echo toNumber(NULL) . " ";
echo toNumber('a') . " ";
echo toNumber('B') . " ";
echo toNumber('c');
// Output is:
// 0 1 2 3
?>
PS:
You can look at the ASCII values here.
It does indeed work as in the sample, except that you should be using php syntax (and as a sidenote: the language that code you found most probably was, it did not do the same thing).
So:
$in = "123";
$out = (int)$in;
Afterwards the following will be true:
$out === 123
This may help you:
http://www.php.net/manual/en/function.ord.php
So, if you need the ASCII code you will need to do:
$dest = 'a';
$conv = ord($dest);
If you want something like:
a == 1
b == 2
.
.
.
you should do:
$dest = 'a';
$conv = ord($dest)-96;
For more info on the ASCII codes: http://www.asciitable.com/
And for the function ord: http://www.php.net/manual/en/function.ord.php
It's very hard to answer because it's not a real question but just a little bit of it.
But if you ask.
It seems you need some translation table, that defines links between letters and numbers
A -> 2
B -> 3
C -> 4
S -> 1
or whatever.
You can achieve this by using an array, where keys would be these letters and values - desired numbers.
$defects_arr = array(
'A' -> 2,
'B' -> 3,
'C' -> 4'
'S' -> 1
};
Thus, you can convert these letters to numbers
$letter = 'A';
$number = $defects_arr($letter);
echo $number; // outputs 1
But it still seems is not what you want.
Do these defect types have any verbose equivalents? If so, why not to use them instead of letters?
Telling the whole story instead of little bit of it will help you to avoid mistakes and will save a ton of time, both yours and those who to answer.
Out of this question, if you are looking for convert RT0005 to 5
$max = 'RT0005';
return base_convert($max,10,10);
// return 5

Categories