Freemarker/Velocity - date manipulation

10,134

Solution 1

In Velocity Tools there is no such method.

Solution 2

I know this is post is really old, but for people from the future still looking for an answer: Date manipulation can be done converting dates to/from milliseconds:

${(mydate?long - 18 * 86400000)?number_to_date?string("yyyy-MM-dd")}

for example would subtract 18 days from mydate. (Note that 86400000 is the amount of milliseconds per day)

Solution 3

You can do it in Velocity too, but not with the DateTool (that belongs the Velocity Extras anyway).

It is a good practice to have a "Format" object with various utilities that are practical for presentational purposes only (you can see the various frameworks that use Velocity how they have "Format" objects).

So your code would look like $format.dateFromNow(), and there would be still a presentational approach.

Solution 4

For freemarker, perhaps : Built-ins for dates.

Solution 5

I found that per @Stefan Haberl, ?long does work on dates to get the same value as java.util.Date.getTime() as a Long. However, I needed a little more explanation to be able to compare dates or modify dates.

Here's the gist:

  1. ?long = java.util.Date.getTime() returns epoch time in milliseconds
  2. At this point, you can add/subtract any number of milliseconds from that number for your manipulation

I like working in seconds instead of milliseconds (less unnecessary zeros, I don't care about milliseconds, etc.), which looks like this:

[#function convertToUnix date]
  [#return (date?date?long / 1000)]
[/#function]

[#-- Output Unix Timestamp --]
${convertToUnix(.now)}

At this point, 86400 = 1 day (because we are in "seconds" now), so you can simply add/subtract that to manipulate the date.

[#assign
  day = 86400
  week = 7 * day
  avgMonth = 365.25 / 12 * day

  testingEndOfDay = convertToUnix(.now) < (convertToUnix(sameDay) + day)
  testingYesterday = convertToUnix(.now) < (convertToUnix(yesterday) + day)
]
${testingEndOfDay?c} # true, .now is less than the end of the day
${testingYesterday?c} # false, .now is greater than the end of yesterday

Note: I am ignoring the time of day, we received dates that started at 12:00AM and wanted to check against .now for the end of the day.

Now, if I want to get a date back from the Unix format (in seconds), I can convert it back using the ?number_to_date builtin

[#assign
  nowAsUnix = convertToUnix(.now)
  prettyDate = (nowAsUnix * 1000)?number_to_date
]

Note: I'm open to edits/improvements as I'm not sure why much of this was required ¯\_(ツ)_/¯

Share:
10,134
Razor
Author by

Razor

Worked in banking, gaming and ecommerce on sites ranging from 100s to tens of millions of views per day. Front End development is my specialty, and I love all things DevOps - I know a fair bit about these 2, from how to create 3D games on a mobile all the way down to CI pipelines deploying to a kubernetes cluster. I know CSS/JS/HTML inside out, including node. Not a stranger to React, Jest, SCSS, canvas and a great deal of other Front End bits that are not cool anymore. Can find my way around C#, Java, Scala and python. While I don't do much C++ these days, I can still put together a respectable explanation of how a linked lists or hashmap works. Used a fair bit of kubernetes and AWS/azure/google cloud. Love TDD, automated testing and automation in general. I run several services as private projects, including my email server, website and voice chat server.

Updated on June 04, 2022

Comments

  • Razor
    Razor almost 2 years

    I have a fairly simple question about these 2 templating engines.
    I'm trying to make a future/past date, a fixed time from now, e.g. 18 months ago, or tomorrow.

    I know that it is possible to do this with a java date object inside a velocity/freemarker template (something like $date.add(2,-18)), but I would like to do this with DateTool or freemarker core.

    This is something that I see as purely presentational (just think at the default dates you see in flight booking forms), so I can't see any reason why a templating engine shouldn't be able to do this.

    Is it possible though? If so, how?

  • Razor
    Razor about 14 years
    I had already seen that doc page, and I cannot find any reference to date manipulation, just how to format them, perhaps I missed it?
  • Istao
    Istao about 14 years
    Sorry, I think you need to write your own freemarker TemplateMethodModelEx for that... see this post : Calculate days between two dates at thread.gmane.org/gmane.comp.web.freemarker.user/4292
  • Razor
    Razor about 14 years
    That's something different from what I need, but it doesn't look like freemarker has any better date manipulation possibilities, when compared to velocity tools. I'm guessing here that it's not possible to do what I need with this engine either.
  • joshwhatk
    joshwhatk about 5 years
    One thing to note: ?long is not a documented date builtin, it is on the expert builtins page: freemarker.apache.org/docs/ref_builtins_expert.html