Validate datetime input for scheduling - php

I have a scheduling system school project,
I need to create a function that validates the date entered by the user,
check if it is 2 days ahead, not Sunday and it is between working hours.
Im using codeigniter framework.
//my controller looks like this:
public function checkDateTimeInput(){
$dateTimeInput = $this->input->post('dateTimeInput');
if($dateTimeInput /*Greater than 2 days or more*/ && /*not sunday*/ && /*between 8AM-5PM*/){
return true;
}else{
return false;
}
}
//in my view:
<?php echo form_open('schedules/checkDateTimeInput'); ?>
<input type="datetime-local" name="dateTimeInput">
<input type="submit" value="submit">
</form>

For completion's sake, I'm going to consider <input type="datetime-local" name="dateTimeInput"> as the input.
So this basically creates this format:
d/m/Y h:i A
I tried it on my browser (Chrome) and it does that. More info here also:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local
So taking that into consideration, you can use createFromFormat to parse the input and use DateTime class.
$input = DateTimeImmutable::createFromFormat('d/m/Y h:i A', $dateTimeInput);
$dt = new DateTime; // now
if (
($input >= $input->setTime(8, 0) && $input <= $input->setTime(17, 0)) && // time is between 8 to 5
$input->format('l') !== 'Sunday' && // is not sunday
$dt->diff($input)->d >= 2 // is greater or more than two days
) {
return true;
}
return false;
Here's a sample output
Sidenote: I should also point out that type="datetime-local" is not supported in Firefox browser and should consider using a real date time plugin instead. If the user happens to use Firefox, you should prepare a fall back.

You can use below function and call it from your controller.
function checkDateConditions( $dateTimeInput ) {
//Make DateTime Object using the input
$inputDate = new DateTime( $dateTimeInput );
//Get the Hour from the Date Input
$inputHour = $inputDate->format('G');
//Check Time is between 8AM and 5PM ( 5PM is = 17)
if( $inputHour < 8 || $inputHour > 17) {
return false;
}
//This Returns 7 for Sunday
$dayOfWeek = $inputDate->format('N');
//If its Sunday we return false
if( $dayOfWeek == 7) {
return false;
}
//Calculate Date Difference
$now = new DateTime( Date('Y-m-d') );
$diff = $inputDate->diff($now);
//If date difference is greater than 2 days return false
if( $diff->days > 2 ) {
return false;
}
//If it reaches here it means all conditions are met so retrun true.
return true;
}

Related

True only on Weekdays and at a specific time

I am using PHP 7.4.1 and Laravel Framework 6.20.12 with the carbon library.
I want to return true only once from Monday to Friday if a date crosses the $sendPost variable. My cron-job runs every 5 Minutes.
I tried:
<?php
require 'vendor/autoload.php';
use Carbon\Carbon;
function checkMsgFired() {
$now = Carbon::now();
// $now = Carbon::createFromFormat('d/m/Y H:i:s', "19/1/2021 14:43:00");
$lastSendPost = Carbon::createFromFormat('d/m/Y H:i:s', "18/1/2021 14:43:00"); // the posting has already happended today
$post = array();
$post['Frequency'] = "MoToFr"; // send only from monday to friday at a specific date once
$post['sendPost'] = Carbon::createFromFormat('H:i:s', "14:40:00"); // when the post should be send
if($post['Frequency'] === "MoToFr") {
// if it is a WEEKDAY
if($now->dayOfWeek !== Carbon::SATURDAY or $now->dayOfWeek !== Carbon::SUNDAY) {
// $lastPosting didn't happen today
if(!$lastSendPost->isToday() && $now->gt($post['sendPost'])){
return true;
}
else{
return false;
}
} else {
return false;
}
}
}
var_dump(checkMsgFired());
However, the posting time does not seem to work. How can I check that the event has already fired once at the exact time?
Furthermore, is there an easier version to code this?
I appreciate your replies!
Something like possibly? This’ll give you true when the time is between 14:40 and 14:45, so long as your cron job runs every 5 minutes it should be mostly correct.
<?php
require 'vendor/autoload.php';
use Carbon\Carbon;
function checkMsgFired() {
$now = Carbon::now();
$frequency = "MoToFr";
$sendPost = Carbon::createFromFormat('H:i:s', "14:40:00");
if ($frequency === "MoToFr") {
if ($now->isWeekday()) {
return $now->between($sendPost, $sendPost->addMinutes(5));
}
}
return false;
}
var_dump(checkMsgFired());

