Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm using the GNU date command to parse arbitrary natural language dates - for example to detect if a certain epoch time stamp is from last week, I can do:

if [ "$timestamp" -lt "$(date +"%s" -d "last sunday")" ]; then ...

Now when I'm trying to port my script to FreeBSD, how do I achieve the same functionality? man date didn't show any promise, unless I missed something obvious.

share|improve this question

3 Answers 3

There are a number of commands on FreeBSD that use the same API as GNU date to input natural language dates from the user. I've just found one that can be tricked into converting that date into Unix epoch time:

/usr/sbin/fifolog_reader -B 'last sunday' /dev/null 2>&1 |
  sed 's/^From[[:blank:]]*\([0-9]*\).*/\1/p'

(note that at least on FreeBSD 9.1-RELEASE-p2 where I tried that on, it only seems to work reliably if you're in a UTC timezone and the date specifications it recognises are not necessarily the same as those recognised by GNU date).

Note that some shells have that capability builtin.

ksh93:

if (( timestamp < $(printf '%(%s)T' 'last sunday') )); then

zsh:

autoload calendar_scandate
calendar_scandate 'last sun'
if (( timestamp < REPLY)); then...

Or you could use perl and the Date::Manip if installed:

last_sun=$(perl -MDate::Manip -e 'print UnixDate("last sunday","%s")')
if [ "$timestamp" -lt "$last_sun" ]; then...

Or:

if perl -MDate::Manip -e 'exit 1 unless $ARGV[0] < UnixDate("last sunday","%s")
    ' "$timestamp"; then....

If the aim is to check file timestamps, then note that FreeBSD find supports:

find file -prune -newermt 'last sunday'

In this very case, if you want the time of the beginning of this week (weeks starting on Sunday), you can do:

week_start=$(($(date '+%s - 86400*%w - 3600*%H - 60*%M - %S')))

That should work on both GNU and FreeBSD (or any system where %s is supported).

In timezones with summer time, that will be off by an hour around the switch from/to summer time.

share|improve this answer
    
Thanks for the find usage - it may be useful for future work, so I up voted. Regarding using different shells - I don't have them installed, and I rather write bash (which I'm very familiar with). Perl is a bit of heavy lifting for the task, but I'll do it if don't find an alternative - which I had already. –  Guss Aug 6 at 11:04

Probably the best way to ensure compatibility is to install GNU date on the FreeBSD system.

You can install the coreutils package from the FreeBSD ports collection. This will put the GNU date command into /usr/local/bin/gdate.

share|improve this answer

While it may not be applicable to all operations that can be expressed easily in natural language, FreeBSD's date has the -v operator that allows to set both arbitrary and relative values to separate date fields, and this can be repeated as necessary to produce most effects.

For example, to get "last sunday" one can apply "zero out all time fields" followed by "zero out weekday", like this:

date -v0S -v0M -v0H -v0w

so bash-speak for "give me the seconds since the epoch of the start of the last sunday, regardless if you are running on Linux or BSD", will look like this:

last_sunday_start() {
    if [ "$(uname)" = "Linux" ]; then
        date +"%s" -d "next sunday -1 week"
    else
        date -v0S -v0M -v0H -v0w +"%s"
    fi
}

Note that the GNU date example in the question is incorrect if you want to get the "last time time Sunday 00:00:00 occurred" - it will return the start of the previous Sunday when called during Sunday. The above code also fixes the GNU date time specification for that.

share|improve this answer
1  
That will yield different results if run on Sunday. You may prefer date -v -1d -v -sunw –  Stéphane Chazelas Aug 6 at 11:31
    
Thanks - you are correct. Thought what I actually want is "last time Sunday started", unlike GNU's date -d "last sunday" which is "last time a full Sunday occurred", so date -v0S -v0M -v0H -v-sunw is actually exactly what I need and the GNU date syntax is incorrect :-) I fixed my answer to reflect that the example in my question is incorrect. –  Guss Aug 6 at 12:09
    
You can also do date -d 'next sunday -1 week' (though that doesn't work with the fifolog_reader of my answer). –  Stéphane Chazelas Aug 6 at 12:22
    
Thanks again! your date expression is better than mine, so I'll fix my answer. BTW - on my system (based on FreeBSD 9.1), that expression also works with your fifolog_reader command (which frankly I didn't notice until you mentioned it now - I read an earlier version of your answer and then only read the bottom of the update, sorry :-) ). –  Guss Aug 6 at 13:18
    
With the FreeBSD I'm trying this on (9.1-RELEASE-p2) next thursday -1 week gives me tomorrow. And actually, it gives me random results for any timezone other than UTC, so I'll have to add a warning about that in my answer. –  Stéphane Chazelas Aug 6 at 13:27

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.