on 03-24-2014 11:21 AM
Hi Experts,
I am unable to understand the below UDF. Can anyone help me with some example:
The input is something like YEARWEEK i.e. 201449 or 201501 which is splitted as 2014 or 2015 and 49 or 01 using Substring function.
Locale loc = new Locale("en","us");
Calendar cal1 = Calendar.getInstance(loc);
cal1.setLenient(true);
cal1.set(Calendar.WEEK_OF_YEAR, week);
cal1.set(Calendar.YEAR, year);
cal1.set(Calendar.DAY_OF_WEEK,2);
cal1.setMinimalDaysInFirstWeek(1);
int data = cal1.get(Calendar.DATE);
String fin = Integer.toString(data);
String res = String.format("%1$2s",fin).replaceAll(" ","0")+""+(String.format("%1$2s",(cal1.get(Calendar.MONTH)+1)).replaceAll(" ","0"))+""+cal1.get(Calendar.YEAR);
String sample = res;
SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy");
Date date = new Date();
try
{
date = sdf.parse(sample);
}
catch (java.text.ParseException e)
{
}
Calendar cal2 = Calendar.getInstance();
cal2.setLenient(true);
cal2.setMinimalDaysInFirstWeek(4);
cal2.setTime(date);
int res1 = cal2.get(Calendar.WEEK_OF_YEAR);
String finalweek = Integer.toString(res1);
return String.format("%1$2s",finalweek).replaceAll(" ","0");
Thanks,
Shaibayan
Hello Shaibayan
I too find the UDF difficult to understand, but I think this is what it is doing :
>>>>
Create new calendar object using UDF parameters.
It sets the calendar date to the 2nd day of the week supplied by parameter.
<<<<
Locale loc = new Locale("en","us");
Calendar cal1 = Calendar.getInstance(loc);
cal1.setLenient(true);
cal1.set(Calendar.WEEK_OF_YEAR, week);
cal1.set(Calendar.YEAR, year);
cal1.set(Calendar.DAY_OF_WEEK,2);
cal1.setMinimalDaysInFirstWeek(1);
>>> Get the day of the month for the calendar object and convert to string
int data = cal1.get(Calendar.DATE);
String fin = Integer.toString(data);
<<<
>>>
Create a string from day of the month, and calendar month and year (replacing blanks with zeros)
<<<
String res = String.format("%1$2s",fin).replaceAll(" ","0")+""+(String.format("%1$2s",(cal1.get(Calendar.MONTH)+1)).replaceAll(" ","0"))+""+cal1.get(Calendar.YEAR);
>>> Create a date object from string in previous step
String sample = res;
SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy");
Date date = new Date();
try
{
date = sdf.parse(sample);
}
catch (java.text.ParseException e)
{
}
<<<
>>>
Create new calendar object from date in previous step
In this case the minimum days in first week of year is set to 4, whereas in the first calendar object it is set
to 1
<<<
Calendar cal2 = Calendar.getInstance();
cal2.setLenient(true);
cal2.setMinimalDaysInFirstWeek(4);
cal2.setTime(date);
>>>
Get week of year for second calendar object and convert to string (replace blanks with zeros)
<<<
int res1 = cal2.get(Calendar.WEEK_OF_YEAR);
String finalweek = Integer.toString(res1);
return String.format("%1$2s",finalweek).replaceAll(" ","0");
So it seems to create a calendar object for the second day of the week specified where 1st week of year has a minimum of 1 day. Then it uses the date from that calendar object to create a new calendar object where the first week of the year has at least 4 days, and returns the week number for this date.
Kind regards
Steve
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I've just copied and pasted the code into a Java class and run with the same inputs.
For year 2014 week 49, result = 49
For year 2015 week 1, result = 01
Are you getting the output directly from the UDF or from target element after mapping? I'm wondering if there are functions in the graphical mapping to change the result.
Kind regards
Steve
In which case I'm even more confused. The return parameter from the UDF is a 2 character string :
String.format("%1$2s",finalweek).replaceAll(" ","0");
"%1$2s" is a 2 character string containing finalweek
%1$ = first parameter, i.e. finalweek
2s = 2 character string
which should just be the week number, and not include the year at all.
Kind regards
Steve
Thanks.
I can't see how the method could return 53 based on input 201501. Are you sure the input is 201501, and also that the substring to split the input is working correctly?
Could you hardcode the UDF to use year 2015 and week 01 just to make sure it is receiving the correct values?
Kind regards
Steve
The UK and US use the same calendar, but there might be business reasons why the first week of the year is handled differently in the two countries.
It might be that the UDF is returning the last week in the previous year, i.e. 53. Setting lenient to false might prevent this but could throw an exception if a week in the previous year is returned.
Is there any documentation to say what the UDF should be doing exactly?
regards
Steve
Hi Shaibayan/Steve,
I found this discussion very interesting and thus tried to look inside the logic.
As you said, you've changed the MinimalDaysInFirstWeek to 1 and it gave the output '01' which you required. If you scrutinize the runtime internally, '01' is the output for year 2014 which is not entirely correct. Infact, it should give you '53' only for 2014 because the calculated date is the 53rd week of 2014. This might be a java bug which I am not sure of but you can confirm it by outputting the year also with the UDF.
Another important point, if you're setting the MinimalDaysInFirstWeek to 1, then I don't see the need of cal2. It does nothing to the derived date. You/Developer could've easily gotten the WEEK_OF_DAY from cal1 itself.
Another point, Calendar class behaves differently based on country location (timezone). That can be a very valid reason why Steve is getting '01' while we are getting '53' as output. I'm still not very much convinced though as to why this is happening internally.
Steve: Can I request you to to check the value of elements in cal1 in debugger.
PS: The UDF does the following:
Get Week/Year as input => Find the second day of same week that is the Monday of the week provided in input => some format conversions => create another calender using formatted date and for which the week counting starts where there are minimum 4 days in the first week => return the week number.
Thanks,
Abhishek
Hi Abhishek/Steve,
I got more clarity from Business and got to know that if any year there is a week 53 then it should be treated as 1st week of the following year.
By changing the value of MinimalDaysofweek to 1 I am getting the desired output but I am still not clear how. However to the existing mapping logic I have done the following.
Since Year and Week are getting into the UDF as input separately by Substring function I used a IF-THEN-ELSE block. So if the input week say 53 is less than the output week number say 1 then increment the Year number by 1 and finally concat function.
Ex: Input 201553 (Year 2015 has 53 weeks) desired output is 201601
So output of UDF is 01 which is less than 53 hence 2015+1 i.e. 2016
Finally concat i.e. 201601
However I am still in the dark about the use of this MinimalDaysofweek function which solved my issue.
Regards,
Shaibayan
Hi Shaibayan,
Thanks for the update. It makes sense in incrementing the year by 1 where the month is 53.
Besides, the logic you've added is coincidentally meeting your requirements.
Here is what I had a concern with. With input 201501, the 2nd day for week 01 arrives at 29th Dec 2014. Now, this is the 53rd week of 2014 and Java should've optimally converted it to 1st week of 2015.
During debugging, I see that the value of week remains 1 but it has changed the year to 2014.
See below image. I don't find it consistent but this is what we get after executing the UDF. Only possible reason I see why it returns 01 for week is that field was not modified/updated by internal methods during date computation since we manually populated it in the code using cal1.set(Calendar.WEEK_OF_YEAR, week);
If you set MinimalDaysInFirstWeek as 4 in both cal1 and cal2, you'll get same results but the years will be consitent internally.
One more thing, I did some research around this Calendar class method MinimalDaysInFirstWeek and found it behaves oddly. Importantly, ISO 8601 considers the first week as the week with the year's first Thursday in it. Because of this, standard coding sets MinimalDaysInFirstWeek as 4 to ensure that first week has at least 4 days which will conform with ISO.
So, be aware that your results deviate from ISO but somehow fetches you an output you require.
See if 4,4 in MinimalDaysInFirstWeek for cal1, cal2 solves your purpose or not.
Thanks,
Abhishek
Hi Steve,
I now have more clarity. The input starts each week on a Sunday and output start calendar on a Monday.
So In this case Week 201552 on the inbound file has a start date of Sunday 20/12/2015 but on output the week starts on the Monday 21/12/2015. In this scenario both fall into Week 52 . The output week is not always a week ahead. The output week will only be ahead if Input has 53 week and output 52 Week . This all relates back to the Day of the week the calendar start on for each SAP instance.
How shall I set the start day of the week correctly in my code mentioned above.
Regards,
Shaibayan
Hello Shaibayan
I still don't quite understand the logic required. Is this correct?
A week number and year are passed into method.
Get date of Sunday in week.
Return week number and year for day after this date, which will be a Monday.
I've assumed that the week input could start on any day, as the minimal number of days in first week is 1.
regards
Steve
Hi
Check this
Calendar (Java Platform SE 7 )
It will help you to understand each method of calender class.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
101 | |
13 | |
13 | |
11 | |
11 | |
7 | |
6 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.