Check if value is datetime - php

We are designing a new sensor that sends some data to a webapplication. We use similar sensors, but they use data channels to divide the value send to the application into different data types.
However, this new sensor will send either data or a 32 bit time, with miliseconds. It doesn't send a identifier bit to see whether the value is data or a timestamp.
Because both the data and timestamp are integer value's, How can i check which one it is?
The timestamp will be
YYYY/MM/DD HH:MI:SS:vv
I already found preg_match, like this:
if (preg_match('/[0-9]{4}-[0-9]{2}-[0-9]{2}/', $value))
But how do i include the miliseconds? Or is there a better way than a simple if else?
Update
I expect that the date recieved by the application will be in int16.
So it might be easier to count the values recieved and handle value 9 and 10 like datetimes..

You could use the createFromFormat() method from the PHP DateTime object.
You would create a function that checks the method errors :
function is_valid_date($date, $format = 'Y/m/d H:i:s.u')
{
$d = DateTime::createFromFormat($format, $date);
$errors = DateTime::getLastErrors();
return (
$errors['warning_count'] == 0 &&
$errors['error_count'] == 0 &&
$d !== false
);
}
Hope it helps.
EDIT :
Added the u (for microseconds) on the default format.

You could use this regular expression:
With preg_match_all:
preg_match_all("/(\d{4})\/(\d{2})\/(\d{2})\s(\d{2})\:(\d{2})\:(\d{2})\:(\d{2})/", $input_lines, $output_array);
With preg_match:
preg_match("/(\d{4})\/(\d{2})\/(\d{2})\s(\d{2})\:(\d{2})\:(\d{2})\:(\d{2})/", $input_line, $output_array);
Beware, it only checks for the numbers, the backslashes and the ':' character. It doesn't check if the given numbers are valid.
Once you've run the regular expression, you can then check the output array and see if it's empty or not (if it isn't empty it matched the format)
The regular expression matches this range:
0000/00/00 00:00:00:00
9999/99/99 99:99:99:99

I fixed it in a different way:
we determined that the first 2 16bit values in a message are always the timestamps, so i just made a valuecounter and used a if $value is 1 or 2 then do this, else do that.
This was a lot easier for me then to check each value.

Related

Inconsistent createFromFormat return (PHP)

This works (note the single digit ".3")
$date = DateTime::createFromFormat("*-*-*.*.*-Y-m-d-H?i.*", "backup-bla-3.3.3-2019-08-23-21h16.7z");
This fails (note the double digit ".33" :
$date = DateTime::createFromFormat("*-*-*.*.*-Y-m-d-H?i.*", "backup-bla-3.3.33-2019-08-23-21h16.7z");
This makes no sense to me. Why doesn't the * succeed in this case ?
The following also works on this specific example but I cannot make use of it as the version numbers may have double digits.
$date = DateTime::createFromFormat("*-*-*.*.??-Y-m-d-H?i.*", "backup-bla-3.3.33-2019-08-23-21h16.7z");
Why it fails when using * is clear from the manual:
Random bytes until the next separator or digit
You have two digits in a row 3 and 3 so when it reaches the second 3 your provided format is incorrect and causes an error.
The inverse is true with ** and ?? because when you have a single digit number there is no second character for the second * and ? to match.
I don't see any way around this using the available format characters. Your solution seems to be modifying that value to remove anything before the year and then using Datetime:createFromFormat().
$parts = preg_split('/(?=\d{4})/', 'backup-bla-3.3.3-2019-08-23-21h16.7z', -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
$date = DateTime::createFromFormat("Y-m-d-H?i.*", $parts[1]);
echo $date->format('c');
Demo

Laravel and Carbon - DiffInDays If Statement

I think I have a relatively simple question, I just think I'm misunderstanding an aspect of it.
I have an index page where in one of the table cells I have an if statement:
#if (Carbon\Carbon::parse($shipment->due_date)->diffInDays(false) > 0 && Carbon\Carbon::parse($shipment->due_date)->diffInDays(false) < 10)
Where the falses are is where I would like to declare that if the day is in the future, say like tomorrow compared to today, I will have a -1 returned, whereas if I refer to yesterday, I will have a 1 returned.
The problem is I am trying to use the docs but they are lining up for me no matter what sort of way I try them: http://carbon.nesbot.com/docs/#api-humandiff
However I should mention that on the same layout I can do this:
{{Carbon\Carbon::parse($shipment->due_date)->diffInDays()}}
and return the number of days in the past or future (even though both are positive) so I know the above works (in a way, but I still need the positive or negative mentioned).
You need to provide a Carbon date as the first parameter for diffInDays(). So, the logic will be:
Carbon\Carbon::parse($shipment->due_date)->diffInDays(now(), false)
Or:
now()->diffInDays(Carbon\Carbon::parse($shipment->due_date), false)
Depending on what exactly you're trying to achieve.
false as the second parameter makes the method return signed value (positive or negative).
You can use:
Carbon\Carbon::parse($shipment->due_date)->diffInDays(null, false)
in place of
Carbon\Carbon::parse($shipment->due_date)->diffInDays(false)
This is becuase method signature looks like this:
public function diffInDays(Carbon $dt = null, $abs = true)
{
$dt = $dt ?: static::now($this->getTimezone());
return (int) $this->diff($dt, $abs)->format('%r%a');
}
In addition looking at your logic I think it's too complicated. I think it would be enough to use:
#if (Carbon\Carbon::parse($shipment->due_date)->diffInDays(null, false) < 10)
the first condition is not necessary I believe
Also in case you are using Laravel 5.5 you should rather use:
Illuminate\Support\Carbon
instead of
Carbon\Carbon
in case you wanted to add some custom methods to this class.

Simple GET validation

I have GET[] input and would like to carry out their validation. The input data is always a number by. Schema. I want to make sure that the pass number and the appropriate amount - not to throw the sql query.
at this moment I am using the procedures
$cc = $_GET['cc'];
if ($cc=='') $cc='9012';$find=array("..", "/", "\\");
$replace=array("", "", "");
$cc=str_replace($find, $replace, $cc);
$eic = $_GET['eic'];
.... ect.
// where f.ex. 9012 is an real existing data (in dbase) to generate sucure sql question
GET[] variable data schema
$_GET[$cc] - always 4 digits
$_GET[$eic] - always 4 digits
$_GET[$iy] - always 4 digits
$_GET[$ir] - always 1 digit
Can you show me a better way to secure my GET?
If the query you're getting is always a digit you can use the intval() function in PHP to make sure its an int.
$eic = intval($_GET['eic']);
http://php.net/manual/en/function.intval.php
You can force numeric values by using intval().
You can't, however, represent values with a leading 0 like 0123 using this method.
If you don't have values with leading zeros use this:
<?php
$_GET['cc'] = intval($_GET['cc']);
strlen($_GET['cc']) == 4 ? $_GET['cc'] : $_GET['cc'] = 0; // Replace 0 with default/error value
// Repeat the steps above for all parameters...
?>
change in the number of digits in a variable crashes Query
Well, the whole point of validation is that you "validate" data and don't even bother disturbing your SQL database in case the data has not been validated. Why would you bother executing a query which you know to be invalid?
I don't really agree with using intval() for validation. With intval(), you're forcefully changing the value inputted by the user, which is not really validation. A better method would be to use is_int() instead.
For security? Nothing beats "Prepared Statements"
http://php.net/manual/en/pdo.prepared-statements.php

What is the best way to store user BIRTHDATES in MySQL/PHP?

What is the best way to store user BIRTHDATES in MySQL/PHP and why?
I'm currently storing it as a VARCHAR(10) in the following format:
MM-DD-YYYY
...but I have a feeling this isn't the best way, especially since I sometimes see invalid years in that field.
Please don't just say what the best method is, also explain why it's the best method so that I can be convinced to change the entire way birthdates are handled on my site, which is a huge undertaking should that be needed.
Thanks.
mySQL has a native field type for dates: DATE.
Please don't just say what the best method is, also explain why it's the best method so that I can be convinced to change the entire way birthdates are handled on my site, which is a huge undertaking should that be needed.
Not sure what further explanation to give :) If you want to store dates in a mySQL table, DATE simply is the one correct choice. It comes with optimized indexing for queries like >, < and BETWEEN, sorts fast, and can deal with any date from the years 1001-9999, so this really is the way to go.
Store it as a DATE type, since it's very efficient for both storage and operations involving the field (filtering by date, etc.).
As others have already answered: MySQL has a DATE format for just dates, but if you need a time and date there's also DATETIME and TIMESTAMP.
DATE requires 3 bytes of storage, DATETIME require 8 bytes, and TIMESTAMP requires 4.
Incidentally, INT also requires 4 bytes. If you're just using a DATE without a corresponding time - like for your birthdays - then it's not really an issue, however there is an article which presents some arguments as to why you might want to avoid using DATETIME, and I think it's worth a read. It's also worth reading over the comments as some people have noted that the suggestions in the article aren't always practical: e.g. query optimiser sometimes has trouble with date functions, and the difficulty storing dates as unix timestamps.
This Is the php part with verification do declare the Err variable to null before.
<?php
if (! isset ( $_POST ['yearOfBirth'] ) || empty ( $_POST ['yearOfBirth'] )) {
$isFormValid = FALSE;
$yearErr = "Please select year";
if (! isset ( $_POST ['monthOfBirth'] ) || empty ( $_POST ['monthOfBirth'] )) {
$isFormValid = FALSE;
$monthErr = "Please select month";
if (! isset ( $_POST ['dayOfBirth'] ) || empty ( $_POST ['dayOfBirth'] )) {
$isFormValid = FALSE;
$dateErr = "Please complete the dob";
$dob = $_POST ['yearOfBirth'] . "-" . $_POST ['monthOfBirth'] . "-" . $_POST ['dayOfBirth'];
// exit(print_r($_POST));
}
}
}
---------------------------
Here is the SQL part.
----------------------------------
$dob = $_POST["yearOfBirth"] . "-" . $_POST["monthOfBirth"] . "-" . $_POST["dayOfBirth"];
$register = "INSERT INTO tablename( dob, )
VALUES('$dob',)";
Hope this helps

CakePHP is converting MySQL integers into strings... messing up rand() function

I want to grab a random sample of data out of my database using CakePHP. Here's my function:
function categories_list()
{
$this->paginate['limit'] = 6;
$this->paginate['order'] = '';
$this->paginate['conditions'] = '';
// Sort Randomly Start
if ($this->Session->check('Category.randomSeed'))
{
$seed = $this->Session->read('Category.randomSeed');
} else {
$seed = mt_rand();
$this->Session->write('Category.randomSeed', $seed);
}
$this->paginate['order'] = sprintf('RAND(%d)', $seed);
// Sort Randomly End
$this->set('cat_ajax_items', $this->paginate('Category'));
}
The problem is, the query that Cake sends to the DB always does this to the RAND() portion, sending MySQL into a hissy fit:
ORDER BY RAND(`1235123412341`)
Testing on a manual query, it works just fine, and returns a sample when it's formatted like this:
ORDER BY RAND(1235123412341)
Is there any way to get Cake to back off of the autoformatting? Anything I put into that RAND() function gets dumped into string quotes.
Anything I put into that RAND() function gets dumped into string quotes.
No, this isn't correct. If it used string quotes then it would work fine, however backticks aren't string quotes. The problem is that CakePHP is quoting the number as if it were a column name. Try quoting the value using single quotes instead:
"RAND('%d')"
This should result in the following SQL being produced:
ORDER BY RAND('1235123412341')
This gives the same result as when you don't include the quotes.
many applications and frameworks try to use a so called smart determination of the type of variable before they insert them into a database
however, many of these also fail with integers and strings :)
because of PHP's automatic typecasting, you can do a following check: is_int('01234') and that would return TRUE - but that actually is not true - the "number" is actually a string, starting with 0 - and so it should be handled (unless manually converted into an integet before, if that's what it should be)
you will need to adjust CakePHP's database class where it checks for data types
I'm not familiar with CakePHP, but CodeIgniter did use a following check in its escape() function:
if (is_string($str))
... which I've changed to:
if (is_string($str) && (mb_strlen((int) $str) != strlen($str)))
... and now it all works :)
P.S.: I've tried using (int) $str === $str, however that always yielded incorrect result

Categories