What is a Unix Time Stamp?
As per Wikipedia, a Unix Time Stamp is a BigInteger value that represents the number of seconds that elapsed since the time 00:00:00 UTC on 1 January 1970. For example using this converter you can see that the Unix Time Stamp ‘1588400673’ represents date time ’05/02/2020 @ 6:24am (UTC)’.
Problem Description
–> As I was working at an API integration I went through an interesting task: web service uses OAuth2.0 for authentication, so first we need to generate a Bearer Token using the authentication Endpoint. In Postman request and response looks like this:
–> As you can see, the web service response has an “Expires_On” field that gives the date and time when the Token expires, in Unix Time Stamp format.
–> Now, when I am doing this request I am saving the Token and expiration details in Business Central in a setup table. The challenge is to convert the Unit Time Stamp in a DateTime and into the Local Time TimeZone.
–> Then, when we are doing web requests using this Token, we can easily compare the “Expires_On” DateTime to the current DateTime of the system in order to check if token is expired or not. If it is not expired, we just use the existing one, otherwise, we generate a new one using the above authentication Endpoint.
Coding
–> Function that calculates the Local Date Time using the Unix Time Stamp:
local procedure CalcUnixDateTime(StartDate: Date; StartTime: Time; Duration: Integer): DateTime var NoOfDays: Integer; RemDur: Duration; EndDate: Date; EndTime: Time; hoursDiff: Integer; DateTImeDotNet: DotNet DateTime; DateTImeDotNetUTC: DotNet DateTime; DurationDelta: Duration; begin IF Duration = 0 THEN BEGIN EndDate := StartDate; EndTime := StartTime; Exit(CreateDateTime(EndDate, EndTime)); END; NoOfDays := Duration DIV 86400; RemDur := Duration - (NoOfDays * 86400); EndTime := StartTime + (RemDur * 1000); EndDate := StartDate + NoOfDays; IF EndTime < StartTime THEN EndDate := EndDate + 1; DateTImeDotNet := DateTImeDotNet.Now; DateTImeDotNetUTC := DateTImeDotNetUTC.UtcNow; DurationDelta := DateTImeDotNet.Subtract(DateTImeDotNetUTC); IF DurationDelta <> 0 then EndTime += DurationDelta; Exit(CreateDateTime(EndDate, EndTime)); // UTC time converted to Local Time! end;
This function asks as parameters a StartDate, a StartTime and a Unix Time Stamp and returns the Local DateTime. Example of usage:
TestDateTime := CalcUnixDateTime(19700101D, 000000T, 1588400673); Message('%1', TestDateTime);
Result:
*Unix Time Stamp ‘1588400673’ means DateTime ’05/02/2020 @ 6:24am (UTC)’ which means ’05/02/2020 @ 9:24am’ (Local Time: Athens/Bucharest Time Zone)
So, in this example, the token was created at 8:24am local time, expires_in 3599 seconds (1 hour), meaning that expires_on is 9:24 Local Time.
Example of Usage
procedure GetOauthToken() var APITokenResultTxt: Text; JToken: JsonToken; JObject: JsonObject; DateTime: DateTime; Dur: Duration; TestDateTime: DateTime; begin TestDateTime := CalcUnixDateTime(19700101D, 000000T, 1588400673); Message('%1', TestDateTime); Exit; //for test //example of real life usage: GetAPISetup() YourSetupTable.CalcFields("Token"); IF YourSetupTable."Token".HasValue then IF CheckExistingTokenIsValid() then // if existing token is not expired use it exit(YourSetupTable.ReadTextFromBLOB(YourSetupTable.FieldNo("Token"))); //else generate and return a new token JObject.ReadFrom(APITokenResultTxt); //read the content of the json JObject.SelectToken('access_token', JToken); //see https://andreilungu.com/read-write-text-from-to-blob-fields-generic-way-nav/ for more info: YourSetupTable.WriteTextToBLOB(YourSetupTable.FieldNo("Token"), JToken.AsValue().AsText()); YourSetupTable.FIND; JObject.SelectToken('expires_in', JToken); Evaluate(YourSetupTable."Token - Expires In", JToken.AsValue().AsText()); JObject.SelectToken('expires_on', JToken); YourSetupTable."Token - Expires On" := CalcUnixDateTime(19700101D, 000000T, JToken.AsValue().AsInteger()); Dur := (YourSetupTable."Token - Expires In" * 1000) * (-1); YourSetupTable."Token - Created At" := YourSetupTable."Token - Expires On" + Dur; YourSetupTable.Modify(); end;
–> Check if existing token is valid:
local procedure CheckExistingTokenIsValid(): Boolean var CurrDT: DotNet DateTime; CurrDTNAV: DateTime; begin CurrDT := CurrDT.Now; CurrDT.AddMinutes(1); //maybe web service call takes little time so need to ensure token does not expire in the meantime Evaluate(CurrDTNAV, CurrDT.ToString()); Exit(YourSetupTable."Token - INT Expires On" > CurrDTNav); end;
! Notice that in this task I used DotNet variables, so you need to setup in the app.json file “target”: “OnPrem”.
I hope this information and pattern to check if a token is expired is useful.
See also the test project on GitHub.