Jasman's blog

Jasman's blog

Dynamics AX and life

Blog about life and work as an Dynamics AX developer.

Time and dates in Axapta / Dynamics AX

WorkPosted by Jacob Sørensen Tue, September 04, 2007 14:45:30

Have you ever needed to find out the amount of time (secs, hours etc.) between to dates (date and time) in Axapta / Dynamics AX (DAX) ?

I've used this approach a couple of times, and it is actually something I concieved when I was working solely with XAL-coding (the 4GL programming languange in which the Microsoft XAL and Microsoft Dynamics C5 applications are written).

Dates in Axapta / DAX are can be in the interval 01.01.1901 to 31.12.2154.
A date can be converted in to an integer with the function date2num().

Time in Axapta / DAX is represented by an integer which denotes the number of seconds since midnight. There are 86400 seconds in 24 hours. Thus it is in the interval [0,86399].

A time/integer value can be converted to the textual representation by using the function time2str();

Now the trick is to calculate the date and the time in to one value, so that if you have two points in time and want to know the diff. between them, you can calculate the numerical values and subtract them from each other.

I use the method of calculating the date and time in to seconds by doing:

Axapta 3.0 and previous


static void itsAlive(Args _args)
{
date fromdate_,todate_;
timeOfDay fromtime_,totime_;
real secondsAlive;

fromDate_ = 18\01\1971;
toDate_ = today();
fromTime_ = str2time("15:00:00"); // Three o'clock p.m.
toTime_ = timenow();

secondsAlive = (date2num(todate_)*86400+totime_) - (date2num(fromdate_)*86400+fromtime_);
info(strfmt("I have been alive for approx. %1 seconds.",secondsAlive));
info(strfmt("I have been alive for approx. %1 hours.",secondsAlive / 3600)); // Centi hours
}

NOTE that the result of the calculation of diff in seconds is stored in a real variable.
This is because of the integer data types 32 bit signed limitation in Axapta 3.0 in earlier.

This little job will calculate the amount of seconds from 18 january 1971, 3 o'clock p.m (which happens to be my birthday), to current time.

It will print the number of seconds and the number of hours since my birth.
We calculate the numbers od seconds (actually the number of seconds since 01\01\1901) by doing:

(date2num(todate_)*86400+totime_)

making it into a numerical value (datetime value) that can be used for calculations.

By dividing the number of seconds by 3600 (which is the number of seconds in a hour) we get the value in (centi) hours.

This could be used for say:

Calculating the numbers of hours worked for billing.
Calculating the duration of a phone call for billing
Calculating the duration of a ship's stay in harbour for billing.
Etc

To go from a datetime-value back to date and time you can do:

static void back2datetime(Args _args)
{
real datetimevalue = (date2num(18\01\1971)*86400.00)+str2time('15:00:00');
// 2243289600 seconds;
date dateresult;
real days;
timeOfDay timeresult;
;

days = datetimevalue / 86400;
dateresult = num2date(days); // Important that it is a REAL or the daynumbers overflow
timeresult = datetimevalue - trunc(days) * 86400; // Which is actually datetimevalue MOD 86400


info(strfmt("The datetimevalue yields date: %1 %2 o'clock.",dateresult,time2str(timeresult,1,1)));

}

It is important that when initializing datetimevalue you multiply the daynumber with 86400.00. If you multiply by the integer 86400 without the zero fraction, the kernel converts the result of the multiplication to an integer causing a wrong result.

The reason why you can not do datetimevalue MOD 86400 is because of precision loss caused by the MOD operator which converts to datetimevalue to an integer causing a wrong result.


There is a slight difference in the way this is done in Axapta 3.0 and previous and Dynamics AX 4.0.

In Axapta 3.0 the integers are signed 32-bit integers (long) which means that the value of an integer variable is in the interval [-2,147,483,648 to 2,147,483,647].

In DAX 4.0 int64 was introduced, this means that we can actually use the true DIV and MOD operators.

This is the job to calculate the diff in seconds and hours between dates:
DAX 4.0 code:

static void itsAlive4_0(Args _args)
{
date fromdate_,todate_;
timeOfDay fromtime_,totime_;
real secondsAlive;
real datetimevalue;
int64 bigint;

date dateresult;
real days;
timeOfDay timeresult;


fromDate_ = 18\01\1971;
toDate_ = today();
fromTime_ = str2time("15:00:00"); // Three o'clock p.m.
toTime_ = timenow();

secondsAlive = (date2num(todate_)*86400.00+totime_) - (date2num(fromdate_)*86400.00+fromtime_);
info(strfmt("I have been alive for approx. %1 seconds.",secondsAlive));
info(strfmt("I have been alive for approx. %1 hours.",secondsAlive div 3600)); // Centi hours
}

This is the job to go back from seconds to date and time re-written for DAX 4.0:
DAX 4.0 code:


