1

I need to format a string date like this one:

2021-W46 

into something, that I can use in coldfusions parseDateTime or dateFormat function.

W46 in this case is week 46.

What I tried was to directly put that string into parseDateTime and dateFormat, but both gave me an error that my input is not a correct date format.

How can I do that?

Edit:

I forgot to mention that I need the first day of that week (in my case Monday)

Userx10xC
  • 124
  • 9
  • 2
    Does this blog post by Ben Nadel answer your question? https://www.bennadel.com/blog/719-ask-bengetting-the-date-based-on-the-year-and-week-in-coldfusion.htm – user12031119 Nov 15 '21 at 16:16
  • You realize of course that `2021-W46` represents 7 dates, not 1. – Dan Bracuk Nov 15 '21 at 18:34
  • @DanBracuk Exactly. Which is why I think Ben Nadel's solution could be modified adding one extra parameter. That being the day of the week in order to extract the exact date you want from the specified week. – user12031119 Nov 15 '21 at 19:22
  • 2
    It's helpful to include the code attempted, in addition to describing it. Technically you can parse that string with parseDateTime, [`parseDateTime("2021-W46", "YYYY-'W'ww");`](https://trycf.com/gist/5778abf71bdf7eb2e9313264982728a9/acf2021?theme=monokai). The day portion is set to Sunday, or the first day of the week. Whether you should is a different question. – SOS Nov 15 '21 at 19:57
  • @SOS when I try to parse it with "2021-W46" it tells me: Unparseable date: "2021-W46" – Userx10xC Nov 16 '21 at 07:58
  • @DanBracuk yeah sorry I forgot to mention that I need the first day of the week, in my case it's monday. – Userx10xC Nov 16 '21 at 07:59
  • I might need something like this just for week: https://cflib.org/udf/dayOfYearReverse – Userx10xC Nov 16 '21 at 09:18
  • 1
    You still didn't post your code. Did you run the linked example or try the code in the linked post? – SOS Nov 16 '21 at 12:43

1 Answers1

1

Using the algorithm from Wikipedia for calculating an ordinal or month date from a week date and your input format, this function will return the Monday date from the supplied ISO week numbering format passed to the function as a string.

Calculating an ordinal or month date from a week date

Algorithm:

  1. Multiply the week number woy by 7.
  2. Then add the weekday number dow.
  3. From this sum subtract the correction for the year:
    • Get the weekday of 4 January.
    • Add 3.
  4. The result is the ordinal date, which can be converted into a calendar date.
    • If the ordinal date thus obtained is zero or negative, the date belongs to the previous calendar year;
    • if it is greater than the number of days in the year, it belongs to the following year.

A working gist of the code can be found here.

<cffunction name="weekOfYear" returnType="date">
    <cfargument name="yearWeek" type="string">

    <!--- Parse out the year, the week of the year from arguments.yearWeek and default the day of week to Monday --->
    <cfset year = listGetAt(arguments.yearWeek, 1, "-W")>
    <cfset woy = listGetAt(arguments.yearWeek, 2, "-W")>
    <cfset dow = 2>
    
    <!--- Calculate the number of days this year and last year for later use. --->
    <cfset DaysThisYear = daysInYear(CreateDate(year, 1, 1))>
    <cfset DaysLastYear = daysInYear(CreateDate(year-1, 1, 1))>
    
    <!--- Multiply week number "woy" by 7, then add the weekday number "dow" --->
    <cfset ordinalDate = woy*7 + dow>
    
    <!--- From this sum, subtract the correction for the year: Get the weekday of 4 January and add 3 --->
    <cfset ordinalDate = ordinalDate - (dayOfWeek(parseDateTime("#year#-01-04", "y-M-d")) + 3)>
    
    <!--- The result is the ordinal date, which can be converted into a calendar date. --->
    <cfif ordinalDate LT 1>
        <!--- If the ordinal date thus obtained is zero or negative, the date belongs to the previous calendar year. --->
        <cfset ordinalDate = ordinalDate + daysLastYear>
        <cfset year = year-1>
    <cfelseif ordinalDate GT daysThisYear>
        <!--- If it is greater than the number of days in the year, it belongs to the following year. --->
        <cfset ordinalDate = ordinalDate - daysThisYear>
        <cfset year = year+1>
    </cfif>

    <cfreturn parseDateTime("#year#-#ordinalDate#", "y-D")>

</cffunction>
user12031119
  • 1,228
  • 4
  • 14