Skip to content

Commit

Permalink
Integrate DateTime record from Testing lib
Browse files Browse the repository at this point in the history
... with all dependencies on Testing and DymolaModels removed
  • Loading branch information
m-kessler authored and beutlich committed Apr 11, 2020
1 parent 7aa1e43 commit e61a53f
Showing 1 changed file with 349 additions and 0 deletions.
349 changes: 349 additions & 0 deletions Modelica/Utilities/Time.mo
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ dow = dayOfWeek(now) // = 5
</html>"));
end dayOfWeek;

function daysInYear "Get number of days in year"
extends Modelica.Icons.Function;
input Integer a "Year";
output Integer days "Number of days in year a";
algorithm
days := if isLeapYear(a) then 366 else 365;
end daysInYear;

function isLeapYear "Check if a year is a leap year"
extends Modelica.Icons.Function;
input Integer year "Year";
Expand Down Expand Up @@ -148,6 +156,347 @@ days = leapDays(2000, 2020) // = 5 leap days in range [2000, 2019]
final constant String months[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"} "Array of month names";
final constant String shortMonths[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"} "Array of abbreviated month names";

operator record DateTime
extends Modelica.Icons.Record;

Integer a "Year";
Integer mon "Month";
Integer d "Day";
Integer h "Hour";
Integer min "Minute";
Integer s "Second";
Integer ms "Millisecond";

encapsulated operator 'constructor'
import Modelica.Utilities.Time.DateTime;
import Modelica.Icons;
extends Icons.FunctionsPackage;

function fromReadable
extends Icons.Function;

input Integer a "Year";
input Integer mon "Month";
input Integer d "Day";
input Integer h "Hour";
input Integer min "Minute";
input Integer s "Second";
input Integer ms "Millisecond";

output DateTime t(ms=ms, s=s, min=min, h=h, d=d, mon=mon, a=a);

algorithm

end fromReadable;

function fromSystemTime "Get system time as elapsed seconds since custom epoch year"
import Modelica.Utilities.Internal.Time.getTime;
extends Icons.Function;

output DateTime t;

protected
Integer ms "Millisecond";
Integer s "Second";
Integer min "Minute";
Integer h "Hour";
Integer d "Day";
Integer mon "Month";
Integer a "Year";

algorithm
(ms, s, min, h, d, mon, a) := getTime();
t :=DateTime(ms=ms, s=s, min=min, h=h, d=d, mon=mon, a=a);

end fromSystemTime;

function fromEpoch
import Modelica.Utilities.Internal.Time.getTime;
import Modelica.Math.nearestInteger;
import Modelica.Utilities.Time.isLeapYear;
import Modelica.Utilities.Time.daysInYear;
extends Icons.Function;

input Real seconds "Elapsed seconds since epoch_year";
input Integer epoch_year = 1970 "Reference year";
output DateTime t;

protected
Integer[2,12] days_passed = {{31,59,90,120,151,181,212,243,273,304,334,365},
{31,60,91,121,152,182,213,244,274,305,335,366}};
Real rem;
Integer days, day_of_year, counted_days;
Integer i, j;

Integer ms "Millisecond";
Integer s "Second";
Integer min "Minute";
Integer h "Hour";
Integer d "Day";
Integer mon "Month";
Integer a "Year";

algorithm

// get milliseconds
ms := nearestInteger(mod(abs(seconds),1)*1000);

// get seconds
s :=nearestInteger(mod(seconds,60));

// get minutes
rem :=seconds - s;
min :=nearestInteger(mod(rem/60, 60));

// get hours
rem :=rem - min*60;
h :=nearestInteger(mod(rem/3600, 24));

// get number of days since epoch year
rem :=rem - h*3600;
days :=nearestInteger(rem/(24*3600));

// get year
if days >= 0 then
// time is after reference year: count how many years must pass from reference year until 'days' is reached
a :=epoch_year;
counted_days := 0;
while counted_days+daysInYear(a) <= days loop
counted_days := counted_days + daysInYear(a);
a :=a + 1;
end while;
else
// time is before reference year: count years downwards
a :=epoch_year - 1;
counted_days := if isLeapYear(a) then -366 else -365;
while counted_days > days loop
a :=a - 1;
counted_days := counted_days - daysInYear(a);
end while;
end if;

// compute day in current year
day_of_year :=days - counted_days + 1;

// get month
// use correct column depending on leap and regular year
j :=if isLeapYear(a) then 2 else 1;
for i in 1:12 loop
if days_passed[j,i] >= day_of_year then
mon :=i;
break;
end if;
end for;

// get day
d :=if mon > 1 then day_of_year - days_passed[j,mon-1] else day_of_year;

t :=DateTime(ms=ms, s=s, min=min, h=h, d=d, mon=mon, a=a);

end fromEpoch;
end 'constructor';

encapsulated operator 'String' "Convert DateTime to string"
import Modelica.Utilities.Time.DateTime;
import Modelica.Utilities.Strings.replace;
import Modelica.Icons;
extends Icons.FunctionsPackage;

function formated
extends Icons.Function;

input DateTime t;
input String format = "%y-%mon-%d %H:%MIN:%S";
output String s;

protected
encapsulated function string0
import Modelica.Utilities.Strings.replace;
input Integer s;
input Integer l;
output String s0;
algorithm
s0 :=replace(String(s, minimumLength=l, leftJustified=false), " ", "0");
end string0;

algorithm
s :=replace(format, "%y", string0(t.a, l=4));
s :=replace(s, "%Y", string0(t.a, l=4));
s :=replace(s, "%mon", String(t.mon));
s :=replace(s, "%MON", string0(t.mon, l=2));
s :=replace(s, "%d", String(t.d));
s :=replace(s, "%D", string0(t.d, l=2));
s :=replace(s, "%h", String(t.h));
s :=replace(s, "%H", string0(t.h, l=2));
s :=replace(s, "%min", String(t.min));
s :=replace(s, "%MIN", string0(t.min, l=2));
s :=replace(s, "%s", String(t.s));
s :=replace(s, "%S", string0(t.s, l=2));
s :=replace(s, "%ms", String(t.ms));
s :=replace(s, "%MS", string0(t.ms, l=2));

end formated;

end 'String';

encapsulated operator function '=='
import Modelica.Utilities.Time.DateTime;
import Modelica.Icons;
extends Icons.Function;

input DateTime t1;
input DateTime t2;
output Boolean result "= t1 == t2";

algorithm
result := t1.a == t2.a and
t1.mon == t2.mon and
t1.d == t2.d and
t1.h == t2.h and
t1.min == t2.min and
t1.s == t2.s and
t1.ms == t2.ms;

end '==';

encapsulated operator function '<>'
import Modelica.Utilities.Time.DateTime;
import Modelica.Icons;
extends Icons.Function;

input DateTime t1;
input DateTime t2;
output Boolean result "= t1 <> t2";

algorithm
result := not t1 == t2;
end '<>';

encapsulated operator function '>'
import Modelica.Utilities.Time.DateTime;
import Modelica.Icons;
extends Icons.Function;

input DateTime t1;
input DateTime t2;
output Boolean result "= t1 <> t2";

algorithm
if t1.a > t2.a then
result :=true;
else
if t1.a==t2.a and t1.mon > t2.mon then
result :=true;
else
if t1.mon==t2.mon and t1.d > t2.d then
result :=true;
else
if t1.d==t2.d and t1.h > t2.h then
result :=true;
else
if t1.h==t2.h and t1.min > t2.min then
result :=true;
else
if t1.min==t2.min and t1.s > t2.s then
result :=true;
else
if t1.s==t2.s and t1.ms > t2.ms then
result :=true;
else
result :=false;
end if;
end if;
end if;
end if;
end if;
end if;
end if;
end '>';

encapsulated operator function '>='
import Modelica.Utilities.Time.DateTime;
import Modelica.Icons;
extends Icons.Function;

input DateTime t1;
input DateTime t2;
output Boolean result "= t1 >= t2";

algorithm
result :=t1 == t2 or t1 > t2;

end '>=';

encapsulated operator function '<'
import Modelica.Utilities.Time.DateTime;
import Modelica.Icons;
extends Icons.Function;

input DateTime t1;
input DateTime t2;
output Boolean result "= t1 < t2";

algorithm
result := not t1 == t2 and t2 > t1;

end '<';

encapsulated operator function '<='
import Modelica.Utilities.Time.DateTime;
import Modelica.Icons;
extends Icons.Function;

input DateTime t1;
input DateTime t2;
output Boolean result "= t1 <= t2";

algorithm
result := t1 == t2 or t1 < t2;

end '<=';

encapsulated function epoch "Convert time to elapsed seconds since custom epoch year"
import Modelica.Utilities.Time.DateTime;
import Modelica.Utilities.Time.isLeapYear;
import Modelica.Icons;
extends Icons.Function;

input DateTime t;
input Integer epoch_year = 1970 "Reference year";
output Real seconds "Elapsed seconds since epoch_year";

protected
Integer[2,12] days_passed = {{0,31,59,90,120,151,181,212,243,273,304,334},
{0,31,60,91,121,152,182,213,244,274,305,335}};
Integer leap_days, day_of_year;
Integer leap_years_til_epoch;
Integer j;

// Aux variables for shorter access in code
Integer ms=t.ms "Millisecond";
Integer s=t.s "Second";
Integer min=t.min "Minute";
Integer h=t.h "Hour";
Integer d=t.d "Day";
Integer mon=t.mon "Month";
Integer a=t.a "Year";

algorithm
// get leap years from year 0 until the chosen epoch year
leap_years_til_epoch :=integer(epoch_year/4) - integer((epoch_year)/100) + integer((epoch_year)/400);

// get leap days of passed years since epoch year
leap_days :=integer((a-1)/4) - integer((a-1)/100) + integer((a-1)/400) - leap_years_til_epoch;

// get current day of year and consider leap day if current year is leap year and february has passed
day_of_year :=d + days_passed[j,mon];
j := if isLeapYear(a) then 2 else 1;

seconds :=ms/1000 + s + 60*(min + 60*(h + 24*(day_of_year-1 + leap_days + 365*(a-epoch_year))));

end epoch;

end DateTime;
annotation (
Documentation(info="<html>
<p>
Expand Down

0 comments on commit e61a53f

Please sign in to comment.