Solved

# Calendars and Units

• 4 replies
• 92 views

• Enthusiast
• 8 replies

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 , 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
+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
+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]:

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.

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.