给定出生日期的年龄,格式为YYYYMMDD

Fra*_*isc 261 javascript date

如果出生日期格式为YYYYMMDD,我如何计算年龄?是否可以使用该Date()功能?

我正在寻找比我现在使用的解决方案更好的解决方案:

var dob = '19800810';
var year = Number(dob.substr(0, 4));
var month = Number(dob.substr(4, 2)) - 1;
var day = Number(dob.substr(6, 2));
var today = new Date();
var age = today.getFullYear() - year;
if (today.getMonth() < month || (today.getMonth() == month && today.getDate() < day)) {
  age--;
}
alert(age);
Run Code Online (Sandbox Code Playgroud)

nav*_*een 479

试试这个.

function getAge(dateString) {
    var today = new Date();
    var birthDate = new Date(dateString);
    var age = today.getFullYear() - birthDate.getFullYear();
    var m = today.getMonth() - birthDate.getMonth();
    if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
        age--;
    }
    return age;
}
Run Code Online (Sandbox Code Playgroud)

我相信你的代码中唯一看起来粗糙的东西就是这个substr部分.

小提琴:http://jsfiddle.net/codeandcloud/n33RJ/

  • @RobG:当leaplings'庆祝'(这个问题的常见答案实际上似乎只是:'最接近实际日期的周末')他们的出生日**根据上下文不同**包括:地理区域(简单的英语) :你居住的地方),LAW(不要低估那个),宗教和个人偏好(包括团体行为):某些原因:"我出生在二月",其他原因是:"我出生的第二天2月28日"(最常见的是3月1日)http://en.wikipedia.org/wiki/February_29对于以上所有这个算法是正确的如果3月1日是需要的飞跃结果 (2认同)
  • @RobG:'加x个月'的粪坑与人类年龄概念无关.常见的人类概念是,当日历具有相同的月份#和日期#(与开始日期相比)时,年龄(InYears) - 计数器每天(无视时间)增加:因此2000-02-28至2001-02 -27 = 0年和2000-02-28至2001-02-28 = 1年.将这种"常识"扩展到闰:2000-02-29(*2000-02-28之后的那一天)到2001-02-28 =*零年*.我的评论只是说答案算法总是给出'正确的'*人类答案*如果一个人期望/同意这个逻辑用于学习. (2认同)
  • @RobG:我从来没有说过我或答案是*普遍*正确(TM).我包括了背景/司法管辖区/观点的概念.我的评论都清楚地包括一个大写*IF*(处理异常跳跃).事实上,我的第一条评论恰恰说明了我的意思,并且从未包含任何关于是非的判断.实际上我的意见澄清,什么不能从这个答案预期(为什么)(当你把它叫做"突出问题").Ps:2月31日?!? (2认同)

And*_*ock 229

我会考虑可读性:

function _calculateAge(birthday) { // birthday is a date
    var ageDifMs = Date.now() - birthday.getTime();
    var ageDate = new Date(ageDifMs); // miliseconds from epoch
    return Math.abs(ageDate.getUTCFullYear() - 1970);
}
Run Code Online (Sandbox Code Playgroud)

免责声明:这也有精确问题,因此也不能完全信任.它可以关闭几个小时,几年或夏令时(取决于时区).

相反,如果精度非常重要,我会建议使用库.此外@Naveens post,可能是最准确的,因为它不依赖于一天中的时间.


基准:http://jsperf.com/birthday-calculation/15

  • @RobG我认为从2000-02-29到2001-02-28技术上已经过了一整年,让你的答案无效.这是没有意义的,2000-02-28到2001-02-28是一年,所以2000-02-29到2001-02-28,必须不到一年. (11认同)
  • 对于像2000-02-29到2001-02-28这样的日期,它可能会返回1年时返回0年. (3认同)
  • 你没有详细说明"不精确"的含义,我认为其他信息可能会有所帮助.您可以考虑修复问题或删除答案. (3认同)
  • @RobG 其实我做到了。我还指出了比我自己更好的解决方案。我的解决方案以一种易于阅读的方式解决了这个问题,但精度问题很小,但在其目的范围内。 (2认同)

Kri*_*rph 72

重要提示:此答案不能提供100%准确的答案,根据日期约10-20小时.

没有更好的解决方案(无论如何不在这些答案中). - naveen

我当然无法抗拒接受挑战并制作比目前接受的解决方案更快更短的生日计算器的冲动.我的解决方案的要点是,数学是快速的,所以不是使用分支,而是javascript提供的日期模型来计算解决方案,我们使用精彩的数学

答案看起来像这样,比naveen快〜65%,而且要短得多:

function calcAge(dateString) {
  var birthday = +new Date(dateString);
  return ~~((Date.now() - birthday) / (31557600000));
}
Run Code Online (Sandbox Code Playgroud)

