Avatar of Scott Fell
Scott FellFlag for United States of America

asked on 

PHP Function To Calculate Birthdate

I need to create a birthdate and I am only given the name of the birth month and the age. I am setting the day number to 1 because that is not given.

In other words, if I am given, "May" for the birth month and 28 for the age I would end up with 5/1/1982.  If I am given April and 28, then the birthdate would be 4/1/1983.

Below is what I have come up with and it is currently working. My question is about making this function less verbose if possible. 


echo calculateBirthDate('april',28);     #  4/1/1993  given current month is May
echo calculateBirthDate('may',28);       #  4/1/1992  given current month is May
echo calculateBirthDate('mayxyz',28);    #  NULL  given current month is May
echo calculateBirthDate('may',x1x);      #  NULL  given current month is May



function calculateBirthDate($monthName,$age){


   //CONVERT BIRTH MONTH NAME TO INTEGER
          
     $d = date_parse($monthName);
     $birthMonthNumber = $d['month'];
   
   
   //IF DATA IS BAD, RETURN NULL
        if(!$birthMonthNumber){
            return NULL;
        }
        if(is_numeric($age)){
            $age = intval($age);
        } else {
            return NULL;
        }


     
     //DETERMINE BIRTH YEAR
     $currentYear = date("Y");
     $currentMonth = date("n");
   
    if( $birthMonthNumber >= $currentMonth ){ //IF BIRTH MONTH IS CURRENT OR IN THE FUTURE, THE BIRTH YEAR SHOULD BE 1 YEAR LESS THAN IF THE BIRTH MONTH HAS ALREADY  OCCURRED.


      $birthYear = ($currentYear - $age) -1;


    } else {


      $birthYear = $currentYear - $age;


    }


   
    //CREATE DATE STRING USING 1 AS THE DAY


    $dateString = $birthMonthNumber . '/1/' . $birthYear;


    return $dateString;




}

Open in new window



PHP

Avatar of undefined
Last Comment
Chris Stanyon
Avatar of arnold
arnold
Flag of United States of America image

Why make things so complicated.
You have age and month"



Why not do it simpler.
Current year -age
If current month is before birth month, subtract an additional year.
Avatar of Daniel Pineault
Daniel Pineault

Similarly, what about something like

$age = 46;
$birth_month = 5;

if(date('m') < $birth_month){ $age = $age + 1;}
$birth_month = str_pad($birth_month, 2, '0', STR_PAD_LEFT);
echo date("Y-$birth_month-01", strtotime("today -$age years"));

Open in new window


Avatar of arnold
arnold
Flag of United States of America image

Altering $age might cause issues down the line
I.e. The person has to output the conclusion
A person whose birth month is $birth_month and age $age was born on .

Instead of adding 1 to $age setting a modifier to 1 while modifier is always starts as 0
So that current year - age - modifier
Avatar of ste5an
ste5an
Flag of Germany image

Just a comment:

I would implement this also in my own Birthdate class over DateTime. From the use case it requires some factory method doing the calculus as described by @Arnold.
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

ASKER

Daniel, that works. Just need to change line 4 to evaluate less than or equal to.

if(date('m') <= $birth_month){ $age = $age + 1;}

Open in new window

Avatar of Scott Fell
Scott Fell
Flag of United States of America image

ASKER

Why make things so complicated.

This is why I asked....
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

ASKER

I am given $birth_month = 'May'; not $birth_month = 5;

Avatar of arnold
arnold
Flag of United States of America image

I guess Iread toooooo much into a question for an algorithm.

Less than or equal will cause an issue unless you also know the day.

I.e. 22 may
Would reflect may 1999

By including the equal comparison on the month the change will reflect may 1998 which only be true if the person was born after may 8.

You could use the current day / number of days in the month *100 as a reflection of probability accuracy. .

I.e. For the example above may age 22:  Your birth month, year  is may 1999 with confidence percentage at 25%
If you want you could lean until today's less than half of the month as you tried subtract an additional year
May 1998 until it crosses may 16 to then reflect/report may 1999.

???????
ASKER CERTIFIED SOLUTION
Avatar of Daniel Pineault
Daniel Pineault

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
Avatar of arnold
arnold
Flag of United States of America image

what is the nature of data getting to your php?
If from form, you could make sure while it is presented as May in the selection, it is reported to your php script as a numeric, 5.

The other deals whether you convert the month name to numeric, before you compare or you convert the numeric obtained from date('m',....) to the name.
You could as a matter of course define an array/hash that has the months as the key
Determine element, index.
Print Date('m', strtotime 'May');
Should return 5
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

ASKER

I am given the age and birth month (written out).  For this purpose, we are putting the birth day number to 1.  

If I am given "May" and 22, then the birth date would be 5/1/1998.  If it was an April birth month and we are in May, then it would be 4/1/1999.

it is a matter of the best way to account for the birth year.  And you bring up a good point though about accuracy because if this is May 8 and they are 22 an their actual birth date is May 7 then this is off by a year. We can live with that. This data is going into a field called EstimatedBirthDate.  A small amount of error is acceptable here.  I need a way to query on age and birth month once the data is imported and having an estimated date is better than just storing an age.