static void back2datetime4_0(Args _args)
{
date dateresult;
timeOfDay timeresult;
int64 bigint;
;

bigint = (date2num(18\01\1971)*86400.00+str2time('15:00:00'));
dateresult = num2date(bigint div 86400); // Important that it is a REAL or the daynumbers overflow
timeresult = bigint mod 86400; // Which is actually datetimevalue MOD 86400

info(strfmt("The datetimevalue yields date: %1 %2 o'clock.",dateresult,time2str(timeresult,1,1)));
}

  • Comments(0)//blog.fasor.dk/#post41

Finishing new build of APM

WorkPosted by Jacob Sørensen Tue, September 04, 2007 13:52:23

I am currently working on finishing a new build of thy:data's Preventive Maintenance and Service Management Module.

Pretty boring as it is trivial work just running through a check list of things to be done.

A to complete a really nice day, I have a dentist-appointment 16.00 o'clock.

Weeeeh. smiley

  • Comments(0)//blog.fasor.dk/#post40

Life suxx

WorkPosted by Jacob Sørensen Tue, September 04, 2007 13:46:40

We lost a good colleague to brain cancer this friday.

He was only 48, and leaves behind wife and two boys of 15 and 18.

We will be attending his funeral this friday.

smiley

R.I.P Ole - where ever you are.

  • Comments(0)//blog.fasor.dk/#post39

Sebastian's sick

FamilyPosted by Jacob Sørensen Wed, August 22, 2007 12:10:56

Went to the paediatric unit in Aalborg Hospital yesterday to have Sebatian checked out.

He has been having skin rashes for the past week or so, and has had treatment with penicillin. We thought he had a staph. infection, but in fact it turned out to be something called Henoch- Schönlein Purpura (HSP).

It causes skin rash, swelling and pain in joints, abdominal pain, and in severe cases it can cause kidney damage.

Sebastian has rashes and swelling, and has had abdomonal pain, but luckily there were no signs of his kidneys being stressed.

The cure ? Time and if necessary pain killers !

The disease is non-contagious, so he can attend kinder garten.
But trying to find a danish description of the disease that can be understood by ordinary people, not just doctors, so that you can inform the Kinder garten employees and the parents of the other kids, turned out to be easier said than done.

This was completely non-existent. So now I got a hold of a description form an other hospital, that I will have to have desciphered by Rikke's sister, who knows some latin and medical terms, as she is a secretary in Aalborg Hospital.

Dammit.

The not so nice thing about the disease is that I read, but I don't know if it's true, that it is caused by a genetic flaw and a mix of viruses, but it was not hereditary.
And in some cases the disease can be chronic.


So I'm, thinking does Sebastian has damaged genes ? And will he ever be cured ?

A parent's worries never end.

  • Comments(0)//blog.fasor.dk/#post38

Get Simpsonized

HumorPosted by Jacob Sørensen Fri, August 03, 2007 15:04:55

Get Simpsonized now:

Get Simpsonized

This is me:

Blog Image

  • Comments(0)//blog.fasor.dk/#post37

Holidays

FamilyPosted by Jacob Sørensen Thu, August 02, 2007 08:55:51

Visited Jumboland the other day.

Jumboland is basically an indoor playground / activity center for kids. So all the kids had a great time. We only managed to take some (not so good) photos of Rasle.

  • Comments(0)//blog.fasor.dk/#post36

Subtle but important difference

WorkPosted by Jacob Sørensen Thu, June 28, 2007 14:55:35

Been tumbling with a problem for the last few days.

A form in our Dynamics AX module for Preventive Maintenance Control was not behaving.

The form has "explicit" filter fields that the user can see without having to activate the form filter (CTRL+F3), for setting up filters most commonly used in an easy way.

And this is working ok. However at this customer site, the form has been adjusted so that the user can have the form refreshed automatically periodically, and when the users at the customer site were making use of the "explicit" filter combined with the AX's normal filtering (CTRL+F3), the form simply threw away the normal form filtering.

I discovered a subtle but very important difference between writing

<formtable>_ds.executeQuery(); (which was the way our code was doing it)

and

<formtable>_ds.Research();

The difference is that research will retain the filter ranges in the forms query as they are right now.
.executeQuery will NOT.

It is mentioned in the Developer's Guide, but I guess the responsible programmer hadn't noticed that one.

Developer's guide states:

"research vs. executeQuery

If you want to refresh the form with records that were inserted in a method or job that was called, then you should use research.

If you want to change the query to show other records, perhaps based on a modified filter, then you should use executeQuery."

  • Comments(0)//blog.fasor.dk/#post35

Haha

TechnologyPosted by Jacob Sørensen Mon, June 18, 2007 14:02:33

Robot protest.

Blog Image

There are 10 kinds of people in the world. Those who can understand binary numbers and those who do not.

  • Comments(0)//blog.fasor.dk/#post34
« PreviousNext »