Velocitip: Find the ๐ฟ-th ๐-day (e.g. 4th Wednesday) of this month
Your developer community meets on the 4th Wednesday of each month. You want to send monthly invites from Marketo without having to hard-code anything. Earlier, we learned how to find the first ๐-day of next month, and this is just different enough to get its own post.
As always, start with the standard datetime includes in Velocity:
#set( $defaultTimeZone = $date.getTimeZone().getTimeZone("America/New_York") )
#set( $defaultLocale = $date.getLocale() )
#set( $calNow = $date.getCalendar() )
#set( $ret = $calNow.setTimeZone($defaultTimeZone) )
#set( $calConst = $field.in($calNow) )
#set( $ISO8601DateOnly = "yyyy-MM-dd" )
#set( $ISO8601DateTime = "yyyy-MM-dd'T'HH:mm:ss" )
#set( $ISO8601DateTimeWithSpace = "yyyy-MM-dd HH:mm:ss" )
#set( $ISO8601DateTimeWithMillisUTC = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" )
#set( $ISO8601DateTimeWithMillisTZ = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" )
Then add your campaign-specific settings, i.e. 4th Wednesday is $nth = 4
, $day = "WEDNESDAY"
:
#set( $nth = 4 )
#set( $day = "WEDNESDAY" )
($day
must be in all-caps English, since thatโs how Javaโs Calendar constants are stored.)
Next the hard/weird stuff:
#set( $dayConst = $calConst.get($day) )
#if( $dayConst < 7 )
#set( $nextDayConst = $math.add($dayConst,1) )
#else
#set( $nextDayConst = 1 )
#end
#set( $thisMonth = $date.getCalendar() )
#set( $ret = $thisMonth.setTimeZone($defaultTimeZone) )
#set( $ret = $thisMonth.set($calConst.DAY_OF_MONTH, 1) )
#set( $ret = $thisMonth.setFirstDayOfWeek($nextDayConst) ) ## the day *after* Y-day
#set( $ret = $thisMonth.set($calConst.DAY_OF_WEEK, $dayConst) ) ## Y-day itself
#set( $ret = $thisMonth.add($calConst.WEEK_OF_MONTH, $math.sub($nth,1) ) )
Now output $thisMonth
any way you want:
The ${nth}th/nd ${display.capitalize($day.toLowerCase())}
of ${date.format("MMMM yyyy", $thisMonth, $defaultLocale, $defaultTimeZone)}
is ${date.format("MM/dd/yyyy", $thisMonth, $defaultLocale, $defaultTimeZone)}
The 4th/nd Wednesday
of May 2024
is 05/22/2024
Brief code explainer
At the risk of making your head spin:
- Find the next day of the week after day ๐ฟ, using Javaโs 1-based week where Sunday = 1, Monday = 2, etc.
- Set the current day to 1st day of the month, which is naturally in the 1st week of the month as well.
- Shift the calendar (also done in the previous post) so weeks start on the next day from step (1). This ensures weโre in a โWorld of Wednesdaysโ if you will.
- Set the current day of the the week to day ๐ฟ.
- Jump forward ๐-1 weeks. Since weโre already in week 1 of the month, we donโt need to jump the full ๐.
Easy, right? ๐