Function to check user birth date is 18 years or upper not always work correctly

I am beginner webdeveloper.
I use in my project Laravel 5.8.
I have this this code:
if ($this->calcutateAge($request->input('date')) < 18) {
return Redirect::back()->withErrors(['You are a minor. Registration is allowed for adult users']);
}
function calcutateAge($dob)
{
$dob = date("Y-m-d", strtotime($dob));
$dobObject = new DateTime($dob);
$nowObject = new DateTime();
$diff = $dobObject->diff($nowObject);
return $diff->y;
}
It's work fine. But I have problem with date ex 2045-12-12.
This function is not working. With year: 2015-12-12 - it's okey.
How can I repair it?
I suggest you should use Carbon.
use Carbon\Carbon;
function calcutateAge($dob){
return \Carbon::parse($dob)->age;
}
I would write your function to return true or false depending on if the user is 18 or not.
function is_18($dob)
{
$dobObject = new DateTime(date("Y-m-d", strtotime($dob)));
$nowObject = new DateTime();
return $dobObject < $nowObject ? ($dobObject->diff($nowObject)->y > 18) : false;
}
Then your IF block is simplified to this:
if (!$this->is_18($request->input('date')) {
return Redirect::back()->withErrors(['You are a minor. Registration is allowed for adult users']);
}
I would find out when a person born 18 years ago was born, then compare to that:
function isAdult($dob) {
$adult = new DateTime('18 years ago'); // 'date' => '2002-09-01 12:05:52.000000'
$dob = date("Y-m-d", strtotime($dob));
$dobObject = new DateTime($dob);
return $adult >= $dobObject; // 2002-09-01 is after the passed date of birth
}
you can add 18 year and compare the date like this:
$dobObject = new DateTime($dob.' +18 years');
$nowObject = new DateTime();
if ($dobObject > $nowObject)
print 'great you are granted'
else
print 'sorry you are minor'
If you run var_dump($diff); you will see:
["invert"]=> int(1)
Which means is a negative difference.
So, you can do return $diff->invert? -$diff->y : $diff->y;
Of course this is a solution based on your code. You can always check if the date is someday into the future, and return false or throw some exception in this case.

Check if 24 hour formatted hour is between 2 others, over 2 days

I have a datetime, obtained by getting current time and formatting it to my user's timezone. Let's say it's "18", for 6pm in 24 hour format.
I need to have a true/false returned when checking if it falls between 15h one day, and 10h the next day. Between 3pm and the next 10am.
My code so far looks like this, but I cant get PHP to understand that the end-hour is in the next day. What am I doing wrong?!
$deviceTZ = 'America/Toronto';
$dt = new DateTime("now", new DateTimeZone($deviceTZ));
$dt->setTimestamp(time());
$deviceTime = $dt->format('H');
$silentStart = 15;
$silentEnd = 10;
$silentStartDT = date_create_from_format('H', $silentStart);
$silentEndDT = date_create_from_format('H', $silentEnd);
if($silentStartDT > $silentEndDT)
{ $silentEndDT->modify('+1 day'); }
if (($deviceTime > $silentStartDT) && ($deviceTime < $silentEndDT))
{ echo "Silent Period"; }
else { echo "Not Silent"; }
I think I may have come up with a solution
$deviceTime = new DateTime("now", new DateTimeZone($deviceTZ));
$silentStartDT = new DateTime($silentStart.":00");
$silentEndDT = (new DateTime($silentEnd.":00"))->modify('+1 day');
if($silentStart == 0 && $silentEnd == 0)
{ echo "No Silent Mode set."; }
else{
if ($deviceTime >= $silentStartDT && $deviceTime <= $silentEndDT)
{ echo "Within Range<br>"; }
}

Correctly determine if date string is a valid date in that format

I'm receiving a date string from an API, and it is formatted as yyyy-mm-dd.
I am currently using a regex to validate the string format, which works ok, but I can see some cases where it could be a correct format according to the string but actually an invalid date. i.e. 2013-13-01, for example.
Is there a better way in PHP to take a string such as 2013-13-01 and tell if it is a valid date or not for the format yyyy-mm-dd?
You can use DateTime::createFromFormat() for this purpose:
function validateDate($date, $format = 'Y-m-d')
{
$d = DateTime::createFromFormat($format, $date);
// The Y ( 4 digits year ) returns TRUE for any integer with any number of digits so changing the comparison from == to === fixes the issue.
return $d && $d->format($format) === $date;
}
[Function taken from this answer. Also on php.net. Originally written by Glavić.]
Test cases:
var_dump(validateDate('2013-13-01')); // false
var_dump(validateDate('20132-13-01')); // false
var_dump(validateDate('2013-11-32')); // false
var_dump(validateDate('2012-2-25')); // false
var_dump(validateDate('2013-12-01')); // true
var_dump(validateDate('1970-12-01')); // true
var_dump(validateDate('2012-02-29')); // true
var_dump(validateDate('2012', 'Y')); // true
var_dump(validateDate('12012', 'Y')); // false
Demo!
Determine if any string is a date
function checkIsAValidDate($myDateString){
return (bool)strtotime($myDateString);
}
Use in simple way with php prebuilt function:
function checkmydate($date) {
$tempDate = explode('-', $date);
// checkdate(month, day, year)
return checkdate($tempDate[1], $tempDate[2], $tempDate[0]);
}
Test
checkmydate('2015-12-01'); //true
checkmydate('2015-14-04'); //false
Determine if string is a date, even if string is a non-standard format
(strtotime doesn't accept any custom format)
<?php
function validateDateTime($dateStr, $format)
{
date_default_timezone_set('UTC');
$date = DateTime::createFromFormat($format, $dateStr);
return $date && ($date->format($format) === $dateStr);
}
// These return true
validateDateTime('2001-03-10 17:16:18', 'Y-m-d H:i:s');
validateDateTime('2001-03-10', 'Y-m-d');
validateDateTime('2001', 'Y');
validateDateTime('Mon', 'D');
validateDateTime('March 10, 2001, 5:16 pm', 'F j, Y, g:i a');
validateDateTime('March 10, 2001, 5:16 pm', 'F j, Y, g:i a');
validateDateTime('03.10.01', 'm.d.y');
validateDateTime('10, 3, 2001', 'j, n, Y');
validateDateTime('20010310', 'Ymd');
validateDateTime('05-16-18, 10-03-01', 'h-i-s, j-m-y');
validateDateTime('Monday 8th of August 2005 03:12:46 PM', 'l jS \of F Y h:i:s A');
validateDateTime('Wed, 25 Sep 2013 15:28:57', 'D, d M Y H:i:s');
validateDateTime('17:03:18 is the time', 'H:m:s \i\s \t\h\e \t\i\m\e');
validateDateTime('17:16:18', 'H:i:s');
// These return false
validateDateTime('2001-03-10 17:16:18', 'Y-m-D H:i:s');
validateDateTime('2001', 'm');
validateDateTime('Mon', 'D-m-y');
validateDateTime('Mon', 'D-m-y');
validateDateTime('2001-13-04', 'Y-m-d');
This option is not only simple but also accepts almost any format, although with non-standard formats it can be buggy.
$timestamp = strtotime($date);
return $timestamp ? $date : null;
The easiest way to check if given date is valid probably converting it to unixtime using strtotime, formatting it to the given date's format, then comparing it:
function isValidDate($date) {
return date('Y-m-d', strtotime($date)) === $date;
}
Of course you can use regular expression to check for validness, but it will be limited to given format, every time you will have to edit it to satisfy another formats, and also it will be more than required. Built-in functions is the best way (in most cases) to achieve jobs.
You can also Parse the date for month date and year and then you can use the PHP function checkdate() which you can read about here: http://php.net/manual/en/function.checkdate.php
You can also try this one:
$date="2013-13-01";
if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date))
{
echo 'Date is valid';
}else{
echo 'Date is invalid';
}
I'm afraid that most voted solution (https://stackoverflow.com/a/19271434/3283279) is not working properly. The fourth test case (var_dump(validateDate('2012-2-25')); // false) is wrong. The date is correct, because it corresponds to the format - the m allows a month with or without leading zero (see: http://php.net/manual/en/datetime.createfromformat.php). Therefore a date 2012-2-25 is in format Y-m-d and the test case must be true not false.
I believe that better solution is to test possible error as follows:
function validateDate($date, $format = 'Y-m-d') {
DateTime::createFromFormat($format, $date);
$errors = DateTime::getLastErrors();
return $errors['warning_count'] === 0 && $errors['error_count'] === 0;
}
Accordling with cl-sah's answer, but this sound better, shorter...
function checkmydate($date) {
$tempDate = explode('-', $date);
return checkdate($tempDate[1], $tempDate[2], $tempDate[0]);
}
Test
checkmydate('2015-12-01');//true
checkmydate('2015-14-04');//false
I have this thing that, even with PHP, I like to find functional solutions. So, for example, the answer given by #migli is really a good one, highly flexible and elegant.
But it has a problem: what if you need to validate a lot of DateTime strings with the same format? You would have to repeat the format all over the place, what goes against the DRY principle. We could put the format in a constant, but still, we would have to pass the constant as an argument to every function call.
But fear no more! We can use currying to our rescue! PHP doesn't make this task pleasant, but it's still possible to implement currying with PHP:
<?php
function validateDateTime($format)
{
return function($dateStr) use ($format) {
$date = DateTime::createFromFormat($format, $dateStr);
return $date && $date->format($format) === $dateStr;
};
}
So, what we just did? Basically we wrapped the function body in an anonymous and returned such function instead. We can call the validation function like this:
validateDateTime('Y-m-d H:i:s')('2017-02-06 17:07:11'); // true
Yeah, not a big difference... but the real power comes from the partially applied function, made possible by currying:
// Get a partially applied function
$validate = validateDateTime('Y-m-d H:i:s');
// Now you can use it everywhere, without repeating the format!
$validate('2017-02-06 17:09:31'); // true
$validate('1999-03-31 07:07:07'); // true
$validate('13-2-4 3:2:45'); // false
Functional programming FTW!
How about this one?
We simply use a try-catch block.
$dateTime = 'an invalid datetime';
try {
$dateTimeObject = new DateTime($dateTime);
} catch (Exception $exc) {
echo 'Do something with an invalid DateTime';
}
This approach is not limited to only one date/time format, and you don't need to define any function.
Validate with checkdate function:
$date = '2019-02-30';
$date_parts = explode( '-', $date );
if(checkdate( $date_parts[1], $date_parts[2], $date_parts[0] )){
//date is valid
}else{
//date is invalid
}
Tested Regex solution:
function isValidDate($date)
{
if (preg_match("/^(((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))))$/", $date)) {
return $date;
}
return null;
}
This will return null if the date is invalid or is not yyyy-mm-dd format, otherwise it will return the date.
/*********************************************************************************
Returns TRUE if the input parameter is a valid date string in "YYYY-MM-DD" format (aka "MySQL date format")
The date separator can be only the '-' character.
*********************************************************************************/
function isMysqlDate($yyyymmdd)
{
return checkdate(substr($yyyymmdd, 5, 2), substr($yyyymmdd, 8), substr($yyyymmdd, 0, 4))
&& (substr($yyyymmdd, 4, 1) === '-')
&& (substr($yyyymmdd, 7, 1) === '-');
}
To add onto the accepted answer, you can further check for a valid date or DateTime by checking if the formatted date is an instanceof DateTime.
$date = DateTime::createFromFormat('Ymd', $value);
$is_datetime = ($date instanceof DateTime);
$is_valid_datetime_format = $is_datetime
? ($date->format('Ymd') === $value)
: false;
if (!$is_datetime || !$is_valid_datetime_format) {
// Not a valid date.
return false;
}
This will catch any values that are not a DateTime such as random strings or an invalid date such as 20202020.
/**** date check is a recursive function. it's need 3 argument
MONTH,DAY,YEAR. ******/
$always_valid_date = $this->date_check($month,$day,$year);
private function date_check($month,$day,$year){
/** checkdate() is a php function that check a date is valid
or not. if valid date it's return true else false. **/
$status = checkdate($month,$day,$year);
if($status == true){
$always_valid_date = $year . '-' . $month . '-' . $day;
return $always_valid_date;
}else{
$day = ($day - 1);
/**recursive call**/
return $this->date_check($month,$day,$year);
}
}
Try and let me know it works for me
$date = \DateTime::createFromFormat('d/m/Y', $dataRowValue);
if (!empty($date)) {
//Your logic
}else{
//Error
}
if you pass any alpha or alphanumberic values it will give you the empty value in return
Regex solution
function verify_date($date){
/* correct format = "2012-09-15 11:23:32" or "2012-09-15"*/
if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])( (0[0-9]|[1-2][0-4]):(0[0-9]|[1-5][0-9]):(0[0-9]|[1-5][0-9]))?$/",$date)) {
return true;
} else {
die("Wrong date format: it should be '2012-09-15 11:23:32' or '2012-09-15', date received is: ".$date);
}
}
Try this:
$myday = '2022-1-30';
if (($timestamp = strtotime($myday)) === false) {
echo 'The string ('.$myday.') is not date';
} else {
echo 'The string ('.$myday.') is date = ' . date('l dS \o\f F Y h:i:s A', $timestamp);
}
Give this a try:
$date = "2017-10-01";
function date_checker($input,$devider){
$output = false;
$input = explode($devider, $input);
$year = $input[0];
$month = $input[1];
$day = $input[2];
if (is_numeric($year) && is_numeric($month) && is_numeric($day)) {
if (strlen($year) == 4 && strlen($month) == 2 && strlen($day) == 2) {
$output = true;
}
}
return $output;
}
if (date_checker($date, '-')) {
echo "The function is working";
}else {
echo "The function isNOT working";
}