Avatar of Scott Fell
Scott Fell
Flag of United States of America image

ASKER

what is the nature of data getting to your php?

This is for a flat-file that gets imported multiple times every day.  I am only given Birth Month and age and have no control over how the data is given to me.
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

ASKER

Why not do it simpler.
Current year -age
If current month is before birth month, subtract an additional year.

I am doing that in line 33 of the original code.

This data is on a flat file and on lines 18 - 25 in my code I a testing that the data is there and as expected. If not, I am just going to set the field to null as this is going to end up in a SQL Server db.


Avatar of arnold
arnold
Flag of United States of America image

Can you post a sample of how that flat file would look?
Is it
Name, month name, age in some variation of the presentation?

Or this is a statistical analysis without personal identification
Month name, age, sone selection, so eother marker, etc.



Is the file being uploaded via a web interface?
That is why you are going with php?
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

ASKER

The actual file layout does not matter other than the two fields I am using for this which are Birth Month and Age where Birth Month is the format of the month name and age is supposed to be an integer. It is possible there are rows where the data is mangled or missing.

This is part of an import process.

The code I have in my question is what I am currently using and it is working. The key is if the birth month has passed, then the birth year is the current year minus the age. If the birth month is the current month or in the future then subtract one more year.

The main item I am asking here is can you come up with a less verbose function than what I have.  It is not critical because as I said, this is working. I am always looking to improve and find something I may have missed like better using the internal function of the language.
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

ASKER

This would be sample data that is getting passed to my function.

BirthMonth, Age
April, 28
June, 52
,37
xyz,
December, xx

Open in new window

Avatar of arnold
arnold
Flag of United States of America image

I see your question was more of a validation for the approach you took versus a request for input.

Presumably you are passing values to the functions you call. higher probability of passing values versus reference where by the change in the $age and $birth_month variable within the function will not be reflected in the main process as altered.

This is my only thought on your approach.
1) Alteration of the parameters passed to the function as $age and $birth_month
2) going an extra year back if current month and the month in the data are the same. (your code line (33)  I would just either use grater than. current day through daysinmonth(Month) the range.
3) is this a guess what my Date of Birth is? or your purpose is to guesstimate the Month/Year of birth based on the criteria, or you need to also guess the day of Birth. which you could do by using the probability and radomize.  I gather the file is provided today, so you can rely on the answer month and age to be provided today.
May 28.
would mean you have 25% the day is between 1-8 and 75% 9-31
random weighted nnumber for the day.
and then based on the day of your guess you report the date as guessed day, Name of Month, year.
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

ASKER

 is this a guess what my Date of Birth is?

Kind of.  You are reading a lot into this.  I tried to use brevity but I can see how that can also throw off good thinkers.

This is a very small part of a much larger process. Knowing the actual birthdate is important. I have a field in the database for the actual birthdate that will be null for this particular import. There are other imports where the actual birthdate is known and in that case the estimated field is null in the db and the actual field is populated.  

When a query is run for contacts based on age, the actual field is used first and if that is null the estimated field is used. It is not perfect and not 100% accurate but more accurate and easier than just storing the birth month and age and having to use the same data two years down the road.

It really is as simple as passing the birth month and age like
echo calculateBirthDate('april',28);  

Open in new window

and creating a date to represent the estimated birthdate what would end up  like 4/1/1993 while at the same time checking to make sure the data is in proper form.

Avatar of arnold
arnold
Flag of United States of America image

Your code is fine, with the caveat mentioned before. removing equal sign in the comparison on line 33.

The output though using the mm/dd/yyyy outputing yyyy-mm-dd might be better, avoids ambiguity.
SOLUTION
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

ASKER

Thank you very much Chris!  I will try this out.
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

ASKER

Chris, that does work nicely.

The only change is to check if the given birth month is greater than or equal to the current month instead of greater than. Otherwise, it ends up a year younger.  These lists are typically processed prior to the birth month so it is not a big issue. If it is the same month, it will be towards the start.  Now if it was processed on the 30th of May, then everybody with birth dates from the 1st to 29th would be off by a year. There is no winning,so I am going to error on the other side with the assumption the lists are run before or at the very start of the month.


        $birthYear = (date('m') <= date('m', strtotime($month)) ? (int)date('Y') - $age - 1 : (int)date('Y') - $age);

Open in new window



Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Hey Scott,

Yeah - because you don't actually have an exact date, there's always going to be edge cases that end up a year off - there's no way around that, so you need to code it with your own 'acceptable' level of error.
PHP
PHP

PHP is a widely-used server-side scripting language especially suited for web development, powering tens of millions of sites from Facebook to personal WordPress blogs. PHP is often paired with the MySQL relational database, but includes support for most other mainstream databases. By utilizing different Server APIs, PHP can work on many different web servers as a server-side scripting language.

125K
Questions
--
Followers
--
Top Experts
Get a personalized solution from industry experts
Ask the experts
Read over 600 more reviews

TRUSTED BY

IBM logoIntel logoMicrosoft logoUbisoft logoSAP logo
Qualcomm logoCitrix Systems logoWorkday logoErnst & Young logo
High performer badgeUsers love us badge
LinkedIn logoFacebook logoX logoInstagram logoTikTok logoYouTube logo