web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :

Fixing firstDayOfWeek and firstWeekOfYear in AX2012

Tommy Skaue Profile Picture Tommy Skaue Moderator
I was asked to have a look at why the date picker in AX still chose Sunday while the user expected Monday. I remember fixing this back in AX2009, so I was curious to see how this was solved in AX2012. The Global class and the methods firstDayOfWeek and firstWeekOfYear caught my attention. One of them used the current users language as key to find the best possible calendar setting, while the other picked the default system setting. Well, let us rewrite this and make it work a bit better, and since sharing is caring - here is how I solved it.

Global::firstWeekOfYear served as an inspiration, but I want it to differentiate between whatever languages my environment is serving. I can live with one cached result for each language, and the performance penalty is low and acceptable.



static int firstWeekOfYear()
{
#WinAPI
SysGlobalCache cache = classfactory.globalCache();
int clientFirstWeekOfYear;
anytype calendarWeekRuleValue;
// Axdata.Skaue ->
/*
str language;
*/
str language = currentUserLanguage();
// Axdata.Skaue
System.Globalization.CultureInfo userCulture;
System.Globalization.CalendarWeekRule calendarWeekRule;
System.Globalization.DateTimeFormatInfo userDateTimeFormat;

// Axdata.Skaue ->
/*
if (cache.isSet(classStr(Global), funcName()))
*/
if (cache.isSet(classStr(Global), funcName() + language))
// Axdata.Skaue
{
// Axdata.Skaue ->
/*
clientFirstWeekOfYear = cache.get(classStr(Global), funcName());
*/
clientFirstWeekOfYear = cache.get(classStr(Global), funcName() + language);
// Axdata.Skaue
}
else
{
// Axdata.Skaue ->
/*
language = currentUserLanguage();
*/
// Axdata.Skaue
userCulture = new System.Globalization.CultureInfo(language);
userDateTimeFormat = userCulture.get_DateTimeFormat();
calendarWeekRule = userDateTimeFormat.get_CalendarWeekRule();
calendarWeekRuleValue = CLRInterop::getAnyTypeForObject(calendarWeekRule);

switch(calendarWeekRuleValue)
{
case CLRInterop::getAnyTypeForObject(System.Globalization.CalendarWeekRule::FirstDay) :
clientFirstWeekOfYear = 0;
break;
case CLRInterop::getAnyTypeForObject(System.Globalization.CalendarWeekRule::FirstFullWeek) :
clientFirstWeekOfYear = 1;
break;
case CLRInterop::getAnyTypeForObject(System.Globalization.CalendarWeekRule::FirstFourDayWeek) :
clientFirstWeekOfYear = 2;
break;
}

// Axdata.Skaue ->
/*
cache.set(classStr(Global), funcName(),clientFirstWeekOfYear);
*/
cache.set(classStr(Global), funcName() + language,clientFirstWeekOfYear);
// Axdata.Skaue
}

return clientFirstWeekOfYear;
}


Using the same ideas, I changed Global::firstDayOfWeek. Again, I allowed for one cached result for each language.

static int firstDayOfWeek()
{
// Axdata.Skaue ->
/*
System.Globalization.DateTimeFormatInfo fi;
*/
int dow;
str language = currentUserLanguage();
System.Globalization.CultureInfo userCulture;
System.Globalization.DateTimeFormatInfo userDateTimeFormat;
// Axdata.Skaue

SysGlobalCache cache = classfactory.globalCache();
int clientFirstDayOfWeek;

// Axdata.Skaue ->
/*
if (cache.isSet(classStr(Global), funcName()))
*/
if (cache.isSet(classStr(Global), funcName() + language))
// Axdata.Skaue
{
// Axdata.Skaue ->
/*
clientFirstDayOfWeek = cache.get(classStr(Global), funcName());
*/
clientFirstDayOfWeek = cache.get(classStr(Global), funcName() + language);

}
else
{
// Axdata.Skaue ->
userCulture = new System.Globalization.CultureInfo(language);
userDateTimeFormat = userCulture.get_DateTimeFormat();
dow = userDateTimeFormat.get_FirstDayOfWeek();
/* Removed
fi = new System.Globalization.DateTimeFormatInfo();
dow = fi.get_FirstDayOfWeek();
*/
// Axdata.Skaue

// The .NET API returns 0 for sunday, but we expect sunday to
// be represented as 6, (monday is 0).
clientFirstDayOfWeek = (dow + 6) mod 7;

// Axdata.Skaue ->
/*
cache.set(classStr(Global), funcName(),clientFirstDayOfWeek);
*/
cache.set(classStr(Global), funcName() + language,clientFirstDayOfWeek);
// Axdata.Skaue
}

return clientFirstDayOfWeek;
}

So, for those of you who have an environment supporting potential multiple calendar setups, I recommend applying the fix above, or write your own fix. If you know a more efficient and better way, please comment below.

This was originally posted here.

Comments

*This post is locked for comments