System.date.format() returns wrong calendar week

Hi there,
i am calculating the calendar week from a timestamp in a property transform script. The script is not returning what I would expect.

Here is the code:

timestamp = 1671540467576
date = system.date.fromMillis(timestamp)
calendar_week = system.date.format(date, 'w')

In the transform script this returns calendar_week = 52

If I test the code in the script editor I get what I would expect: calendar_week = 51

Any ideas, why the results are different and what causes the transform script to return week 52?

Thanks in advance!

I wonder if it's an integer casting issue, where the expected value is being rounded up.

Are your designer and gateway in the same locale?

The designer script console runs in the Client scope, so whatever local that your machine is set to.

Script transforms run in gateway scope so whatever local the gateway machine is set to.

2 Likes

The 8.1 documentation is somewhat vague, but the 8.0 documentation says this:

I found that bit as well, but I understood it as only the 31st of December would fall into week 1.

If I change the formatting e.g. to 'dd.MM.yyyy', I get the correct date.

	timestamp = 1671540467576
	date = system.date.fromMillis(timestamp)
	formated_date = system.date.format(date, 'dd.MM.yyy')

returns → 20.12.2022

This is the underlying implementation:

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/format/DateTimeFormatter.html

Also read the package introduction, where it points out that all base classes use ISO definitions:

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html

If you need more, you can always read the java source code (via OpenJDK).

If I understand this correctly the ISO week-of-week-based-year should be 51.

python datetime functions return calendar week = 51 in script console as well as in the transform script:

from datetime import datetime
timestamp = 1671540467576
py_date = datetime.fromtimestamp(timestamp/1000)
cw = py_date.strftime('%U')

So that could be a workaround. But i try to stick to @pturmel advice to avoide datetime functions. :thinking:

This seems to work as well:

timestamp = 1671540467576
date = system.date.fromMillis(timestamp)
calendar_week = system.date.format(date, 'w')
calendar_day = system.date.format(date, 'D')

print calendar_week
print float(calendar_day)/7.0
print round(float(calendar_day)/7.0)
print int(round(float(calendar_day)/7.0))

Output:

52
50.5714285714
51.0
51

1 Like

@lrose: You were correct. The locale setting is causing the difference between designer and script transform.
My designer was running with locale de_DE and the Gateway is running wit en_US. I did not manage to change the Gateways locale, which is running in docker, but after changing my client to en_US the system.date.format(date,'w') returned week 52 in the designer as well.
I still don't understand, why en_US would have another calendar_week as locale C.UTF-8 or de_DE.UTF-8.
If someone got some documentation how the various locales are affecting week_of_yearcalculation, that would be nice.

Well if you think about it, I think you can probably work it out. Very basically the local affects the time zone offset of the date, which in some circumstances can cause Week 1 to shift.

This has to do with the way that week 1 is calculated, by the ISO definition. Due to the time zone offset it is possible for Jan 1 to be on a Sunday in some time zones and Monday in others.

1 Like

Huh? I think not.

1 Like

More like the locale can affect where week 1 begins.

You can build a formatter using java.time to just make it ISO, regardless of locale.

from java.time import Instant, ZoneOffset
from java.time.temporal import WeekFields
from java.time.format import DateTimeFormatterBuilder


timestamp = 1671540467576


print '--- US Locale ---'
date = system.date.fromMillis(timestamp)
print '      Date:', date
print 'WeekOfYear:', system.date.format(date, 'w')
print ' '

print '---    ISO    ---'
formatter = DateTimeFormatterBuilder() \
				.appendValue(WeekFields.ISO.weekOfWeekBasedYear(), 2) \
				.toFormatter().withZone(ZoneOffset.UTC)

date = Instant.ofEpochMilli(timestamp)
print '      Date:', date
print 'WeekOfYear:', formatter.format(date)

Output:

--- US Locale ---
      Date: Tue Dec 20 07:47:47 EST 2022
WeekOfYear: 52
 
---    ISO    ---
      Date: 2022-12-20T12:47:47.576Z
WeekOfYear: 51
2 Likes