Solved

Calendars and Units

  • 27 February 2020
  • 4 replies
  • 108 views

Badge

In our application, we use both a DailyCalendar and an HourlyCalendar. So we have the standard SI_Time_Duration quantity with second as a base unit and conversions to hour and day.

For the daily calendar, I want to model a period of time. So I have two element parameters EP_FirstDay and EP_LastDay with range DailyCalendar and a parameter P_LengthOfPeriod. As the length of the period is specified in days, I set the unit of it to [day].

However, if I set EP_FirstDay to the 1st of January 2020 and P_LengthOfPeriod to 1 [day], then EP_LastDay := EP_FirstDay + P_LengthOfPeriod results in 22nd of July in the year 2256 instead of the 2nd of January (which was quite surprising to me).

I understand, that P_LengthOfPeriod is converted to its base unit [s], so the above calculation actually adds 86400 days to EP_FirstDay. Of course, I could just remove the unit from P_LengthOfPeriod, but I would like to keep it, if possible.

Is there a better way of modeling these kind of situations?

Procedure PR_Example {
Body: {
EP_FirstDay := '2020-01-01';
P_LengthOfPeriod := 1 [day];

!Results in EP_LastDay = '2256-07-22' instead of '2020-01-02'
EP_LastDay := EP_FirstDay + P_LengthOfPeriod;
}
}


Quantity SI_Time_Duration {
BaseUnit: s;
Conversions: {
hour->s : #-># * 3600,
day ->s : #-># * 86400
}
Comment: "Expresses the value for the duration of periods.";
}


Calendar DailyCalendar {
Unit: day;
BeginDate: "2020-01-01";
EndDate: "4000-12-31";
TimeslotFormat: "%c%y-%m-%d";
}


ElementParameter EP_FirstDay {
Range: DailyCalendar;
}


Parameter P_LengthOfPeriod {
Range: integer;
Unit: day;
}


ElementParameter EP_LastDay {
Range: DailyCalendar;
}

 

icon

Best answer by mateusarakawa 27 February 2020, 23:24

View original

4 replies

Userlevel 5
Badge +2

Hi, @Benedikt .

 

I would try this function: MomentToString

where Elapsed argument would be your P_LengthOfPeriod.

 

remark: it returns a string, so you’ll need to cast it to the set.

Userlevel 5
Badge +2

Hi, @Benedikt . Great!

 

Could you try using [P_LengthOfPeriod.Unit], instead of P_LengthOfPeriod.Unit?

 

 

Other idea:

There is a type of object in AIMMS called “Unit Parameter”.

You can create one for LenghtOfPeriod:

Then, set the definition of this unit parameter as you wish it to be (week, days, etc):

 

And then set the P_LengthOfPeriod’s unit to UP_LengthOfPeriod and use it in the MomentToString function unit: [UP_LengthOfPeriod]:

Badge

Thank you, @mateusarakawa, this helps me.

One follow-up question:
Is there a way to dynamically use the unit of P_LengthOfPeriod as a second argument to MomentToString? Using “P_LengthOfPeriod.Unit” raises “The second argument of intrinsic function "MomentToString" is not a time unit.”. Otherwise, If I changed to unit of P_LengthOfPeriod to [week], for example, I would also need to change the calculation of EP_LastDay and loose one big advantage of units.

Badge

Using [P_LengthOfPeriod.Unit] fixed the error, thanks! But I seem to have misunderstood the second argument of MomentToString.

When I use

P_LengthOfPeriod := 2 [week];
SP_LastDay := MomentToString("%c%y-%m-%d",
[P_LengthOfPeriod.Unit],
"2020-01-01 00:00:00",
P_LengthOfPeriod);

and P_LengthOfPeriod has the unit [day], I get SP_LastDay = ‘2020-01-15’ as expected. When I change to unit of P_LengthOfPeriod in its declaration to [week], I get SP_LastDay = ‘2020-01-01’. what I don’t really understand.

When I change the calculation to 

P_LengthOfPeriod := 2 [week];
SP_LastDay := MomentToString("%c%y-%m-%d",
[day],
"2020-01-01 00:00:00",
P_LengthOfPeriod);

then everything works as expected. So that’s what I will be using.

Reply


Didn't find what you were looking for? Try searching on our documentation pages:

AIMMS Developer & PRO | AIMMS How-To | AIMMS SC Navigator