幻数:31557600000是24*3600*365.25*1000这是一年的长度,一年的长度是365天,6小时是0.25天.最后我将结果给出了最终年龄.

以下是基准测试:http://jsperf.com/birthday-calculation

要支持OP的数据格式,您可以替换+new Date(dateString);
+new Date(d.substr(0, 4), d.substr(4, 2)-1, d.substr(6, 2));

如果您能想出更好的解决方案,请分享!:-)

  • 这个答案有一个错误.把你的时钟设置为凌晨12:01.在上午12:01,如果你calcAge('2012-03-27')(今天的日期),你会得到零的答案,即使它应该等于1.这个错误存在于整个凌晨12:00.这是由于一年中有365.25天的错误陈述.它不是.我们正在处理日历年,而不是地球轨道的长度(更确切地说是365.256363天).一年有365天,除了闰年有366天.除此之外,在这样的事情上表现毫无意义.可维护性更重要. (22认同)
  • [在测试中添加了OP的代码:](http://jsperf.com/birthday-calculation/2) (2认同)

Vit*_*ski 51

随着时刻:

/* The difference, in years, between NOW and 2012-05-07 */
moment().diff(moment('20120507', 'YYYYMMDD'), 'years')
Run Code Online (Sandbox Code Playgroud)

  • @ itzmukeshy7确实,对于答案是最好的,它应该至少需要jQuery;) (11认同)
  • 简单而精确 (3认同)
  • @RicardoPontual这需要momentjs,所以不能是最好的答案. (2认同)
  • @thomaux 我知道这是个玩笑;) (2认同)

Luc*_*non 25

清洁单线解决方案ES6写道:

const getAge = birthDate => Math.floor((new Date() - new Date(birthDate).getTime()) / 3.15576e+10)

// today is 2018-06-13
getAge('1994-06-14') // 23
getAge('1994-06-13') // 24
Run Code Online (Sandbox Code Playgroud)

使用365.25天(因为闰年)

  • 非常简洁 - 你能详细说明一下 3.15576e+10 的含义吗? (2认同)
  • 是的,最好在函数前添加以下行: `constyearInMs = 3.15576e+10 // 使用 365.25 天的一年(因为闰年)` (2认同)
  • 效果很好,但有几个小时的误差范围。明天“18 岁”的用户实际上是“今天”18 岁。我知道我不应该提及一个库,但是“Day.js”就像魔法一样工作。 (2认同)

CMS*_*CMS 12

前段时间我用这个目的做了一个函数:

function getAge(birthDate) {
  var now = new Date();

  function isLeap(year) {
    return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
  }

  // days since the birthdate    
  var days = Math.floor((now.getTime() - birthDate.getTime())/1000/60/60/24);
  var age = 0;
  // iterate the years
  for (var y = birthDate.getFullYear(); y <= now.getFullYear(); y++){
    var daysInYear = isLeap(y) ? 366 : 365;
    if (days >= daysInYear){
      days -= daysInYear;
      age++;
      // increment the age only if there are available enough days for the year.
    }
  }
  return age;
}
Run Code Online (Sandbox Code Playgroud)

它需要一个Date对象作为输入,因此您需要解析'YYYYMMDD'格式化的日期字符串:

var birthDateStr = '19840831',
    parts = birthDateStr.match(/(\d{4})(\d{2})(\d{2})/),
    dateObj = new Date(parts[1], parts[2]-1, parts[3]); // months 0-based!

getAge(dateObj); // 26
Run Code Online (Sandbox Code Playgroud)


Kin*_*rgy 10

这是我的解决方案,只需传递一个可解析的日期:

function getAge(birth) {
  ageMS = Date.parse(Date()) - Date.parse(birth);
  age = new Date();
  age.setTime(ageMS);
  ageYear = age.getFullYear() - 1970;

  return ageYear;

  // ageMonth = age.getMonth(); // Accurate calculation of the month part of the age
  // ageDay = age.getDate();    // Approximate calculation of the day part of the age
}
Run Code Online (Sandbox Code Playgroud)


cr0*_*bot 8

这个问题已经有 10 多年历史了,没有人解决他们已经有 YYYYMMDD 格式的出生日期的提示?

如果过去日期和当前日期均采用 YYYYMMDD 格式,则可以非常快速地计算它们之间的年数,如下所示:

var pastDate = '20101030';
var currentDate = '20210622';
var years = Math.floor( ( currentDate - pastDate ) * 0.0001 );
// 10 (10.9592)
Run Code Online (Sandbox Code Playgroud)

您可以获得YYYYMMDD如下格式的当前日期:

var now = new Date();

var currentDate = [
    now.getFullYear(),
    ('0' + (now.getMonth() + 1) ).slice(-2),
    ('0' + now.getDate() ).slice(-2),
].join('');
Run Code Online (Sandbox Code Playgroud)


