Calculate time elpased

Hello community,

Is there a simple library for calculating the time elapsed between two time format string?
I have a date string on a barcode and i would like to check if the barcode has expired, older than 7 days, by comparing today’s date with the date on the barcode.
Thanks in advance

2 Likes

for there is no variable type for date in hsl, there is no simple calculation like in other language, you have to write these calculation in hsl or write COM to extend function of hsl.

I write the hsl script to do the calculation

function DaysInMonth(variable y, variable m) variable
{
   if(m==1 || m==3 || m==5 || m==7 || m==8 || m==10 || m==12) return(31);
   if(m==2){
      if(y%4==0 && y%100!=0) return (29);
      if(y%400==0) return (29);
      return (28);
   }
   return (30);
}
function CompareDate(variable y, variable m, variable d, variable y1, variable m1, variable d1) variable{
   if(y>y1) return(1);   if(y<y1) return(-1);
   if(m>m1) return(1);   if(m<m1) return(-1);
   if(d>d1) return(1);   if(d<d1) return(-1);
   return(0);
}
function DasyBetween(string d1, string d2) variable{
   variable days(0);
   variable cp(0);
   variable y,m,d,cy,cm,cd,i,j;
   y=IVal(d1.Mid(0,4));
   m=IVal(d1.Mid(4,2));
   d=IVal(d1.Mid(6,2));
   cy=IVal(d2.Mid(0,4));
   cm=IVal(d2.Mid(4,2));
   cd=IVal(d2.Mid(6,2));
   cp=CompareDate(y,m,d, cy, cm, cd);
   if(cp==0) return (0);
   if(cp<0){
      for(i=y;i<=cy;i++){
         for(j=1;j<=12;j++){
            if((i==y && j<m) || (i==cy && j>cm)) days=days+0;
            else if(i==y && j==m && i==cy && j==cm) days=days+cd-d;
            else if(i==y && j==m) days=days+DaysInMonth(i,j)-d;
            else if(i==cy && j==cm) days=days+cd;
            else days=days+DaysInMonth(i,j);
         }
      }
      return(days);
   }
   else{
      for(i=cy;i<=y;i++){
         for(j=1;j<=12;j++){
            if((i==cy && j<cm) || (i==y && j>m)) days=days+0;
            else if(i==cy && j==cm && i==y && j==m) days=days+d-cd;
            else if(i==cy && j==cm) days=days+DaysInMonth(i,j)-cd;
            else if(i==y && j==m) days=days+d;
            else days=days+DaysInMonth(i,j);
         }
      }
      return(-days);
   }
}
method main()
{
   string barcode("20230105");
   variable days(0);
   string date("");
   date=GetDate("%Y%m%d");
   Trace(DasyBetween(barcode, date));
   Trace(DasyBetween(date, barcode));
   return;
}

2 Likes

#ifndef __HSL_ExpirationTimeCalc_hsl__
#define __HSL_ExpirationTimeCalc_hsl__	1

