Calculate age in years, months and days

I'll post the full code below in case anyone is interested. This allows to calculate the age in years, months and days from the date of birth specified by the user to the current day (today).

The code works from a button on the toolbar, in JScript mode. I would really appreciate it if someone identifies a bug and lets me know, or if they have any suggestions.

Before I finish I want to thank everyone who helped me write this code, @Jon, @Leo , @lxp and very especially @bytespiller, not only for everything he helped me but also for everything he taught me!!!

function OnClick(clickData)
{
	var dlg = clickData.func.Dlg;
	
	//Birthdate
	var date1String = dlg.getString("Enter birthdate (YYYY-MM-DD):");
	if (!date1String) {
		return;
	}

	//Convert birthdate (text) to true date (Date object)
	var date1Array = date1String.split("-");
	var yearString = date1Array[0];
	var monthString = date1Array[1];
	var dayString = date1Array[2];
	var date1 = new Date(yearString, monthString - 1, dayString);

	//Current date
    var date2 = new Date();
	if (!date2) {
		return;
	}

	//Customize dates to show in the result (YYYY-MM-DD format, and days and months with 2 digits (0 to the left))
	var yearF1 = date1.getFullYear();
	var monthF1 = ("0" + (date1.getMonth()+1)).slice(-2);
	var dayF1 = ("0" + date1.getDate()).slice(-2);
	var date1Short = yearF1 + "-" + monthF1 + "-" + dayF1

	var yearF2 = date2.getFullYear();
	var monthF2 = ("0" + (date2.getMonth()+1)).slice(-2);
	var dayF2 = ("0" + date2.getDate()).slice(-2);
	var date2Short = yearF2 + "-" + monthF2 + "-" + dayF2
	
    //Calculate time
    var difference = date2 - date1; //In milliseconds
    var total_days = Math.floor(difference / 24 * 60 * 60 * 1000); //In days

	//Error message if birthdate > current date
	if(difference < 0){
	dlg.title = "Current age";
	dlg.message = "Error: Birthdate must be less than current date.\n\nBirthdate: " + date1Short + "\nCurrent date: " + date2Short;
	dlg.icon = "error";
	dlg.buttons = "OK";
	dlg.Show();
	return;
    }

	//Calculate age
	var age = new Date(0);
	age.setMilliseconds(date2 - date1);

	var years = age.getFullYear() - 1970;
	var months = age.getMonth();
	var days = age.getDate();

	//Ignore 0 values and set singular or plural
	var SEPARATOR = ", ";
	function que(value, singular, plural) {
		if (!value) {
			return "";
		}
		var suffix = (Math.abs(value) > 1) ? plural : singular;
		return value + " " + suffix + SEPARATOR;
	}

	var str_years = que(years, "year", "years");
	var str_months = que(months, "month", "months");
	var str_days = que(days, "day", "days");

	var str_total = (str_years + str_months + str_days).slice(0, -SEPARATOR.length);
	var result = str_total || "Born today";

	//Show result
	dlg.title = "Current age";
	dlg.message = "Birthdate:      " + date1Short + "\nCurrent age: " + date2Short + "\n\nEdad: " + result;
	dlg.icon = "info";
	dlg.buttons = "OK";
	dlg.Show();
  }

Calculate age....dcf (5.1 KB)

@fkast The code is ready!

@Leo now that this topic is solved, you could change the name to make it more intuitive and can help more people, for example "Calculate age in years, months and days". Thank you

is there a mistake in 1 day?

image

and it seems to me that you wanted to rename the directory based on the results of the script. did it work?

@fkast here I was also giving 1 day difference, +1 day, I commented with @lxp, that's why I put the -1 in the var days = age.getDate()-1; line. Try to reverse that situation by leaving the line like this var days = age.getDate(); I hope it works for you.

Regarding the renaming, what I wanted initially was that, when selecting a photo, a script, based on the birthdate that I had specified internally, would calculate the age of that person on the day the photo was taken, that is, datetaken - birthdate, and yes, I got that result, the script is available at...

@fkast With the corrected line var days = age.getDate();

2023-08-24 07 54 07

image

Oi @qiuqiu, the same thing is happening with you it was happening here with me, it's giving you + 1 day, solve it by modifying this line var days = age.getDate(); to var days = age.getDate() - 1;

I don't know why this behavior, for some people + 1 day, for others -1 day?!?

Timezone issue?

I really don't know the reason for that 1 day variation on some computers?

I have added the "Nuevo cĂĄlculo" (New calculation) button to the result window to be able to perform new calculations, but I have not been able to assign it its action, which would be to re-execute all the code.

I would also like, if possible, to move the button to the far left, and if it's not difficult, keep the window always on top. Can someone help me?!?

01

Hi @bytespiller Could you help me here please?

Hi, please paste your code and I'll take a look.

Hi @bytespiller thank you very much!

