Во-первых, обратите внимание на предположение, что если, например, вы родились 1 февраля, то 1 марта следующего года вам ровно 1 месяц, даже если ваш возраст в днях составляет всего 28 - меньше, чем продолжительность средний месяц Годы также имеют переменную длину (из-за високосных лет), что означает, что ваш возраст в день рождения обычно не является точным целым числом лет. Если вы хотите указать точное количество времени, которое вы прожили в годах / месяцах / днях, см. Мой другой ответ. Но более вероятно, что вы хотите сделать это правильно, так что рождение 1 февраля означает, что каждый 1 февраля вам X лет, 0 месяцев и 0 дней, а 1-го числа любого месяца вам X лет, Y месяцев, и 0 дней.
В этом случае читайте дальше. (Примечание: следующее работает только для дат в прошлом.)
Учитывая дату рождения, (y,m,d)
, текущую дату, (ynow,mnow,dnow)
и функцию tm()
, которая дает Unix / время эпохи для данной даты , следующее выдает список элементов с указанием возраста {годы, месяцы, дни}:
t0 = y*12 + m - 1; # total months for birthdate.
t = ynow*12 + mnow - 1; # total months for Now.
dm = t - t0; # delta months.
if(dnow >= d) return [floor(dm/12), mod(dm,12), dnow-d];
dm--; t--;
return [floor(dm/12), mod(dm,12),
(tm({ynow,mnow,dnow}) - tm({floor(t/12), mod(t,12)+1, d}))/60/60/24];
Ниже приведен эквивалентный алгоритм, если вам не нравятся все этажи и моды. Но я думаю, что выше, лучше. Во-первых, он избегает вызова tm()
, когда в этом нет необходимости.
{yl, ml} = {ynow, mnow};
if(mnow < m || mnow == m && dnow < d) yl--;
if(dnow < d) ml--;
years = yl - y;
months = ml + 12*(ynow - yl) - m;
yl = ynow;
if(ml == 0) { ml = 12; yl--; }
days = (tm({ynow, mnow, dnow}) - tm({yl, ml, d}))/60/60/24;
return [years, months, days];