namespace ExpirationTimeCalc
{
function DaysInMonth(variable y, variable m) variable
{
   if(m==1 || m==3 || m==5 || m==7 || m==8 || m==10 || m==12) return(31);
   if(m==2){
      if(y%4==0 && y%100!=0) return (29);
      if(y%400==0) return (29);
      return (28);
   }
   return (30);
}
function CompareDate(variable y, variable m, variable d, variable y1, variable m1, variable d1) variable{
   if(y>y1) return(1);   if(y<y1) return(-1);
   if(m>m1) return(1);   if(m<m1) return(-1);
   if(d>d1) return(1);   if(d<d1) return(-1);
   return(0);
}
function DasyBetween(string d1, string d2) variable{
   variable days(0);
   variable cp(0);
   variable y,m,d,cy,cm,cd,i,j;
   y=IVal(d1.Mid(0,4));
   m=IVal(d1.Mid(4,2));
   d=IVal(d1.Mid(6,2));
   cy=IVal(d2.Mid(0,4));
   cm=IVal(d2.Mid(4,2));
   cd=IVal(d2.Mid(6,2));
   cp=CompareDate(y,m,d, cy, cm, cd);
   if(cp==0) return (0);
   if(cp<0){
      for(i=y;i<=cy;i++){
         for(j=1;j<=12;j++){
            if((i==y && j<m) || (i==cy && j>cm)) days=days+0;
            else if(i==y && j==m && i==cy && j==cm) days=days+cd-d;
            else if(i==y && j==m) days=days+DaysInMonth(i,j)-d;
            else if(i==cy && j==cm) days=days+cd;
            else days=days+DaysInMonth(i,j);
         }
      }
      return(days);
   }
   else{
      for(i=cy;i<=y;i++){
         for(j=1;j<=12;j++){
            if((i==cy && j<cm) || (i==y && j>m)) days=days+0;
            else if(i==cy && j==cm && i==y && j==m) days=days+d-cd;
            else if(i==cy && j==cm) days=days+DaysInMonth(i,j)-cd;
            else if(i==y && j==m) days=days+d;
            else days=days+DaysInMonth(i,j);
         }
      }
      return(-days);
   }
}

}
#endif

You can bulit a library HSL. Then at method import this library. And use direct.


2

3 Likes

@Huajiang and @colobe,
Thanks you very much for the suggestions. This is really an elegant way to tackle that problem. I am going to give it a try.

make following modifications, these useless functions can be hide.

#ifndef __HSL_ExpirationTimeCalc_hsl__
#define __HSL_ExpirationTimeCalc_hsl__	1

namespace ExpirationTimeCalc
{
   #ifndef HSL_RUNTIME
      function DasyBetween(string d1, string d2) variable;
   #endif
   #ifdef HSL_RUNTIME
      function DaysInMonth(variable y, variable m) variable
      {
         if(m==1 || m==3 || m==5 || m==7 || m==8 || m==10 || m==12) return(31);
         if(m==2){
            if(y%4==0 && y%100!=0) return (29);
            if(y%400==0) return (29);
            return (28);
         }
         return (30);
      }
      function CompareDate(variable y, variable m, variable d, variable y1, variable m1, variable d1) variable{
         if(y>y1) return(1);   if(y<y1) return(-1);
         if(m>m1) return(1);   if(m<m1) return(-1);
         if(d>d1) return(1);   if(d<d1) return(-1);
         return(0);
      }
      function DasyBetween(string d1, string d2) variable{
         variable days(0);
         variable cp(0);
         variable y,m,d,cy,cm,cd,i,j;
         y=IVal(d1.Mid(0,4));
         m=IVal(d1.Mid(4,2));
         d=IVal(d1.Mid(6,2));
         cy=IVal(d2.Mid(0,4));
         cm=IVal(d2.Mid(4,2));
         cd=IVal(d2.Mid(6,2));
         cp=CompareDate(y,m,d, cy, cm, cd);
         if(cp==0) return (0);
         if(cp<0){
            for(i=y;i<=cy;i++){
               for(j=1;j<=12;j++){
                  if((i==y && j<m) || (i==cy && j>cm)) days=days+0;
                  else if(i==y && j==m && i==cy && j==cm) days=days+cd-d;
                  else if(i==y && j==m) days=days+DaysInMonth(i,j)-d;
                  else if(i==cy && j==cm) days=days+cd;
                  else days=days+DaysInMonth(i,j);
               }
            }
            return(days);
         }
         else{
            for(i=cy;i<=y;i++){
               for(j=1;j<=12;j++){
                  if((i==cy && j<cm) || (i==y && j>m)) days=days+0;
                  else if(i==cy && j==cm && i==y && j==m) days=days+d-cd;
                  else if(i==cy && j==cm) days=days+DaysInMonth(i,j)-cd;
                  else if(i==y && j==m) days=days+d;
                  else days=days+DaysInMonth(i,j);
               }
            }
            return(-days);
         }
      }
   #endif
}
#endif