Checking if date is weekend PHP

This function seems to only return false. Are any of you getting the same? I'm sure I'm overlooking something, however, fresh eyes and all that ...
function isweekend($date){
$date = strtotime($date);
$date = date("l", $date);
$date = strtolower($date);
echo $date;
if($date == "saturday" || $date == "sunday") {
return "true";
} else {
return "false";
}
}
I call the function using the following:
$isthisaweekend = isweekend('2011-01-01');
If you have PHP >= 5.1:
function isWeekend($date) {
return (date('N', strtotime($date)) >= 6);
}
otherwise:
function isWeekend($date) {
$weekDay = date('w', strtotime($date));
return ($weekDay == 0 || $weekDay == 6);
}
Another way is to use the DateTime class, this way you can also specify the timezone.
Note: PHP 5.3 or higher.
// For the current date
function isTodayWeekend() {
$currentDate = new DateTime("now", new DateTimeZone("Europe/Amsterdam"));
return $currentDate->format('N') >= 6;
}
If you need to be able to check a certain date string, you can use DateTime::createFromFormat
function isWeekend($date) {
$inputDate = DateTime::createFromFormat("d-m-Y", $date, new DateTimeZone("Europe/Amsterdam"));
return $inputDate->format('N') >= 6;
}
The beauty of this way is that you can specify the timezone without changing the timezone globally in PHP, which might cause side-effects in other scripts (for ex. Wordpress).
If you're using PHP 5.5 or PHP 7 above, you may want to use:
function isTodayWeekend() {
return in_array(date("l"), ["Saturday", "Sunday"]);
}
and it will return "true" if today is weekend and "false" if not.
Here:
function isweekend($year, $month, $day)
{
$time = mktime(0, 0, 0, $month, $day, $year);
$weekday = date('w', $time);
return ($weekday == 0 || $weekday == 6);
}
The working version of your code (from the errors pointed out by BoltClock):
<?php
$date = '2011-01-01';
$timestamp = strtotime($date);
$weekday= date("l", $timestamp );
$normalized_weekday = strtolower($weekday);
echo $normalized_weekday ;
if (($normalized_weekday == "saturday") || ($normalized_weekday == "sunday")) {
echo "true";
} else {
echo "false";
}
?>
The stray "{" is difficult to see, especially without a decent PHP editor (in my case). So I post the corrected version here.
For guys like me, who aren't minimalistic, there is a PECL extension called "intl".
I use it for idn conversion since it works way better than the "idn" extension and some other n1 classes like "IntlDateFormatter".
Well, what I want to say is, the "intl" extension has a class called "IntlCalendar" which can handle many international countries (e.g. in Saudi Arabia, sunday is not a weekend day). The IntlCalendar has a method IntlCalendar::isWeekend for that. Maybe you guys give it a shot, I like that "it works for almost every country" fact on these intl-classes.
EDIT: Not quite sure but since PHP 5.5.0, the intl extension is bundled with PHP (--enable-intl).
This works for me and is reusable.
function isThisDayAWeekend($date) {
$timestamp = strtotime($date);
$weekday= date("l", $timestamp );
if ($weekday =="Saturday" OR $weekday =="Sunday") { return true; }
else {return false; }
}
As opposed to testing the explicit day of the week string or number, you can also test using the relative date this weekday of the supplied date.
A direct comparison between the values is not possible without a workaround, as the use of weekday resets the time of the supplied date to 00:00:00.0000.
DateTimeInterface objects
$date->setTime(0, 0, 0) != $date->modify('this weekday');
DateTimeInterface Method
A simple method to implement to ensure the supplied date object is not changed.
function isWeekend(DateTimeInterface $date): bool
{
if ($date instanceof DateTime) {
$date = DateTimeImmutable::createFromMutable($date);
}
return $date->setTime(0,0,0) != $date->modify('this weekday');
}
isWeekend(new DateTimeImmutable('Sunday')); //true
strtotime method
With strtotime you can compare with the date('Yz') format. If the Yz value changes between the supplied date and this weekday, the supplied date is not a weekday.
function isWeekend(string $date): bool
{
return date('Yz', strtotime($dateValue)) != date('Yz', strtotime($dateValue . ' this weekday'));
}
isWeekend('Sunday'); //true
Example
https://3v4l.org/TSAVi
$sunday = new DateTimeImmutable('Sunday');
foreach (new DatePeriod($sunday, new DateInterval('P1D'), 6) as $date) {
echo $date->format('D') . ' is' . (isWeekend($date) ? '' : ' not') . ' a weekend';
}
Result
Sun is a weekend
Mon is not a weekend
Tue is not a weekend
Wed is not a weekend
Thu is not a weekend
Fri is not a weekend
Sat is a weekend

Categories