Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

How is this possible and how do I deal with it? I'm making backup script that is dependent on Unix date and have discovered an interesting bug:

[root@web000c zfs_test]# date +%y-%m-%d --date='2 months ago'
14-04-01
[root@web000c zfs_test]# date +%y-%m-%d --date='3 months ago'
14-02-28
[root@web000c zfs_test]# date
Sun Jun  1 00:08:50 CEST 2014
share|improve this question
    
Could it be a leap year/Feb 29 bug? Unlikely in a tool like date though... –  Mark Henderson Jun 12 at 2:41

3 Answers 3

up vote 42 down vote accepted

You're seeing this behavior because of summer time (daylight saving time).

Because you are currently in summer time, where your clock is one hour ahead, when you ask for three months ago at just after midnight on the first of June, the time ends up being one hour "earlier" because it was not summer time three months ago.

The GNU date documentation suggests to work around this by using 12:00 noon and the 15th of the month as starting points, when asking for relative days or months, respectively. For example:

date +%y-%m-%d --date="$(date +%Y-%m-15) -3 month"
share|improve this answer
    
thank you. Yes, exactly "3 months ago" coming by 01 am: [root@web000c zfs_test]# date +%y-%m-%d --date='3 months ago' 14-03-01 [root@web000c zfs_test]# date Sun Jun 1 01:00:15 CEST 2014 –  Shirker Jun 12 at 3:01
    
Doh! I think I need to go grep through some of my scripts as I suspect I've overlooked this suggestion on date usage. –  Caleb Jun 13 at 8:16

If absolute timing is your primary concern, it's probably best to work off of UTC as it exists for that purpose. Michael's answer is very useful for when you have to work inside of the problem, but it's usually a good idea to avoid it entirely where you can.

When your system isn't set to UTC by default, the simplest way to pass the timezone in is by prefixing your command with the TZ environment variable. This limits the zone switch to a single command and keeps the variable from leaking into your subsequent commands.

$ NOW=$(date '+%s')
$ date -d @$NOW
Wed Jun 11 23:44:35 EDT 2014
$ TZ=UTC date -d @$NOW
Thu Jun 12 03:44:35 UTC 2014

What you shouldn't do is export the TZ variable as this can make things very confusing to troubleshoot, as the following demonstrates.

$ export TZ=UTC
$ date -d @$NOW
Thu Jun 12 03:44:35 UTC 2014
$ TZ=EDT date -d @$NOW
Thu Jun 12 03:44:35 EDT 2014
share|improve this answer

On this specific year that your computer thinks it being operated in, and on the specific date you chose for a test of "1 month ago, 2 months ago, and 3 months ago, yes - it is likely a February 29 detection. Not always an error, but ..

Now, today is NOT 2014-06-01. Try again. Set the computer date to 2013-06-01. Try again.
Set the computer date to 2014-09-01. Try again.

share|improve this answer
6  
If you are providing dates in American MDY format, plase use /es for separating. Even better, as we are an international community here, use proper ISO dates such as 2014-09-01. –  glglgl Jun 12 at 13:38

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.