hsl is too old, and it lacks too many features of modern programming languages. If we do it in C#, two line code is enough.

    string barcode = "20240105";
    var offset = (DateTime.Now - new DateTime(int.Parse(barcode.Substring(0,4)), 
        int.Parse(barcode.Substring(4,2)), 
        int.Parse(barcode.Substring(6,2)))).Days;
1 Like

Thank providing the additional information. I was also able to hide the helper functions by just using the keyword private in front of the function. It achieves the same results as using HLS_RUNTIME declarations.
I agree with you that this much easier in other languages.
Robust testing is really needed for these function, I will try to create a function for better error handling. I noticed that if the value in d1 is not correct, let say a mislabeled barcode that contains a letter or missing characters, the function return still something. I will circle back once I have something robust.
Thanks again for the head start.

Hi @Starrif2263,

Another option is to use the HSLTime Library, which can be downloaded at this link. The list of commands can be seen in the image below:

image

Using the ‘GetTimeSpan’ command will allow input of a start time, end time, and unit (i.e. ‘days’), then will output a float of the difference between the input times. For example, the command in the image below would return a ‘7’ for the ‘l_fltTimeSpan’ variable:

image

The other functions are useful for formatting or retrieving times as strings.

Thank you,
Dan

5 Likes

@DanHartman_Hamilton,

I was pretty sure Hamilton had a library for this. It was fun though working with @Huajiang codes and creating the error handling for these function library.
Thank again for sharing @DanHartman_Hamilton.

1 Like

Update: @DanHartman_Hamilton, the HSTime library does not really work for what @Huajiang and I were talking about. It seems to require a string in a certain format (with / or - between ). For what we were talking about the time is part of the barcode string without those characters (ei 2024011 not 2024/01/11). The snippet of codes from @Huajiang are more like what I was talking about for this problem.
Thanks again.

@Starrif2263 ,

One more suggestion using the HSLTime library. As long as the barcode follows a consistent format, which appears to be the case, it is easy to convert the barcode into the date format that the library is looking for. See below:

Timespan Logic

image

Trace of results

2 Likes

Thank you @BrandonBare_Hamilton,
Immediately after I sent the response I told myself the same thing, i could rebuild the string such that it is compatible with the library. It’s always good to have options. I would admit that the way your approach, takes care of the error handling i was trying to address.

Cheers.

2 Likes

I’m trying to use the GetTimespan functionality from the example above. I downloaded and installed the library using the installer and added it to my method. When I try to run the GetTimespan function, I see the start and end dates in the trace but then I get an “class not registered” error. Any idea why this isn’t working?

image

I’m also noticing that I get the same error with the included library demo methods.

Hi @EH421,

The error you’re receiving usually occurs due to an incomplete install of the library. For the HSLTime library to work, it requires the following files to exist in the HAMILTON\Bin folder:

image

Additionally, these files need to be registered in order to work. For both of these to occur, the user account used to run the installer will need to have sufficient administrator privileges and modification access for the HAMILTON folder. I suggest checking the HAMILTON folder Security properties to ensure your user account has full control (see below) and that the account also has administrator rights (best to run the .exe by right-clicking on it and selecting “Run as administator”). In some cases, IT will be required to allow appropriate access.

image

image

Thank you,
Dan

Thank you. It looks like it installed all the files but did not place the .tlb and .dll files in the bin folder. I manually transferred them and they worked. This is what my folder structure looked like after running the installer as admin. I’m working under the assumption that those two files should’ve been installed in the bin folder but were not. Can you also tell me what the unins000.dat and .exe files are for?

image

Hi @EH421,

The unins000.dat and .exe files are used to properly uninstall software. They get placed in their respective folders during the install process. They can be ignored, as deleting them can cause software to not uninstall correctly in the future leaving behind unnecessary files. To note, I have three pairs of these files in my Bin folder for separate libraries, and confirm which library each is for by opening the .dat file in a text editor.

Thank you,
Dan