SOLVED

Re: Velocity - comparing to today's date

Go to solution
Phillip_Wild
Level 10

Ugh. I know I've asked very similar things to this before, so I feel like I should know better....but I'm having trouble comparing a date to today's date. I've successfully done this in the past with two points in time, but not when one is today's date....and that's tripping me up. Here's what I have so far. $LTD.Expiry_Date__c is a date field that comes in from Salesforce like this: "2015-11-05".

##set time zone and locale settings for date conversions

#set( $TimeZone = $date.getTimeZone().getTimeZone('America/New York') )  

#set( $locale = $date.getLocale() )

##set a calendar object

#set( $calNow = $date.getCalendar() )

#set( $calConst = $field.in($calNow) )

#set ($validCredits = [])

#if( ! $LTD.Expiry_Date__c)

#set ($discard = $validCredits.add($LTD.Compass_ID__c))

#else

##set travel credit expiry date and convert it to a date, then a calendar so we can compare later

#set($TravelCreditExpiryDate = $LTD.Expiry_Date__c)

#set($TravelCreditExpiryDate = $convert.parseDate($TravelCreditExpiryDate,'yyyy-MM-dd',$locale,$TimeZone))

#set($TravelCreditExpiryDate= $date.toCalendar($TravelCreditExpiryDate))

##compare the expiry date of the travel credit to today's date.

##if expiry date is in the future, add to valid credits list.

#if ( $calNow.compareTo($TravelCreditExpiryDate) < 0)

#set ($discard = $validCredits.add($LTD.Compass_ID__c))

#end

#end

Here is the error I get:

Cannot get email content- <div>An error occurred when procesing the email Rendered_Email_Velocity_Error_Area_?! </div> <p>Invocation of method 'compareTo' in class java.util.GregorianCalendar threw exception java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Calendar near</p> <div><pre >?</pre></div>

So either my travel credit isn't being formatted properly, or my current date $calNow isn't. I think the travel credit part is right since I've used that before. So I'm guessing it's today's date. But how can I fix this?

Any ideas?

Thanks in advance.

1 ACCEPTED SOLUTION
SanfordWhiteman
Level 10 - Community Moderator

It's not $calNow that's the problem, because if it were null or another non-Calendar value it wouldn't have a compareTo method at all.

The prob is certainly with your custom field remaining a String because it can't be converted. You have a condition in there that suggests it may be empty. In that empty case the Calendar conversion will fail, and in turn the compareTo will error out, but you haven't short-circuited the rest of the processing.

View solution in original post

12 REPLIES 12
Grant_Booth
Level 10

I think I found a simpler way of doing this. Excuse me if I leave out something obvious because I'm new to velocity, but it's working in my tests and seemed conceptually simpler to me. The idea is that you convert each date to integers, and then simply subtract the two.
I'm trying to determine that a voucher is expired by comparing a custom date field from SFDC with today's date.


##get today's date as yyyyMMdd

#set($todayString = $date.get('yyyyMMdd'))

##make an integer variable
#set($todayInt = 0)

##convert the string to an integer
#set($today = $todayInt.parseInt($todayString))

##remove the dashes from the custom date field to make it yyyyMMdd
#set( $ExpDateString = $Voucher.Expiration_Date__c.replace("-","") )

##make an integer variable
#set( $ExpDateInt = 0)

##convert the expiration date to an integer
#set( $ExpDate = $ExpDateInt.parseInt($ExpDateString) )

##subtract the $today integer from the $ExpDate integer
#if( $ExpDate - $today >= 0 )
This voucher has NOT expired yet
#else
This voucher is EXPIRED
#end

SanfordWhiteman
Level 10 - Community Moderator

The difference between 2 unpunctuated ISO 8601 dates *from the same timezone* converted to Integers is indeed a valid way to determine the simple answer to "which one is later."

But date math should be done with proper libraries.

Grant_Booth
Level 10

And I agree with that sentiment, it's always preferable, but in our use case a margin of error of +/- 1 day is acceptable, so I'm going to save the headache of troubleshooting date objects and using the proper libraries for another day

SanfordWhiteman
Level 10 - Community Moderator

Phillip Wild​​ please come back to the thread and mark one of my answers as Correct (probably the one noting the typo) for future searches, thanks.

SanfordWhiteman
Level 10 - Community Moderator

Also, you're testing for Boolean false, not empty. You should be using isEmpty there.

SanfordWhiteman
Level 10 - Community Moderator

It's not $calNow that's the problem, because if it were null or another non-Calendar value it wouldn't have a compareTo method at all.

The prob is certainly with your custom field remaining a String because it can't be converted. You have a condition in there that suggests it may be empty. In that empty case the Calendar conversion will fail, and in turn the compareTo will error out, but you haven't short-circuited the rest of the processing.

Phillip_Wild
Level 10

Hmm....I still don't think I get it. Since my code structure is basically this (after changing to isEmpty for logic):

#if( $LTD.Expiry_Date__c.isEmpty())

#set ($discard = $validCredits.add($LTD.Compass_ID__c))

#else

##compare dates

#end

So if my first check is to see whether it's empty.....then the #else section should only be dealing with circumstances where there is a value in there, right? Since the field is a date field in Salesforce I know the output must be either empty, or yyyy-mm-dd. So why would my #else section be failing if it's only applying where the value is there?

To test this further I got the output of that field for the test lead where this is failing (using preview of the email and selecting sample lead). The field value is:

Expiry_Date__c=2015-12-15

What am I missing here.....

SanfordWhiteman
Level 10 - Community Moderator

It's

America/New_York

not

America/New York

(Was on my phone before so I didn't notice this typo.)

Because of the typo, $TimeZone is never set. Thus the later use of $TimeZone in the conversion to Date fails silently, and the variable remains as-is, a String.

Phillip_Wild
Level 10

Ah, of course! Duh.

Now that is solved, I went back and modified my simple "checks based on having a value" (eg. $LTD.Amount__c) to be checking on isEmpty (eg. $LTD.Amount__c.isEmpty() ).

But here's the weird thing. Those logic checks don't seem to be working for some reason using the Preview. Here's what works:

#elseif($LTD.Type__c == "Travel Credit" && ! $LTD.Applied_To__c && $LTD.Amount__c)

And what doesn't:

#elseif($LTD.Type__c == "Travel Credit" && $LTD.Applied_To__c.isEmpty() && ! $LTD.Amount__c.isEmpty() )

I know you said above that using isEmpty is more reliable. But that's not what I'm finding in this example. Why so?

(When I output the fields of "Applied_To" and "Amount__c" for this lead it displays as "Applied_To__c=null". So the value is definitely null in there.

SanfordWhiteman
Level 10 - Community Moderator

It's not that one is more reliable than the other, it's that they do totally different things.

$var.isEmpty() checks if a reference is an empty String.

!$var checks if a reference is Boolean false or null or does not exist in the Velocity context.

If you come from a background in popular dynamic languages, you might assume that !$var is false for empty Strings. Velocity sometimes is dynamically typed (or more like error-suppressing) and sometimes is strongly typed.

Phillip_Wild
Level 10

Thanks Sanford! Can you tell I never went to programming school?

SanfordWhiteman
Level 10 - Community Moderator

Me neither, technically!  But I'm founding the School of Velocity. You're gonna like the next blog post, I think.