/ Development  

Get excited; easily format your precious value with the magic of 'sprintf()'

Hi there AppWorks fans,

Welcome to a new installment of AppWorks tips.

Somewhere in the history of time on my own explorations for the AppWorks platform an interesting statement passed my attention which directly decided me to make a blogpost out of it. It was on my backlog to pick up and today is the day to explore it further. The feature is seen in the BPM space and at that moment I was also playing with a date/time property (as far as I can remember!). Let’s just check out what it was and see what value it can bring.

Let get right into it…

My VM is already started during the writing of the introduction, so I can directly dive into my clean workspace and related project. Time to take a view on what I saw passing by during my BPM exploration. Create a new BPM type of document (nicely in the bpms folder), add the start-construct, one activity-construct, the end-construct, and glue it together with those arrow-flows. After this, open the message map tab from the bottom.

To dive deeper, we create a new ‘Process Specific Message’ element from the top-left. Use this element for the assignment on the activity, and you make sure to have a view like this:


It’s now time to click open the ‘Expression Editor’. From the left-bottom panel open the ‘Date-Time’ functions, and double-click on the sprintf function to see the magic statement filled in the XPath panel:


sprintf("%D(%yyyy-%MM-%dd)T%T(%HH:%mm:%ss.0)", utc(), utc())

Well, this statement requires some investigation based on some open questions:

  1. What does sprintf mean? Well, print I get; The f for format too, but the s??
  2. What is utc??
  3. Why all the % signs??
  4. Why all the () signs??
  5. What else can we format??
  6. Can we find more details in the documentation??
  7. Is it an XPath specific thing, or AppWorks specific??
  8. Where can we use this function; what are the use-cases??

Question, questions…Let’s just go through them; one by one.

If you find this already interesting, you also find this post valuable!

Finding the answers to our questions

What does sprintf mean? Well, print I get; The f for format too, but the s??

I rephrase the question here and I directly give an answer to my own question. 😣 The s is of course standing for ‘String’. So, we can print a string with a predefined format!

What is utc??

Well, It all has to do with time; Specifically, Universal Time (Coordinated) which is the basis for our civil time today (in 24-hours). See also this interesting post where I also read about Greenwich Mean Time which we can call with function utcgmt()!

  • UTC will return 2023-02-13T11:58:32.0
  • GMT will return 2023-02-13T10:58:32.0

Fine, that’s a 1-hour difference, but what I always found strange is ‘Amsterdam’. It falls into the “Prime meridian” (GMT; UTC+0), but we use UTC+1!? A little history lesson can be found here which tells me that we magically moved 1 meridian since 1 May 1892 because it was better for shipping in Europe. #knowyourhistory

WorldTimeBuddy is a great tool to get the overview as in Europe we also have Central Europe Time (CET) and Central Europe Summer Time (CEST) which makes it even more complicated:


The image is wrong as CEST is currently running here in the Netherlands; Since last month, Fri May 26th, 2023!

Now I also understand why date/time APIs struggle a lot on a solid implementation. There are a lot of catches/snags to implement!

Why all the % signs??

The question asks for on answer on this specific string: "%D(%yyyy-%MM-%dd)T%T(%HH:%mm:%ss.0)". What is this string telling me? Well, 3 things:

  1. We have a date variable in format “yyyy-MM-dd”: %D(%yyyy-%MM-%dd)
  2. We have a time separator: T
  3. We have a time variable in format “HH-mm-ss.0”: %T(%HH:%mm:%ss.0). The .0 are the milliseconds!

A quick reformat to this "%D(%dd %MMMM %yyyy) %T(%HH:%mm:%ss)", will get output like this: 14 February 2023 14:40:16…You get the point…correct?

Read more on date/time data types in XML here

Why all the () signs??

Well, it’s all in the functions. This makes it more readable:


%D() is a DATE function
%T() is a TIME function

What else can we format??

Check this table on things I tried to do (with some documentation help!):

Format Output Type
sprintf("Sum of %d and %d is %d", 1, 3, 4) Sum of 1 and 3 is 4 Decimal
sprintf("%C(%dd.dd)", 123543251) $ 123,543,251.00 Currency
sprintf("%C(%g(3)%s(,)%S(.)%c(€))", 123543251) € 123.543.251,00 Currency
sprintf("%e", 123) 1.230000e+02 Exponent
sprintf("%f", 12323.56) 12323.560000 Double/Float
sprintf("Hello %s, %s", "world!", 'AppWorks') Hello world!, AppWorks String
sprintf("%o", '8') 10; that’s not ten, but 1 and 0! Octal
sprintf("%x", '255') ff Hex decimal

Can we find more details in the documentation??

YES, we can!…And lots of samples too! You can find it in the advanced developer guide of the platform. The section is named: “Sprintf function library”! 😉

Is it an XPath specific thing, or AppWorks specific??

After a quick google search, I see this function has lots of relations with the PHP and the C-language. So, is it AppWorks specific? I think it is! Why? Well, as I see also these formats passing by in the documentation: %XD (Date format in XML string), %XT (Time format in XML string), %l (locale):

  • sprintf("%XD", '2023-02-14T16:26:45') will output to 02/14/2023
  • sprintf("%XT", '2023-02-14T16:26:45') will output to 4:26:45 PM
  • Even this works: sprintf("%XD", sprintf("%D(%yyyy-%MM-%dd)T%T(%HH:%mm:%ss.0)", utc(), utc()))!
  • I leave %l out of scope which is for me currently not worth diving into.

I did also a quick search in the JAR files for any ‘public static’ methods with name sprintf like this post explains, but I couldn’t find it!? Comment me if you have the final clue…

Where can we use this function; what are the use-cases??

Let me think about what list to produce here…

  1. It’s obvious we can manipulate values from one format to another format; Date formatting and currency formatting especially will benefit somewhere in the future with this function.
  2. You can use a template string with variables instead of concatenating strings together with the concat() function.
  3. When you call an external system (via webservices) and the data on the other side is (for some reason?) formatted differently.
  4. This is the same when an external system calling AppWorks services with data input; There is always a value which needs reformatting to have a final fit.
  5. You can format data to have a correct representation for your end-user but save it in a consistent way in the database.

Looks to me like all questions have a solid answer now where we learned a lot more on the sprintf() function which we can use in the BPM expression language. I say “DONE” which makes me continue my life to a new post; next week…cheers! 🍻

Don’t forget to subscribe to get updates on the activities happening on this site. Have you noticed the quiz where you find out if you are also “The AppWorks guy”?