@@ -519,16 +519,59 @@ public with sharing class DateAndTimeFunctions {
519519 Object dateValue = evaluate (arguments .get (0 ));
520520 if (! (dateValue instanceof Date )) {
521521 throw new FunctionExecutionException (
522- ' Error executing "ISOWEEK" function: the argument must evaluate to a date value.'
522+ ' Error executing "ISOWEEK" function: the argument must evaluate to a date value.'
523523 );
524524 }
525525
526- return Integer . valueOf ( Datetime . newInstanceGmt (( Date )dateValue , Time . newInstance ( 0 , 0 , 0 , 0 )). format ( ' w ' ) );
526+ return getIsoWeekNumber (( Date ) dateValue );
527527 }
528528
529529 public override Arity getArity () {
530530 return Arity .exactly (1 );
531531 }
532+
533+ // --- ISO WEEK IMPLEMENTATION ---
534+
535+ private Integer getIsoWeekNumber (Date inputDate ) {
536+ Integer isoWeekday = getIsoWeekday (inputDate ); // Monday=1 ... Sunday=7
537+ Integer week = floorDiv (inputDate .dayOfYear () - isoWeekday + 10 , 7 );
538+
539+ if (week < 1 ) {
540+ return getIsoWeeksInYear (inputDate .year () - 1 );
541+ }
542+
543+ Integer weeksInYear = getIsoWeeksInYear (inputDate .year ());
544+ if (week > weeksInYear ) {
545+ return 1 ;
546+ }
547+
548+ return week ;
549+ }
550+
551+ private Integer getIsoWeeksInYear (Integer year ) {
552+ // Dec 28 is always in the last ISO week
553+ Date dec28 = Date .newInstance (year , 12 , 28 );
554+ Integer isoWeekday = getIsoWeekday (dec28 );
555+ return floorDiv (dec28 .dayOfYear () - isoWeekday + 10 , 7 );
556+ }
557+
558+ private Integer getIsoWeekday (Date inputDate ) {
559+ // 1900-01-01 was Monday
560+ Integer diff = Date .newInstance (1900 , 1 , 1 ).daysBetween (inputDate );
561+ Integer mod = Math .mod (diff , 7 );
562+ if (mod < 0 ) {
563+ mod += 7 ;
564+ }
565+ return mod + 1 ;
566+ }
567+
568+ private Integer floorDiv (Integer a , Integer b ) {
569+ Integer result = a / b ;
570+ if (a < 0 && Math .mod (a , b ) != 0 ) {
571+ result -- ;
572+ }
573+ return result ;
574+ }
532575 }
533576
534577 /**
0 commit comments