1. 03 Sep, 2015 2 commits
    • Jeff King's avatar
      date: make "local" orthogonal to date format · add00ba2
      Jeff King authored
      Most of our "--date" modes are about the format of the date:
      which items we show and in what order. But "--date=local" is
      a bit of an oddball. It means "show the date in the normal
      format, but using the local timezone". The timezone we use
      is orthogonal to the actual format, and there is no reason
      we could not have "localized iso8601", etc.
      
      This patch adds a "local" boolean field to "struct
      date_mode", and drops the DATE_LOCAL element from the
      date_mode_type enum (it's now just DATE_NORMAL plus
      local=1). The new feature is accessible to users by adding
      "-local" to any date mode (e.g., "iso-local"), and we retain
      "local" as an alias for "default-local" for backwards
      compatibility.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: John Keeping's avatarJohn Keeping <john@keeping.me.uk>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      add00ba2
    • John Keeping's avatar
      date: check for "local" before anything else · dc6d782c
      John Keeping authored
      In a following commit we will make "local" orthogonal to the format.
      Although this will not apply to "relative", which does not use the
      timezone, it applies to all other formats so move the timezone
      conversion to the start of the function.
      Signed-off-by: John Keeping's avatarJohn Keeping <john@keeping.me.uk>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      dc6d782c
  2. 29 Jun, 2015 2 commits
    • Jeff King's avatar
      introduce "format" date-mode · aa1462cc
      Jeff King authored
      This feeds the format directly to strftime. Besides being a
      little more flexible, the main advantage is that your system
      strftime may know more about your locale's preferred format
      (e.g., how to spell the days of the week).
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      aa1462cc
    • Jeff King's avatar
      convert "enum date_mode" into a struct · a5481a6c
      Jeff King authored
      In preparation for adding date modes that may carry extra
      information beyond the mode itself, this patch converts the
      date_mode enum into a struct.
      
      Most of the conversion is fairly straightforward; we pass
      the struct as a pointer and dereference the type field where
      necessary. Locations that declare a date_mode can use a "{}"
      constructor.  However, the tricky case is where we use the
      enum labels as constants, like:
      
        show_date(t, tz, DATE_NORMAL);
      
      Ideally we could say:
      
        show_date(t, tz, &{ DATE_NORMAL });
      
      but of course C does not allow that. Likewise, we cannot
      cast the constant to a struct, because we need to pass an
      actual address. Our options are basically:
      
        1. Manually add a "struct date_mode d = { DATE_NORMAL }"
           definition to each caller, and pass "&d". This makes
           the callers uglier, because they sometimes do not even
           have their own scope (e.g., they are inside a switch
           statement).
      
        2. Provide a pre-made global "date_normal" struct that can
           be passed by address. We'd also need "date_rfc2822",
           "date_iso8601", and so forth. But at least the ugliness
           is defined in one place.
      
        3. Provide a wrapper that generates the correct struct on
           the fly. The big downside is that we end up pointing to
           a single global, which makes our wrapper non-reentrant.
           But show_date is already not reentrant, so it does not
           matter.
      
      This patch implements 3, along with a minor macro to keep
      the size of the callers sane.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      a5481a6c
  3. 15 Apr, 2015 2 commits
  4. 13 Nov, 2014 2 commits
    • Jeff King's avatar
      approxidate: allow ISO-like dates far in the future · d3723953
      Jeff King authored
      When we are parsing approxidate strings and we find three
      numbers separate by one of ":/-.", we guess that it may be a
      date. We feed the numbers to match_multi_number, which
      checks whether it makes sense as a date in various orderings
      (e.g., dd/mm/yy or mm/dd/yy, etc).
      
      One of the checks we do is to see whether it is a date more
      than 10 days in the future. This was added in 38035cf4 (date
      parsing: be friendlier to our European friends.,
      2006-04-05), and lets us guess that if it is currently April
      2014, then "10/03/2014" is probably March 10th, not October
      3rd.
      
      This has a downside, though; if you want to be overly
      generous with your "--until" date specification, we may
      wrongly parse "2014-12-01" as "2014-01-12" (because the
      latter is an in-the-past date). If the year is a future year
      (i.e., both are future dates), it gets even weirder. Due to
      the vagaries of approxidate, months _after_ the current date
      (no matter the year) get flipped, but ones before do not.
      
      This patch drops the "in the future" check for dates of this
      form, letting us treat them always as yyyy-mm-dd, even if
      they are in the future. This does not affect the normal
      dd/mm/yyyy versus mm/dd/yyyy lookup, because this code path
      only kicks in when the first number is greater than 70
      (i.e., it must be a year, and cannot be either a date or a
      month).
      
      The one possible casualty is that "yyyy-dd-mm" is less
      likely to be chosen over "yyyy-mm-dd". That's probably OK,
      though because:
      
        1. The difference happens only when the date is in the
           future. Already we prefer yyyy-mm-dd for dates in the
           past.
      
        2. It's unclear whether anybody even uses yyyy-dd-mm
           regularly. It does not appear in lists of common date
           formats in Wikipedia[1,2].
      
        3. Even if (2) is wrong, it is better to prefer ISO-like
           dates, as that is consistent with what we use elsewhere
           in git.
      
      [1] http://en.wikipedia.org/wiki/Date_and_time_representation_by_country
      [2] http://en.wikipedia.org/wiki/Calendar_dateSigned-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      d3723953
    • Jeff King's avatar
      pass TIME_DATE_NOW to approxidate future-check · 073281e2
      Jeff King authored
      The approxidate functions accept an extra "now" parameter to
      avoid calling time() themselves. We use this in our test
      suite to make sure we have a consistent time for computing
      relative dates. However, deep in the bowels of approxidate,
      we also call time() to check whether possible dates are far
      in the future. Let's make sure that the "now" override makes
      it to that spot, too, so we can consistently test that
      feature.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      073281e2
  5. 29 Aug, 2014 1 commit
  6. 27 Aug, 2014 1 commit
    • Jeff King's avatar
      date: use strbufs in date-formatting functions · c33ddc2e
      Jeff King authored
      Many of the date functions write into fixed-size buffers.
      This is a minor pain, as we have to take special
      precautions, and frequently end up copying the result into a
      strbuf or heap-allocated buffer anyway (for which we
      sometimes use strcpy!).
      
      Let's instead teach parse_date, datestamp, etc to write to a
      strbuf. The obvious downside is that we might need to
      perform a heap allocation where we otherwise would not need
      to. However, it turns out that the only two new allocations
      required are:
      
        1. In test-date.c, where we don't care about efficiency.
      
        2. In determine_author_info, which is not performance
           critical (and where the use of a strbuf will help later
           refactoring).
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      c33ddc2e
  7. 17 Apr, 2014 1 commit
  8. 24 Feb, 2014 2 commits
    • Jeff King's avatar
      log: do not segfault on gmtime errors · 2b15846d
      Jeff King authored
      Many code paths assume that show_date and show_ident_date
      cannot return NULL. For the most part, we handle missing or
      corrupt timestamps by showing the epoch time t=0.
      
      However, we might still return NULL if gmtime rejects the
      time_t we feed it, resulting in a segfault. Let's catch this
      case and just format t=0.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      2b15846d
    • Jeff King's avatar
      date: check date overflow against time_t · 7ca36d93
      Jeff King authored
      When we check whether a timestamp has overflowed, we check
      only against ULONG_MAX, meaning that strtoul has overflowed.
      However, we also feed these timestamps to system functions
      like gmtime, which expect a time_t. On many systems, time_t
      is actually smaller than "unsigned long" (e.g., because it
      is signed), and we would overflow when using these
      functions.  We don't know the actual size or signedness of
      time_t, but we can easily check for truncation with a simple
      assignment.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      7ca36d93
  9. 24 Oct, 2013 1 commit
  10. 17 Apr, 2013 1 commit
    • Junio C Hamano's avatar
      date.c: add parse_expiry_date() · 3d27b9b0
      Junio C Hamano authored
      "git reflog --expire=all" tries to expire reflog entries up to the
      current second, because the approxidate() parser gives the current
      timestamp for anything it does not understand (and it does not know
      what time "all" means).  When the user tells us to expire "all" (or
      set the expiration time to "now"), the user wants to remove all the
      reflog entries (no reflog entry should record future time).
      
      Just set it to ULONG_MAX and to let everything that is older that
      timestamp expire.
      
      While at it, allow "now" to be treated the same way for callers that
      parse expiry date timestamp with this function.  Also use an error
      reporting version of approxidate() to report misspelled date.  When
      the user says e.g. "--expire=mnoday" to delete entries two days or
      older on Wednesday, we wouldn't want the "unknown, default to now"
      logic to kick in.
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      3d27b9b0
  11. 25 Feb, 2013 2 commits
  12. 12 Jul, 2012 1 commit
  13. 24 Apr, 2012 1 commit
  14. 04 Feb, 2012 2 commits
    • Junio C Hamano's avatar
      parse_date(): '@' prefix forces git-timestamp · 2c733fb2
      Junio C Hamano authored
      The only place that the issue this series addresses was observed
      where we read "cat-file commit" output and put it in GIT_AUTHOR_DATE
      in order to replay a commit with an ancient timestamp.
      
      With the previous patch alone, "git commit --date='20100917 +0900'"
      can be misinterpreted to mean an ancient timestamp, not September in
      year 2010.  Guard this codepath by requring an extra '@' in front of
      the raw git timestamp on the parsing side. This of course needs to
      be compensated by updating get_author_ident_from_commit and the code
      for "git commit --amend" to prepend '@' to the string read from the
      existing commit in the GIT_AUTHOR_DATE environment variable.
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      2c733fb2
    • Junio C Hamano's avatar
      parse_date(): allow ancient git-timestamp · 116eb3ab
      Junio C Hamano authored
      The date-time parser parses out a human-readble datestring piece by
      piece, so that it could even parse a string in a rather strange
      notation like 'noon november 11, 2005', but restricts itself from
      parsing strings in "<seconds since epoch> <timezone>" format only
      for reasonably new timestamps (like 1974 or newer) with 10 or more
      digits. This is to prevent a string like "20100917" from getting
      interpreted as seconds since epoch (we want to treat it as September
      17, 2010 instead) while doing so.
      
      The same codepath is used to read back the timestamp that we have
      already recorded in the headers of commit and tag objects; because
      of this, such a commit with timestamp "0 +0000" cannot be rebased or
      amended very easily.
      
      Teach parse_date() codepath to special case a string of the form
      "<digits> +<4-digits>" to work this issue around, but require that
      there is no other cruft around the string when parsing a timestamp
      of this format for safety.
      
      Note that this has a slight backward incompatibility implications.
      
      If somebody writes "git commit --date='20100917 +0900'" and wants it
      to mean a timestamp in September 2010 in Japan, this change will
      break such a use case.
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      116eb3ab
  15. 12 Sep, 2011 1 commit
  16. 21 Apr, 2011 1 commit
    • Michael J Gruber's avatar
      date: avoid "X years, 12 months" in relative dates · f1e9c548
      Michael J Gruber authored
      When relative dates are more than about a year ago, we start
      writing them as "Y years, M months".  At the point where we
      calculate Y and M, we have the time delta specified as a
      number of days. We calculate these integers as:
      
        Y = days / 365
        M = (days % 365 + 15) / 30
      
      This rounds days in the latter half of a month up to the
      nearest month, so that day 16 is "1 month" (or day 381 is "1
      year, 1 month").
      
      We don't round the year at all, though, meaning we can end
      up with "1 year, 12 months", which is silly; it should just
      be "2 years".
      
      Implement this differently with months of size
      
        onemonth = 365/12
      
      so that
      
        totalmonths = (long)( (days + onemonth/2)/onemonth )
        years = totalmonths / 12
        months = totalmonths % 12
      
      In order to do this without floats, we write the first formula as
      
        totalmonths = (days*12*2 + 365) / (365*2)
      
      Tests and inspiration by Jeff King.
      Helped-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarMichael J Gruber <git@drmicha.warpmail.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      f1e9c548
  17. 15 Jul, 2010 1 commit
  18. 05 Jul, 2010 1 commit
    • Jeff King's avatar
      parse_date: fix signedness in timezone calculation · 9ba0f033
      Jeff King authored
      When no timezone is specified, we deduce the offset by
      subtracting the result of mktime from our calculated
      timestamp.
      
      However, our timestamp is stored as an unsigned integer,
      meaning we perform the subtraction as unsigned. For a
      negative offset, this means we wrap to a very high number,
      and our numeric timezone is in the millions of hours. You
      can see this bug by doing:
      
         $ TZ=EST \
           GIT_AUTHOR_DATE='2010-06-01 10:00' \
           git commit -a -m foo
         $ git cat-file -p HEAD | grep author
         author Jeff King <peff@peff.net> 1275404416 +119304128
      
      Instead, we should perform this subtraction as a time_t, the
      same type that mktime returns.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      9ba0f033
  19. 07 Jun, 2010 1 commit
  20. 19 May, 2010 1 commit
  21. 26 Jan, 2010 1 commit
    • Junio C Hamano's avatar
      approxidate_careful() reports errorneous date string · 93cfa7c7
      Junio C Hamano authored
      For a long time, the time based reflog syntax (e.g. master@{yesterday})
      didn't complain when the "human readable" timestamp was misspelled, as
      the underlying mechanism tried to be as lenient as possible.  The funny
      thing was that parsing of "@{now}" even relied on the fact that anything
      not recognized by the machinery returned the current timestamp.
      
      Introduce approxidate_careful() that takes an optional pointer to an
      integer, that gets assigned 1 when the input does not make sense as a
      timestamp.
      
      As I am too lazy to fix all the callers that use approxidate(), most of
      the callers do not take advantage of the error checking, but convert the
      code to parse reflog to use it as a demonstration.
      
      Tests are mostly from Jeff King.
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      93cfa7c7
  22. 20 Jan, 2010 1 commit
  23. 03 Oct, 2009 1 commit
  24. 31 Aug, 2009 2 commits
  25. 28 Aug, 2009 1 commit
  26. 23 Aug, 2009 2 commits
    • Linus Torvalds's avatar
      Further 'approxidate' improvements · 36e4986f
      Linus Torvalds authored
      The previous patch to improve approxidate got us to the point that a lot
      of the remaining annoyances were due to the 'strict' date handling running
      first, and deciding that it got a good enough date that the approximate
      date routines were never even invoked.
      
      For example, using a date string like
      
      	6AM, June 7, 2009
      
      the strict date logic would be perfectly happy with the "June 7, 2009"
      part, and ignore the 6AM part that it didn't understand - resulting in the
      information getting dropped on the floor:
      
      	6AM, June 7, 2009 -> Sat Jun 6 00:00:00 2009
      
      and the date being calculated as if it was midnight, and the '6AM' having
      confused the date routines into thinking about '6 June' rather than 'June
      7' at 6AM (ie notice how the _day_ was wrong due to this, not just the
      time).
      
      So this makes the strict date routines a bit stricter, and requires that
      not just the date, but also the time, has actually been parsed. With that
      fix, and trivial extension of the approxidate routines, git now properly
      parses the date as
      
      	6AM, June 7, 2009 -> Sun Jun  7 06:00:00 2009
      
      without dropping the fuzzy time ("6AM" or "noon" or any of the other
      non-strict time formats) on the floor.
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      36e4986f
    • Linus Torvalds's avatar
      Improve on 'approxidate' · 90290552
      Linus Torvalds authored
      This is not a new failure mode - approxidate has always been kind of
      random in the input it accepts, but some of the randomness is more
      irritating than others.
      
      For example:
      
      	Jun 6, 5AM -> Mon Jun 22 05:00:00 2009
      	5AM Jun 6 -> Sat Jun  6 05:00:00 2009
      
      Whaa? The reason for the above is that approxidate squirrells away the '6'
      from "Jun 6" to see if it's going to be a relative number, and then
      forgets about it when it sees a new number (the '5' in '5AM'). So the odd
      "June 22" date is because today is July 22nd, and if it doesn't have
      another day of the month, it will just pick todays mday - having ignored
      the '6' entirely due to getting all excited about seeing a new number (5).
      
      There are other oddnesses. This does not fix them all, but I think it
      makes for fewer _really_ perplexing cases. At least now we have
      
      	Jun 6, 5AM -> Sat Jun  6 05:00:00 2009
      	5AM, Jun 6 -> Sat Jun  6 05:00:00 2009
      
      which makes me happier. I can still point to cases that don't work as
      well, but those are separate issues.
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      90290552
  27. 06 May, 2009 1 commit
  28. 25 Feb, 2009 1 commit
  29. 21 Feb, 2009 1 commit
    • Linus Torvalds's avatar
      Support 'raw' date format · 7dff9b30
      Linus Torvalds authored
      Talking about --date, one thing I wanted for the 1234567890 date was to
      get things in the raw format. Sure, you get them with --pretty=raw, but it
      felt a bit sad that you couldn't just ask for the date in raw format.
      
      So here's a throw-away patch (meaning: I won't be re-sending it, because I
      really don't think it's a big deal) to add "--date=raw". It just prints
      out the internal raw git format - seconds since epoch plus timezone (put
      another way: 'date +"%s %z"' format)
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      7dff9b30
  30. 13 Nov, 2008 1 commit
    • Linus Torvalds's avatar
      date/time: do not get confused by fractional seconds · e9854a76
      Linus Torvalds authored
      The date/time parsing code was confused if the input time HH:MM:SS is
      followed by fractional seconds.  Since we do not record anything finer
      grained than seconds, we could just drop fractional part, but there is a
      twist.
      
      We have taught people that not just spaces but dot can be used as word
      separators when spelling things like:
      
          $ git log --since 2.days
          $ git show @{12:34:56.7.days.ago}
      
      and we shouldn't mistake "7" in the latter example as a fraction and
      discard it.
      
      The rules are:
      
       - valid days of month/mday are always single or double digits.
      
       - valid years are either two or four digits
      
         No, we don't support the year 600 _anyway_, since our encoding is based
         on the UNIX epoch, and the day we worry about the year 10,000 is far
         away and we can raise the limit to five digits when we get closer.
      
       - Other numbers (eg "600 days ago") can have any number of digits, but
         they cannot start with a zero. Again, the only exception is for
         two-digit numbers, since that is fairly common for dates ("Dec 01" is
         not unheard of)
      
      So that means that any milli- or micro-second would be thrown out just
      because the number of digits shows that it cannot be an interesting date.
      
      A milli- or micro-second can obviously be a perfectly fine number
      according to the rules above, as long as it doesn't start with a '0'. So
      if we have
      
      	12:34:56.123
      
      then that '123' gets parsed as a number, and we remember it. But because
      it's bigger than 31, we'll never use it as such _unless_ there is
      something after it to trigger that use.
      
      So you can say "12:34:56.123.days.ago", and because of the "days", that
      123 will actually be meaninful now.
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      e9854a76
  31. 18 Aug, 2008 1 commit
    • Linus Torvalds's avatar
      date/time: do not get confused by fractional seconds · 9f2b6d29
      Linus Torvalds authored
      The date/time parsing code was confused if the input time HH:MM:SS is
      followed by fractional seconds.  Since we do not record anything finer
      grained than seconds, we could just drop fractional part, but there is a
      twist.
      
      We have taught people that not just spaces but dot can be used as word
      separators when spelling things like:
      
          $ git log --since 2.days
          $ git show @{12:34:56.7.days.ago}
      
      and we shouldn't mistake "7" in the latter example as a fraction and
      discard it.
      
      The rules are:
      
       - valid days of month/mday are always single or double digits.
      
       - valid years are either two or four digits
      
         No, we don't support the year 600 _anyway_, since our encoding is based
         on the UNIX epoch, and the day we worry about the year 10,000 is far
         away and we can raise the limit to five digits when we get closer.
      
       - Other numbers (eg "600 days ago") can have any number of digits, but
         they cannot start with a zero. Again, the only exception is for
         two-digit numbers, since that is fairly common for dates ("Dec 01" is
         not unheard of)
      
      So that means that any milli- or micro-second would be thrown out just
      because the number of digits shows that it cannot be an interesting date.
      
      A milli- or micro-second can obviously be a perfectly fine number
      according to the rules above, as long as it doesn't start with a '0'. So
      if we have
      
      	12:34:56.123
      
      then that '123' gets parsed as a number, and we remember it. But because
      it's bigger than 31, we'll never use it as such _unless_ there is
      something after it to trigger that use.
      
      So you can say "12:34:56.123.days.ago", and because of the "days", that
      123 will actually be meaninful now.
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      9f2b6d29