function OnClick(clickData)
{
	var dlg = clickData.func.Dlg;
	
	//Fecha nacimiento
	var fecha1_texto = dlg.getString("Fecha nacimiento (DD-MM-AAAA):");
	if (!fecha1_texto) {
		return;
	}

	//Covertir fecha 1 (texto) en fecha verdadera (objeto Date)
	var fecha1_texto = fecha1_texto.split("-");
	var dia_f1 = fecha1_texto[0];
	var mes_f1 = fecha1_texto[1];
	var anio_f1 = fecha1_texto[2];
    var fecha1 = new Date(anio_f1, mes_f1 -1, dia_f1);

	//Fecha actual
    var fecha2 = new Date();
	if (!fecha2) {
		return;
	}

	//Fraccionar las fechas para establecer las condiciones
	var df1 = fecha1.getDate();
	var mf1 = fecha1.getMonth()+1;
	var af1 = fecha1.getFullYear();

	var df2 = fecha2.getDate();
	var mf2 = fecha2.getMonth()+1;
	var af2 = fecha2.getFullYear();

	//Personalizar fechas a mostrar en el resultado (Formato DD-MM-AAAA, y dĂ­as y meses con 2 dĂ­gitos (0 a la izquierda))
	var diaF1 = ("0" + df1).slice(-2);
	var mesF1 = ("0" + mf1).slice(-2);
	var anioF1 = af1;
	var fecha1Corta = diaF1 + "-" + mesF1 + "-" + anioF1;
	
	var diaF2 = ("0" + df2).slice(-2);
	var mesF2 = ("0" + mf2).slice(-2);
	var anioF2 = af2;
	var fecha2Corta = diaF2 + "-" + mesF2 + "-" + anioF2;

    //Calcular tiempo
    var diferencia = fecha2 - fecha1; //En milisegundos
    var total_dias = Math.floor(diferencia / 24 * 60 * 60 * 1000); //En dĂ­as

    //Mensaje de error si fecha1 > fecha2
	if(diferencia < 0){
	dlg.title = "Edad actual";
	dlg.message = "Error: La fecha de nacimiento tiene que ser menor que la fecha actual.\n\nFecha nacimiento: " + fecha1Corta + "\nFecha actual:        " + fecha2Corta;
	dlg.icon = "error";
	dlg.buttons = "Aceptar";
	dlg.Show();
	return;
    }

	//Calcular años
	var anios = ((mf1 == mf2 && df2 >= df1) || (mf2 > mf1)) ? (af2 - af1) : (af2 - af1 -1);

	//Calcular meses
	var mf2 = (mf1 <= mf2) ? mf2 : (mf2 + 12); //Cuando mf2 sea menor que mf1, a mf2 + 12 para facilitar las condiciones y los cĂĄlculos
	var meses = (mf1 == mf2) ? 0 : (df2 >= df1) ? (mf2 - mf1) : (mf2 - mf1 -1);

	//Calcular dĂ­as
	var febrero = (af1 % 4 == 0 && af1 % 100 != 0) ? 29 : 28; // Si año fecha1 es bisiesto, febrero = 29 días, sino 28 días
	var ultimo_dia_meses = [31, febrero, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
	var ultimo_dia_mes_fecha1 = ultimo_dia_meses.slice(mf1-1, mf1);
	var dias = (df1 == df2) ? 0 : (df1 < df2) ? (df2 - df1) : (ultimo_dia_mes_fecha1 - df1 + df2);

	//Ignorar valores 0 y establecer singular o plural
	var SEPARATOR = ", ";
	function que(value, singular, plural) {
		if (!value) {
			return "";
		}
		var suffix = (Math.abs(value) > 1) ? plural : singular;
		return value + " " + suffix + SEPARATOR;
	}

	var str_anios = que(anios, "año", "años");
	var str_meses = que(meses, "mes", "meses");
	var str_dias = que(dias, "dĂ­a", "dĂ­as");

	var str_total = (str_anios + str_meses + str_dias).slice(0, -SEPARATOR.length);
	var resultado = str_total || " 0 tiempo";

	// Mostrar resultado
	dlg.title = "Edad actual";
	dlg.message = "Fecha nacimiento: " + fecha1Corta + "\nFecha actual:        " + fecha2Corta + "\n\nEdad: " + resultado;
	dlg.icon = "info";
	dlg.buttons = "Nuevo cĂĄlculo|Aceptar";
	dlg.Show();
  }

I meant the code for the dialog in your picture.

But nevermind, here's the code for that dialog along with helpful comments in the code:

	// Mostrar resultado
	dlg.title = "Edad actual";
	dlg.message = "Fecha nacimiento: " + fecha1Corta + "\nFecha actual:        " + fecha2Corta + "\n\nEdad: " + resultado;
	dlg.icon = "info";
	dlg.buttons = "Nuevo cĂĄlculo|Salir"; // Docs: https://www.gpsoft.com.au/help/opus12/index.html#!Documents/Scripting/Dialog.htm
	var sel = dlg.Show(); // After this line the execution is PAUSED until the user clicks a button. Then it resumes to the next line.
	if (sel === 1) { // Check what was clicked by the user. Number represents a clicked button from right to left (rightmost starting with 0).
		OnClick(clickData); // Fun fact: recursion depth (also known as "nested calls") of the JS is 10000, so in theory if you click "Nuevo cĂĄlculo" button 10001 times this line will then fail :)
	}

Also...

This dialog should already be on top (and modal) relative to the Opus main window. If you mean globally on top, then it's not really feasible.

1 Like

I did not understand, the code that I posted is not the one corresponding to that image?

I thought you already have the code for the dialog with the "Nuevo cĂĄlculo" button (hence your picture). Not important though.

How wonderful, everything is working very well, I don't know how to thank you so much, here I am laughing a lot with happiness, thank you very much.

Regarding trying to keep the window always on top, it was in order to be able to go to Excel pages and copy the results easily, always having the window visible, but that is not very important, the truth is that I am very, very happy, many thanks again!!!

1 Like

I'm also happy to hear it, enjoy :smiley:

Thank you very much, it's almost 4 in the morning here and I don't even feel like sleeping because I'm so happy :rofl: