Calculate age in years, months and days

Can someone help me correctly enter: fecha 1?

function OnClick(clickData)
{
	var DOpusFactory = DOpus.Create();

	// Fecha de nacimiento
	var fecha1 = new Date(2017, 2 - 1, 01);
	fecha1 = DOpusFactory.Date(fecha1);

	// Fecha actual (Hoy)
	var fecha2 = DOpusFactory.Date().Format("D#dd-MM-yyyy");
	fecha2 = DOpusFactory.Date(fecha2);

	//Calcula edad	
    var diff = fecha2 - fecha1;
    if(diff <=0) return "error";
    var totalDias = Math.floor(diff / 8.64e+7);
....

Not unless you give more detail. :smiley:

Excuse me, I will give more details now :face_with_hand_over_mouth:

I want to calculate the elapsed time from a predefined date to the current date, but when executing the following code, no result is displayed, no error, I think it is because I am incorrectly specifying date 1.

function OnClick(clickData)
{
	var DOpusFactory = DOpus.Create();

	// Fecha de nacimiento
	var fecha1 = new Date(2017, 2 - 1, 01);
	fecha1 = DOpusFactory.Date(fecha1);

	// Fecha actual (Hoy)
	var fecha2 = DOpusFactory.Date().Format("D#dd-MM-yyyy");
	fecha2 = DOpusFactory.Date(fecha2);

	//Calcula edad	
    var diff = fecha2 - fecha1;
    if(diff <=0) return "error";

    var totalDias = Math.floor(diff / 8.64e+7);

    var anios = fecha2.year - fecha1.year;
    var meses = fecha2.month - fecha1.month;
    var dias = fecha2.day - fecha1.day;

    if(dias<0){
      var primerDiaProximoMes = new Date(fecha1.getFullYear(),fecha1.getMonth() +1 ,1);
      var diff = primerDiaProximoMes - fecha1;
      var diasHastaFinMes = Math.floor(diff /  (60 * 60 * 24 * 1000));
      dias = diasHastaFinMes + fecha2.getDate() - 1;
      meses--;
    }

    if(meses<0){
      meses = 12 + meses;
      anios--;
    }
	
	//Ignorar valores 0
    var strAnios = (anios != 0) ? (anios + " años, ") : "";
    var strMeses = (meses != 0) ? (meses + " meses, ") : "";
    var strDias = (dias != 0) ? (dias + " dĂ­as ") : "";
    var strTotal = (strAnios + strMeses + strDias).slice(0,-1);

    var edad = "" + (strTotal || "0 tiempo") + "";
	  
	// Mostrar el resultado
	var fecha1 = fecha1.Format("D#dd-MM-yyyy");
	var fecha2 = fecha2.Format("D#dd-MM-yyyy");
	
	dlg.title = "Edad actual";
	dlg.message = "Su edad hoy " + fecha2 + " para FN: " + fecha1 + " es:\n\n " + edad;
	dlg.icon = "info";
	dlg.buttons = "Aceptar";
	dlg.Show();
}

Avoid mixing the JScript and Opus Date objects.
Opus currently doesn't support initializing its Date object from JScript dates, so what happens is that the fecha1 variable becomes a today's date rather than what you intend.

To fix this, replace this:

// Fecha de nacimiento
var fecha1 = new Date(2017, 2 - 1, 01);
fecha1 = DOpusFactory.Date(fecha1);

with this:

// Fecha de nacimiento
var fecha1 = DOpusFactory.Date("2017-02-01"); // Real date, no month offset.

This little problem caused this line to silently exit your script:
if(diff <=0) return "error";

The reason it didn't display "error" was that you didn't invoke any of the Opus' facilities to do so.
To make it display an error in the log:
if(diff <=0) return DOpus.Output("error");

If you want it to display a message box instead, I leave that to you as an exercise.

BTW, you'll have another error after this related to the dlg object not existing. The reason for that is that it is undefined, you need to define it: var dlg = clickData.func.Dlg;

1 Like

There is also a problem in your if(dias<0){ block, if it triggers it will fail (it won't today with the current Esther's date hardcoded, but it's a ticking timebomb :slight_smile: ), but the problem here is that your calculation for that situation needs milliseconds since epoch, and I don't think Opus Date object currently supports getting that? We'll ask Leo about it...

@leo: if the Opus Date objects currently don't support getting the milliseconds since epoch value, perhaps that could be introduced in the next Opus 12 beta? While at it, it would be neat if the Opus date initialization from JScript Date could be included as well.

Those are all on the list, but not for the next beta.

Ok, in that case @dasota you can use this function to get the milliseconds since epoch from Opus dates:

function getMillis(opusDate) {
    return new Date(opusDate.year, opusDate.month - 1, opusDate.day).getTime();
}
Usage example
function OnClick(clickData)
{
	function getMillis(opusDate) {
		return new Date(opusDate.year, opusDate.month - 1, opusDate.day).getTime();
	}

	var exampleOpusDate = DOpus.Create().Date("2017-02-13");
	var millis = getMillis(exampleOpusDate);

	DOpus.Output(millis); // You can verify with: https://www.epochconverter.com/
}

In any case, please verify that you aren't mixing the JScript new Date(...) with DOpusFactory.Date(...) (you need to use the latter, not the former).

I've also seen you have problems with this: know that JScript Date objects have x.getFullYear(), x.getMonth() and x.getDay() but when you use Opus dates you need to use instead: x.year, x.month and x.day.

Also remember when using DOpusFactory.Date you don't need to offset the month.

Good luck.

Oi @bytespiller thank you very much for all the knowledge that you give me, I really learn a lot with you. I applied the changes that you indicated and the code ran wonderfully!

Let me see if I understood correctly:

if(diff <=0) return "error"; //Stop execution silently.
if(diff <=0) return DOpus.Output("error"); //Stop showing error message in the log

Now my question is, how to make that flashing red icon appear, that clicking on it opens the log? :thinking:

And the other situation would be showing a popup message, and although I did a lot of research, both here in the forum, in the manual, and in Google (error handling), I didn't find anything specific, and I would really like to know that detail, it's very important, explain to me please. :slightly_smiling_face:

I thought the "error" in if(diff <=0) return "error" was the popup message that would be displayed to the user, but I was well fooled.

About the if(days<0){ condition, I did not understand very well, what do you recommend, modify it, can it generate an error? So far the code is working fine.

About function getMillis(opusDate), yes, I'm going to apply it. The page is very interesting https://www.epochconverter.com/

Thank you very much once again for everything, greetings!!!

See in docs, you need to put a second parameter true:
DOpus.Output("some error message", true); // Parameter true means error, it will be red and the bug icon will flash.

But you already display the message box (the calculation result), so you can use that same way to display the error message (you can put dlg.icon = "error" for additional styling in that situation).

If you've eliminated all new Date(...) (replacing it with the DOpusFactory.Date(...)) and used the getMillis(x) function instead of x.getDate() then it shouldn't throw an error. If not, perhaps the condition days < 0 never triggered so the problematic section isn't executed at all.

Hi @bytespiller perfect, now I know how to enable the display of the red icon in the Status bar (true).

And to display a popup message, something like the following:

if(diff < 0){
dlg.title = "Current Age";
dlg.message = "Error: Age less than 0";
dlg.icon = "error";
dlg.buttons = "OK";
dlg.Show();
return;
}

But now I have another question, how to know the name or a preview of all the icons available for cases like these?

I already did all the replacements related to
new Date and DOpusFactory.Date and everything running great!!!

I am keeping all these "pearls" of knowledge that you give me and others, in a document so that I never forget it and can consult it at any time.

I only have to thank you, thank you and thank you!!!

Simply check the docs for the Dialog object:

Thank you very much!

Hi @bytespiller, sorry to bother you again, but when I thought the date issue was resolved, I fixed myself with an little error.

The following code calculates the age of one of my children for a certain date. I replaced new Date(...) with DOpusFactory.Date(...) and x.getDate() with getMillis(x) as you recommended and apparently everything is fine, but yesterday I noticed that specifying the date 01-01-2023 generates an error on line 38 (Object does not accept this property or method), with any other date the code works fine, what could it be, please?

function OnClick(clickData)
{
	var DOpusFactory = DOpus.Create();
	var dlg = clickData.func.Dlg;

	//Fecha de nacimiento
	var fecha1 = DOpusFactory.Date("2019-02-13");

	//Fecha de cálculo (sugiriéndose como fecha, la fecha actual
	var fecha2 = dlg.getString("Fecha de cálculo (DD-MM-AAAA):", DOpusFactory.Date().Format("D#dd-MM-yyyy")); // Se sugiere la fecha actual
	if (!fecha2) {
		return; // Si el usuario cancela o no se introduce nada, salir
	}
	fecha2 = DOpusFactory.Date(fecha2);

	//Calcula edad	
    var diff = fecha2 - fecha1;

	//Mensaje de error si fecha menor que 0
	if(diff <0){
	var fecha1 = fecha1.Format("D#dd-MM-yyyy");
	var fecha2 = fecha2.Format("D#dd-MM-yyyy");
	dlg.title = "Edad Sophia para...";
	dlg.message = "Error: Edad de cálculo tiene que ser mayor que fecha de nacimiento.\n\nFecha nacimiento: " + fecha1 + "\nFecha de cálculo:  " + fecha2;
	dlg.icon = "error";
	dlg.buttons = "Aceptar";
	dlg.Show();
	return;	
    }

    var totalDias = Math.floor(diff / 8.64e+7);

    var anios = fecha2.year - fecha1.year;
    var meses = fecha2.month - fecha1.month;
    var dias = fecha2.day - fecha1.day;

    if(dias<0){
      var primerDiaProximoMes = DOpusFactory.Date(fecha1.getFullYear(),fecha1.getMonth() +1 ,1);
      var diff = primerDiaProximoMes - fecha1;
      var diasHastaFinMes = Math.floor(diff /  (60 * 60 * 24 * 1000));
      dias = diasHastaFinMes + getMillis(fecha2) - 1;
      meses--;
    }

    if(meses<0){
      meses = 12 + meses;
      anios--;
    }
	
	//Ignorar valores 0
    var strAnios = (anios != 0) ? (anios + " años, ") : "";
    var strMeses = (meses != 0) ? (meses + " meses, ") : "";
    var strDias = (dias != 0) ? (dias + " dĂ­as ") : "";
    var strTotal = (strAnios + strMeses + strDias).slice(0,-1);

    var edad = "" + (strTotal || "0 tiempo") + "";
	  
	// Mostrar el resultado
	var fecha1 = fecha1.Format("D#dd-MM-yyyy");
	var fecha2 = fecha2.Format("D#dd-MM-yyyy");
	
	dlg.title = "Edad Sophia para la fecha";
	dlg.message = "Fecha nacimiento: " + fecha1 + "\nFecha de cálculo:  " + fecha2 + "\n\nEdad: " + edad;
	dlg.icon = "info";
	dlg.buttons = "Aceptar";
	dlg.Show();
}

fetcha1 is an Opus Date object:

var fecha1 = DOpusFactory.Date("2019-02-13");

But you're using it like a JScript Date here:

var primerDiaProximoMes = DOpusFactory.Date(fecha1.getFullYear(),fecha1.getMonth() +1 ,1);

Change that to:

var primerDiaProximoMes = DOpusFactory.Date(fecha1.year, fecha1.month+1, 1);

That will fix the error on line 38. But I suspect you'll still have a problem with the very next line, where it subtracts the two dates. (I'm not sure what the aim is with that part of the code, so I don't know what to suggest to replace it.)

1 Like

Thank you very much Leo, your help is very valuable!

Now it gives an error on line 41, as well @Leo told me, oh long-suffering life :smile:

I think you can replace:

//Calcula edad	
var diff = fecha2 - fecha1;

with:

//Calcula edad	
var diff = getMillis(fecha2) - getMillis(fecha1);

Also, if you encounter any discrepancies, verify whether the month offset (you apply elsewhere in your code) is needed or not.

From what I see, most of the errors are because I'm using the Date object in JScript and DOpusFactory modes. Well @bytespiller told me to avoid doing this. But what are the major advantages between the Date object in JScript and DOpusFactory, which one is better?

I made that change, and now it gives me an error on that line itself

//Calcula edad	
var diff = getMillis(fecha2) - getMillis(fecha1);