ObjectScript: Looping over a multidimensional global value and comparing

Hi,

I have a global that holds users name and date of birth.

I would like to loop through them and check if the date of birth is more than 2 years based on todays date

so I have ^checker("under2", "Eric David", "02-05-2018")

I want to check the birthdate based on todays date to see if it is greater than 2. How do I access the birthdate in the global

Please can you advice

I tried :

set values = $order(^checker("under2"))
set td = $zdate($horolog, 3)
set ol = $p(^checker("under2"), ",", 3) // this does not work
while (values ' = "")
{
set difdays = $system.SQL.DateDiff("d", ol, td)
if difdays > 730
{    
set ^value("greater than 2")
}
}
  • 0
  • 0
  • 266
  • 5
  • 3

Answers

Hello,

You have to navigate through subscript using $order.
Assuming your first node is "under2" and won't change, and assuming your date is "DD-MM-YYYY"

you can do:

ClassMethod TestGlobalAccess()
{
   set ^checker("under2", "Eric David", "02-05-2018") = ""
   set ^checker("under2", "Eric2 David2", "02-07-2016") = ""
   set ^checker("under2", "Name1 Name2", "07-06-2018") = ""
   set Name = ""
   for {
        set Name = $order(^checker("under2", Name))
        quit:Name=""
        set DateBirth = ""
        for {
             set DateBirth = $order(^checker("under2",Name,DateBirth))
             quit:DateBirth=""
             set CacheDateBirth = $zdateh(DateBirth,15)
             if ((+$h-CacheDateBirth)>730) {
                  write $$$FormatText("%1 with Birthdate=%2 is older than 2 years",Name,DateBirth), !
             }
        }
    }
}

I hope this help.

for date conversion I decided to convert the birthdate into Cache Date, instead of converting $horolog into "DD-MM-YYYY" format.
But your method work also.

If you have only one record you can do:

ClassMethod Test()
{
   set ^checker("under2", "Eric David", "02-05-2018") = ""
   set Name = $order(^checker("under2", ""))
   quit:Name=""
   set DateBirth = $order(^checker("under2",Name,""))
   quit:DateBirth=""
   set CacheDateBirth = $zdateh(DateBirth,15)
   if ((+$h-CacheDateBirth)>730) {
      write $$$FormatText("%1 with Birthdate=%2 is older than 2 years",Name,DateBirth), !
   }
}

I hope this help.

Cheers,

Jacques

Thank you so much Jacques. That was really helpful. I was able to build my solution

An old fashioned design:

ClassMethod TestA()
{
        s  (under,name,dob)=""
1      under=$o(^checker(under)) g:under="" end g:under'="under2" 1
2      name=$o(^checker(under,name)) g:name="" 1
3      dob=$o(^checker(under,name,dob)) g:dob="" 2
         s dob1=$zdateh(dob,15)
         if (+$h-dob1)>730 {name,?30,dob}
         g 3
end q
}

But you should take into account leap years.

In the common case:

ClassMethod TestB(underage,daysofyears)
{
       s (under,name,dob)=""
1    under=$o(^checker(under)) g:under="" end g:under'=underage 1
2    name=$o(^checker(under,name)) g:name="" 1
3    dob=$o(^checker(under,name,dob)) g:dob="" 2
      s dob1=$zdateh(dob,15)
      if (+$h-dob1)>daysofyears {name,?30,dob}
      g 3
end q
}

Hi Vladmir, thank you so much. I just saw your answer.

Why would you use GOTOs? There is no good reason to use GOTOs for anything, ever.

The main reason I use GOTOs instead of FOR loops is that,

when I use  GOTOs  I can come back (or enter) at any point of the loops,

while in the case with FOR loops  you can not start from the middle (that is, from any point in the loop).

In addition, how many operators do you count in Method A and Method B?

--------------------------------------------------------------------------------------------------------------------------------------------

ClassMethod TestA() As %String [ ZenMethod ]
{
   set under2 = ""
   for {
        set under2 = $order(^checker(under2))
        quit:under2=""
   set Name = ""
      for {
        set Name = $order(^checker(under2, Name))
        quit:Name=""
        set DateBirth = ""
        for {
             set DateBirth = $order(^checker(under2,Name,DateBirth))
             quit:DateBirth=""
             }
           }
        
}
ClassMethod TestB() As %String [ ZenMethod ]
{
       (under,name,dob)=""
1      under=$o(^checker(under)) q:under="" 
2      name=$o(^checker(under,name)) g:name="" 1
3      dob=$o(^checker(under,name,dob)) g:dob="" 2
       3   
}

--------------------------------------------------------------------------------------------------------------

Your question does not say the format of the dates. I am answering based upon dd-mm-yyyy, but it is easy enough to change for a different date format.  The big mistake in all prior answers is that they contain small errors around leap years. To compute the number of years between to dates in $HOROLOG format use $ZDATE(date2,8)-$ZDATE(date1,8)\10000.

So:

UNDER2    ; SRS 2018-12-06
    SET today=$ZDATE($HOROLOG,8)
    SET name=""
    WHILE 1 {
      SET name=$ORDER(^checker("under2",name)) QUIT:name=""  ;        [1]
      SET birthday=$ORDER(^checker("under2",name,"")) ;               [2]
      SET birthday=$ZDATEH($TRANSLATE(birthday,"-","/"),4,,,,,,,"") ; [3]
      CONTINUE:birthday=""  ;                                         [4]
      SET age=today-$ZDATE(birthday,8)\10000 ;                        [5]
      CONTINUE:age'<2  ;                                              [6]
      WRITE !,name,?22,age," ",$ZDATE(birthday,4,,4) ;                [7]
    }
    QUIT

 

[1] Advance to next name.

[2] Get the first birthday. The structure allows multiple birthdays, but the code only looks at the first birthday.

[3] Convert the birthday from dd-mm-yyyy format to $HOROLOG format.

[4] Skip badly formatted birthdays.

[5] Compute the age in whole years.

[6] Skip people whose age is >= 2.

[7] Do something with people whose age is less than 2.