小智 6

替代解决方案,因为为什么不:

function calculateAgeInYears (date) {
    var now = new Date();
    var current_year = now.getFullYear();
    var year_diff = current_year - date.getFullYear();
    var birthday_this_year = new Date(current_year, date.getMonth(), date.getDate());
    var has_had_birthday_this_year = (now >= birthday_this_year);

    return has_had_birthday_this_year
        ? year_diff
        : year_diff - 1;
}
Run Code Online (Sandbox Code Playgroud)


Krz*_*ski 6

这对我来说是最优雅的方式:

const getAge = (birthDateString) => {
    const today = new Date();
    const birthDate = new Date(birthDateString);

    const yearsDifference = today.getFullYear() - birthDate.getFullYear();

    const isBeforeBirthday =
        today.getMonth() < birthDate.getMonth() ||
        (today.getMonth() === birthDate.getMonth() &&
            today.getDate() < birthDate.getDate());

    return isBeforeBirthday ? yearsDifference - 1 : yearsDifference;
};

console.log(getAge("2018-03-12"));
Run Code Online (Sandbox Code Playgroud)


Mar*_*pel 5

为了测试生日是否已经过去,我定义了一个辅助函数Date.prototype.getDoY,它有效地返回了年份的日期编号.其余的都是不言自明的.

Date.prototype.getDoY = function() {
    var onejan = new Date(this.getFullYear(), 0, 1);
    return Math.floor(((this - onejan) / 86400000) + 1);
};

function getAge(birthDate) {
    function isLeap(year) {
        return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
    }

    var now = new Date(),
        age = now.getFullYear() - birthDate.getFullYear(),
        doyNow = now.getDoY(),
        doyBirth = birthDate.getDoY();

    // normalize day-of-year in leap years
    if (isLeap(now.getFullYear()) && doyNow > 58 && doyBirth > 59)
        doyNow--;

    if (isLeap(birthDate.getFullYear()) && doyNow > 58 && doyBirth > 59)
        doyBirth--;

    if (doyNow <= doyBirth)
        age--;  // birthday not yet passed this year, so -1

    return age;
};

var myBirth = new Date(2001, 6, 4);
console.log(getAge(myBirth));
Run Code Online (Sandbox Code Playgroud)


小智 5

function age()
{
    var birthdate = $j('#birthDate').val(); // in   "mm/dd/yyyy" format
    var senddate = $j('#expireDate').val(); // in   "mm/dd/yyyy" format
    var x = birthdate.split("/");    
    var y = senddate.split("/");
    var bdays = x[1];
    var bmonths = x[0];
    var byear = x[2];
    //alert(bdays);
    var sdays = y[1];
    var smonths = y[0];
    var syear = y[2];
    //alert(sdays);

    if(sdays < bdays)
    {
        sdays = parseInt(sdays) + 30;
        smonths = parseInt(smonths) - 1;
        //alert(sdays);
        var fdays = sdays - bdays;
        //alert(fdays);
    }
    else{
        var fdays = sdays - bdays;
    }

    if(smonths < bmonths)
    {
        smonths = parseInt(smonths) + 12;
        syear = syear - 1;
        var fmonths = smonths - bmonths;
    }
    else
    {
        var fmonths = smonths - bmonths;
    }

    var fyear = syear - byear;
    document.getElementById('patientAge').value = fyear+' years '+fmonths+' months '+fdays+' days';
}
Run Code Online (Sandbox Code Playgroud)


Kei*_*rom 5

我只需要为自己编写这个函数 - 接受的答案相当不错,但 IMO 可以进行一些清理。这需要 dob 的 unix 时间戳,因为这是我的要求,但可以快速调整以使用字符串:

var getAge = function(dob) {
    var measureDays = function(dateObj) {
            return 31*dateObj.getMonth()+dateObj.getDate();
        },
        d = new Date(dob*1000),
        now = new Date();

    return now.getFullYear() - d.getFullYear() - (measureDays(now) < measureDays(d));
}
Run Code Online (Sandbox Code Playgroud)

请注意,我在measureDays 函数中使用了固定值31。所有计算关心的是“一年中的某一天”是时间戳的单调递增度量。

如果使用 JavaScript 时间戳或字符串,显然您需要删除 1000 因子。


rom*_*ald 5

我认为这可能只是这样:

function age(dateString){
    let birth = new Date(dateString);
    let now = new Date();
    let beforeBirth = ((() => {birth.setDate(now.getDate());birth.setMonth(now.getMonth()); return birth.getTime()})() < birth.getTime()) ? 0 : 1;
    return now.getFullYear() - birth.getFullYear() - beforeBirth;
}

age('09/20/1981');
//35
Run Code Online (Sandbox Code Playgroud)

也适用于时间戳

age(403501000000)
//34
Run Code Online (Sandbox Code Playgroud)