I'm trying to validate a date in dd-mm-yyyy format, where the year should be between 1900 to 2019.
The day and month part work fine, but i'm failing with the year part. Can you pls help?
$date="31-12-2020";
if (preg_match("/^(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])-(19[0-9]{2}|20([0-1]|[0-9]){2})$/",$date)) {
echo 'True';
return true;
} else {
echo 'False';
return false;
}
This is complete script that you need; function will return true or false if given date is in range:
http://sandbox.onlinephpfunctions.com/code/c0e8108319a24ae5ecf993bb940e1f30aab53fc7
$start_date = '01-01-1900';
$end_date = '01-01-2019';
$date_from_user = '01-01-2018';
check_in_range($start_date, $end_date, $date_from_user);
function check_in_range($start_date, $end_date, $date_from_user,$format='d-m-Y')
{
// Convert to timestamp
$start_ts = DateTime::createFromFormat($format,$start_date);
$end_ts = DateTime::createFromFormat($format,$end_date);
$user_ts = DateTime::createFromFormat($format,$date_from_user);
// Check that user date is between start & end
return (($user_ts >= $start_ts) && ($user_ts <= $end_ts));
}
Your current year part 20([0-1]|[0-9]){2} for handling years 2000 to 2019 just needs little modification to make it correct. Third digit in year part can only be 0 or 1 hence it can be written as [01] and fourth digit can be any hence can be written as [0-9] and that gives us 20[01][0-9]. Following is your modified regex you can use,
^(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])-(19[0-9]{2}|20[01][0-9])$
Demo
Also, since you're just validating your text, you can convert all groups as non-capturing groups to make it little better performance wise.
^(?:0[1-9]|[1-2][0-9]|3[0-1])-(?:0[1-9]|1[0-2])-(?:19[0-9]{2}|20[01][0-9])$
Demo with non-capturing group
This think year expression should as below
19[0-9][0-9] | 20[0-1][0-9]
Related
I need to know if a date is in the current month.
Examples:
If the date is 2018-06-30 and current month is June (06), then true.
If the date is 2018-07-30 and current month is June (06), then false.
I have a list of dates with more than 1000 dates and I want to show or colorize only the dates that belongs to a current month.
You can do it all on one line. Basically convert the date in question to a PHP time, and get the month.
date('m',strtotime('2018-06-30' )) == date('m');
Using the date() function, if you pass in only the format, it'll assume the current date/time. You can pass in a second optional variable of a time() object to use in lieu of the current date/time.
I hope this helps -
$date = "2018-07-31";
if(date("m", strtotime($date)) == date("m"))
{
//if they are the same it will come here
}
else
{
// they aren't the same
}
As an alternative you could use a DateTime and for the format use for example the n to get the numeric representation of a month without leading zeros and use Y to get the full numeric representation of a year in 4 digits.
$d = DateTime::createFromFormat('Y-m-d', '2018-06-30');
$today = new DateTime();
if($d->format('n') === $today->format('n') && $d->format('Y') === $today->format('Y')) {
echo "Months match and year match";
}
Test
PHP doesn't implement a date type. If you are starting with a date/time and you know that your you are only dealing with a single timezone, AND you mean you want the current month in the curent year
$testdate=strtotime('2018-06-31 12:00'); // this will be converted to 2018-07-01
if (date('Ym')==date('Ym', $testdate)) {
// current month
} else {
// not current month
}
function get_date_diff1($from,$to,$remove_dates,$check=0){
$cDays = dateDiff($from,$to);
$tmp=$from;
$i=0;$o=0;$p=0;
while($i<$cDays){
if(in_array($tmp,$remove_dates)){
$p=$p+1;
}
$tmp=strtotime($tmp)+(($i>0)?86400:0);
$twd = strtolower(date("l",$tmp));
if($twd=='sunday' || $twd=='saturday') $o=$o+1;
$tmp = date("Y-m-d",$tmp);
$i=$i+1;
}
if($check==0){
return abs($cDays-$o-$p);
}else{
return abs($cDays-$p);
}
}
echo get_date_diff1("14 April, 2014","16 April, 2014",array('14 April, 2014'));
I'm sorry for my grammar mistakes. I want to make a function which is remove the FROM or TO date between three dates and give the result of due dates. In this function when I removing the 14 April, 2014 then function work good and give the due dates (result = 2 (which I want)) but when I removing the 15 April, 2014 then function give the three due dates (result = 3) while function should be return two dates (result = 2) can someone help me where I am wrong? Thanks in Advance
You're passing in dates in 14 April, 2014 format, which corresponds to the PHP date() format code of d F, Y. You then build dates internally in your code in Y-m-d format. That means your in_array() call is literally trying to do
if ('14 April, 2014' == '2014-04-14`) { ... }
which will NEVER be true. You and I know they're the same dates. PHP has NO idea they're dates. They're just strings, and as strings they're NOT equal.
I'm trying to use DateTime to check if a credit card expiry date has expired but I'm a bit lost.
I only want to compare the mm/yy date.
Here is my code so far
$expmonth = $_POST['expMonth']; //e.g 08
$expyear = $_POST['expYear']; //e.g 15
$rawExpiry = $expmonth . $expyear;
$expiryDateTime = \DateTime::createFromFormat('my', $rawExpiry);
$expiryDate = $expiryDateTime->format('m y');
$currentDateTime = new \DateTime();
$currentDate = $currentDateTime->format('m y');
if ($expiryDate < $currentDate) {
echo 'Expired';
} else {
echo 'Valid';
}
I feel i'm almost there but the if statement is producing incorrect results. Any help would be appreciated.
It's simpler than you think. The format of the datess you are working with is not important as PHP does the comparison internally.
$expires = \DateTime::createFromFormat('my', $_POST['expMonth'].$_POST['expYear']);
$now = new \DateTime();
if ($expires < $now) {
// expired
}
You can use the DateTime class to generate a DateTime object matching the format of your given date string using the DateTime::createFromFormat() constructor.
The format ('my') would match any date string with the string pattern 'mmyy', e.g. '0620'. Or for dates with 4 digit years use the format 'mY' which will match dates with the following string pattern 'mmyyyy', e.g. '062020'. It's also sensible to specify the timezone using the DateTimeZone class.
$expiryMonth = 06;
$expiryYear = 20;
$timezone = new DateTimeZone('Europe/London');
$expiryTime = \DateTime::createFromFormat('my', $expiryMonth.$expiryYear, $timezone);
See the DateTime::createFromFormat page for more formats.
However - for credit/debit card expiry dates you will also need to take into account the full expiry DATE and TIME - not just the month and year.
DateTime::createFromFormat will by default use todays day of the month (e.g. 17) if it is not specified. This means that a credit card could appear expired when it still has several days to go. If a card expires 06/20 (i.e. June 2020) then it actually stops working at 00:00:00 on 1st July 2020. The modify method fixes this. E.g.
$expiryTime = \DateTime::createFromFormat('my', $expiryMonth.$expiryYear, $timezone)->modify('+1 month first day of midnight');
The string '+1 month first day of midnight' does three things.
'+1 month' - add one month.
'first day of' - switch to the first day of the month
'midnight' - change the time to 00:00:00
The modify method is really useful for many date manipulations!
So to answer the op, this is what you need — with a slight adjustment to format to cater for single digit months:
$expiryMonth = 6;
$expiryYear = 20;
$timezone = new DateTimeZone('Europe/London');
$expiryTime = \DateTime::createFromFormat(
'm-y',
$expiryMonth.'-'.$expiryYear,
$timezone
)->modify('+1 month first day of midnight');
$currentTime = new \DateTime('now', $timezone);
if ($expiryTime < $currentTime) {
// Card has expired.
}
An addition to the above answers.
Be aware that by default the days will also be in the calculation.
For example today is 2019-10-31 and if you run this:
\DateTime::createFromFormat('Ym', '202111');
It will output 2021-12-01, because day 31 does not exist in November and it will add 1 extra day to your DateTime object with a side effect that you will be in the month December instead of the expected November.
My suggestion is always use the day in your code.
For op's question:
$y=15;
$m=05;
if(strtotime( substr(date('Y'), 0, 2)."{$y}-{$m}" ) < strtotime( date("Y-m") ))
{
echo 'card is expired';
}
For others with full year:
$y=2015;
$m=5;
if(strtotime("{$y}-{$m}") < strtotime( date("Y-m") ))
{
echo 'card is expired';
}
Would it not be simpler to just compare the string "201709" to the current year-month? Creating datetime objects will cost php some effort, I suppose.
if($_POST['expYear']. str_pad($_POST['expMonth'],2,'0', STR_PAD_LEFT ) < date('Ym')) {
echo 'expired';
}
edited as Adam states
The best answer is provided by John Conde above. It it does the minimum amount of processing: creates two correct DateTime objects, compares them and that's all it needs.
It could work also as you started but you must format the dates in a way that puts the year first.
Think a bit about it: as dates, 08/15 (August 2015) is after 12/14 (December 2014) but as strings, '08 15' is before '12 14'.
When the year is in front, even as strings the years are compared first and then, only when the years are equal the months are compared:
$expiryDate = $expiryDateTime->format('y m');
$currentDate = $currentDateTime->format('y m');
if ($expiryDate < $currentDate) {
echo 'Expired';
} else {
echo 'Valid';
}
Keep it simple, as the answer above me says except you need to string pad to the left:
isCardExpired($month, $year)
{
$expires = $year.str_pad($month, 2, '0', STR_PAD_LEFT);
$now = date('Ym');
return $expires < $now;
}
No need to add extra PHP load using DateTime
If you are using Carbon, which is a very popular Datetime extension library. Then this should be:
$expMonth = $_POST['month'];
$expYear = $_POST['year'];
$format_m_y = str_pad($expMonth,2,'0', STR_PAD_LEFT).'-'.substr($expYear, 2);
$date = \Carbon\Carbon::createFromFormat('m-y', $format_m_y)
->endOfMonth()
->startOfDay();
if ($date->isPast()) {
// this card is expired
}
Also take into consideration the exact date and time expiration:
Credit cards expire at the end of the month printed as its expiration date, not at the beginning. Many cards actually technically expire one day after the end of that month. In any case, unless they list a specific day of expiration along with month and year, they should work all the way through the end of their expiration month. Cardholders should not wait until the last moment to secure a replacement card. Source
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');
I have an array which will output a date. This date is outputted in the mm/dd/yyyy format. I have no control over how this outputted so I cant change this.
Array
(
[date] => 04/06/1989
)
I want to use php to check if this date matches the current date (today), but ignoring the year. So in the above example I just want to check if today is the 6th April. I am just struggling to find anything which documents how to ignore the years.
if( substr( $date, 0, 5 ) == date( 'm/d' ) ) { ...
Works only if it's certain that the month and date are both two characters long.
Came in a little late, but here’s one that doesn’t care what format the other date is in (e.g. “Sep 26, 1989”). It could come in handy should the format change.
if (date('m/d') === date('m/d', strtotime($date))) {
echo 'same as today';
} else {
echo 'not same as today';
}
this will retrieve the date in the same format:
$today = date('m/d');
Use this:
$my_date = YOUR_ARRAY[date];
$my_date_string = explode('/', $my_date);
$curr_date = date('m,d,o');
$curr_date_string = explode(',', $date);
if (($my_date_string[0] == $curr_date_string[0]) && ($my_date_string[1] == $curr_date_string[1]))
{
DO IT
}
This way, you convert the dates into strings (day, month, year) which are saved in an array. Then you can easily compare the first two elements of each array which contains the day and month.
You can use for compare duple conversion if you have a date.
$currentDate = strtotime(date('m/d',time())); --> returns current date without care for year.
//$someDateTime - variable pointing to some date some years ago, like birthday.
$someDateTimeUNIX = strtotime($someDateTime) --> converts to unix time format.
now we convert this timeunix to a date with only showing the day and month:
$dateConversionWithoutYear = date('m/d',$someDateTimeUNIX );
$dateWithoutRegardForYear = strtotime($dateConversionWithoutYear); -->voila!, we can now compare with current year values.
for example: $dateWithoutRegardForYear == $currentDate , direct comparison
You can convert the other date into its timestamp equivalent, and then use date() formatting to compare. Might be a better way to do this, but this will work as long as the original date is formatted sanely.
$today = date('m/Y', time());
$other_date = date('m/Y', strtotime('04/06/1989'));
if($today == $other_date) {
//date matched
}
hi you can just compare the dates like this
if(date('m/d',strtotime($array['date']])) == date('m/d',strtotime(date('Y-m-d H:i:s',time()))) )