从南非身份证号码生成出生日期

Generate date of birth from South African ID number

提问人:Gee Developer 提问时间:5/13/2023 最后编辑:Solomon UckoGee Developer 更新时间:5/15/2023 访问量:851

问:

如何从南非身份证号码生成出生日期?

身份证号码的前 6 位数字代表他们的出生日期,格式为 YYMMDD。

从用户输入的身份证号码中,我想提取前 6 个字符,并用它填写出生日期,输入日期的格式dd/mm/yyyy

这是我获取前 6 位数字作为有效日期的代码:

var currDate = new Date(saIDNumber.substring(0, 2),
                        saIDNumber.substring(2, 4) - 1,
                        saIDNumber.substring(4, 6)); 
var id_date  = currDate.getDate(); 
var id_month = currDate.getMonth(); 
var id_year  = currDate.getFullYear();

该代码不会自动生成出生日期,但也不会显示任何错误。

JavaScript 日期 解析

评论

4赞 Tim Biegeleisen 5/13/2023
前 6 位数字是......我们如何知道 YY = 23 是否意味着 1923 年或 2023 年?YYMMDD
2赞 Tim Biegeleisen 5/13/2023
请回答上述评论中向您提出的问题。
2赞 Hans Kesting 5/13/2023
为什么您发布的代码不适合您?请将其添加到您的帖子中
2赞 Tim Biegeleisen 5/13/2023
@Yogi我同意这可能是一个晦涩难懂的边缘案例,事实上,那些非常年长的南非公民甚至可能没有这些数字。但我只是想从 OP 中获得规则/假设,以便有人可以给出确切的答案。
1赞 user1601324 5/14/2023
您已经为我们提供了从前 6 位数字创建日期的代码 - 您是否确认 (1) 创建了有效对象,并且 (2) 将正确的值添加到您的 3 个变量中?你用这些变量做什么?您提到了出生日期输入,但没有向我们展示该输入的任何代码,也没有向我们展示如何使用变量将它们添加到该输入中。Dateid_

答:

2赞 Chris Barr 5/15/2023 #1

重写我的答案,因为我在阅读评论后发现了一些问题!通常,您的代码可以正常工作,但 1999 年之后的日期会遇到问题,因为之后的两位数年份可以以前导零开头,这在数字中是不允许的。例如,在控制台中,运行将产生,因为它显然会尝试将这个数字转换为八进制console.log(001234)668

因此,您绝对必须将“数字”输入为数字字符串,以确保您的数据准确无误。这意味着您必须始终将这些数字保存为字符串,并将它们作为字符串传递。

说到这里,另一个问题是 1999 年之后的日期将采用“19”前缀。因此,许多人会假设 的年份是 而不是 。正如上面在评论中指出的那样,一个人有 0.025% 的机会超过 100 岁,而这个国家这么大的人甚至可能没有获得号码,这似乎可以安全地假设它们是在本世纪佩戴的。'001205'0019002000

我认为解决这个问题的一个好方法是将两位数的输入年份与当前年份的最后两位数字进行比较。当我写这个是 ,所以它变成了 .以下是一些示例202323

  • 输入年份小于,因此我们可以预置,因此全年是 。0523202005
  • 输入年份大于,因此我们可以预置,因此整年是 。2723191927

这是我的建议,它考虑到了所有这些。我还删除了对对象的需求。这意味着我们现在也不需要从月份中减去 1。我们可以从字符串中获取数字,然后将它们解析为实数。Date

function parseIdNumber(numStr){
  //if the last 2 digits of the input year are less than the last 2 of the current year
  //assume they were born after the year 2000
  var currentYearTwoDigits = parseInt(new Date().getFullYear().toString().substring(2,4), 10);
  var inputYear = parseInt(numStr.substring(0, 2), 10);
  var bestGuessYear = (inputYear < currentYearTwoDigits ? '20' : '19') + inputYear;

 return {
  day: parseInt(numStr.substring(4, 6), 10),
  month: parseInt(numStr.substring(2, 4), 10),
  year: parseInt(bestGuessYear, 10)
 }
}

console.log(parseIdNumber('541213'));
console.log(parseIdNumber('841003'));
console.log(parseIdNumber('930214'));
console.log(parseIdNumber('991205'));
console.log(parseIdNumber('000101'));
console.log(parseIdNumber('071205'));
console.log(parseIdNumber('220824'));

评论

0赞 RobG 5/15/2023
new Date(saIDNumber.substring(0, 2), ...)将所有年份都视为二十世纪。因此,自 2000 年以来出生的任何人都将被视为 100 岁以上。需要添加一些逻辑来确定年份是否应该以“19”或“20”为前缀。
1赞 Chris Barr 5/15/2023
但这个数字是南非政府的问题。当这些数字发布时,这似乎是他们的疏忽。在没有任何额外信息的情况下,任何代码都应该猜测这一点?这段代码是否应该假设它更有可能不是 100 年的历史?
0赞 Chris Barr 5/15/2023
在我写完那条评论后,我想到了一个好方法来做出这个假设,并修复我发现的一些错误。请参阅上面我修改后的答案。
1赞 RobG 5/15/2023
可能。OP 可能谨慎的做法是假设“23”代表“2023”,并添加一个复选框以选择它是否应该是 1923(或从 0 到当前年份 % 100 的任何值)。
1赞 RobG 5/15/2023
new Date(Date.now())将产生与 相同的结果。;-)new Date()
1赞 RobG 5/15/2023 #2

无需使用 Date 对象,与 OP 代码相同的结果由下式给出:

var id_date  = saIDNumber.substring(4, 6);
var id_month = saIDNumber.substring(2, 4); 
var id_year  = "19" + saIDNumber.substring(0, 2);

Date 构造函数将年份值 0 到 99 视为(请参阅步骤 5.j.ii)。1900 + year

1999 年以后出生的任何人(即 00 至 23 年)都将被视为 1900 年至 1923 年。您可能会假设任何早于当前两位数年份的 ID 年份都必须在 21 世纪,但会有一些百岁老人再次成为孩子。;-)

所以:

function getIDDate(saIDNumber) {
    let currentYear = new Date().getFullYear() % 100;
    let [year, month, day]  = saIDNumber.match(/\d\d/g);
    return `${day}/${month}/${(year <= currentYear? '20' : '19') + year}`;
}

['931205','150124'].forEach( id =>
  console.log(`${id} => ${getIDDate(id)}`)
);

这不会验证值,它们可能不表示有效日期。

附言。

new Date().getFullYear() % 100可能是,但我认为前者在获得适当的年份值方面更清楚。new Date().getYear()