Subject: [sieve] Julian date vs. :zone...

From: Hannah Schroeter <[email-masked]>
Date: Thu, 17 Sep 2009 18:07:02 +0200

Hello!

RFC 5260 states

     "julian"    => the Modified Julian Day, that is, the date
                    expressed as an integer number of days since
                    00:00 UTC on November 17, 1858 (using the Gregorian
                    calendar).  This corresponds to the regular
                    Julian Day minus 2400000.5.  Sample routines to
                    convert to and from modified Julian dates are
                    given in Appendix A.

Do I understand it right that date-part "julian" ignores any timezones
that way?

According to http://en.wikipedia.org/wiki/Julian_day,
  A Julian date of 2454115.05486 means that the date and Universal Time
  is Sunday January 14, 2007 at 13:18:59.9.
So "julian" for that time would be 54114.55486, truncated down, i.e.
54114? So I could calculate "julian" by using an Unix timestamp,
dividing it by 86400 and adding 39610 to it, without any timestamp
corrections?

Kind regards,

Hannah.

---

From: Hannah Schroeter <[email-masked]>
Date: Thu, 17 Sep 2009 18:21:05 +0200

Hello again.

>dividing it by 86400 and adding 39610 to it, without any timestamp

Seems I did something wrong. Just checked again and the offset must be
40587.

According to the table there:
  http://en.wikipedia.org/wiki/Julian_day#Alternatives

Unix time (U) is (JD - 2440587.5) * 86400
Modified Julian Day (MJD) is JD - 2400000.5

So U / 86400 = JD - 2440587.5 = MJD + 2400000.5 - 2440587.5 = MJD - 40587,
so MJD = U / 86400 - 40587.

"julian" would be trunc(MJD), if I understand things right and the
timezone doesn't affect the "julian" date-part of RFC 5260.

If one uses large enough (e.g. 64 bit) integers to encode the parsed
date field, together with a timezone offset (for the case if the script
specifies :originalzone), one can use that and generate MJD and other
date-parts from it.

Kind regards,

Hannah.

---

From: [email-masked]
Date: Thu, 17 Sep 2009 09:32:37 -0700 (PDT)

> Do I understand it right that date-part "julian" ignores any timezones

I'm not entirely clear on what you mean here, but if you're talking about
simply dropping any time zone component before converting to Julian day, then
no, that makes no sense.

Julian day is defined as the integral number of days between *two* points in
time. You're confusing the specification of the time zone for the first - fixed
- one of these points with the specification of the time zone for the second.

>   is Sunday January 14, 2007 at 13:18:59.9.

And you will note that the results were expressed in terms of a specific
time zone.

> 54114?

Correct but not especially relevant in the context of handling time zones.

> So I could calculate "julian" by using an Unix timestamp,

I don't know what you mean by "timestamp corrections", but if by "Unix
timestamp" you mean a time_t value expressing the number of seconds since Jan
01 1970 00:00 UTC, then yes, this should get you the modified Julian date.
However, this ignores how you got to that "Unix timestamp" in the first place.
If you did so by incorporating any time zone offset in the original time value
into the calculation, then it's all good. If, however, you simply dropped any
zone information, then the result can be incorrect.

Putting this in terms of standard C library functions, it's the difference
between calling mktime (correct) to get that time_t value and timegm (wrong).

				Ned

---

From: Hannah Schroeter <[email-masked]>
Date: Thu, 17 Sep 2009 19:41:39 +0200

Hello!

>simply dropping any time zone component before converting to Julian day, then

My question was this:

Date: ...

Does
  if date :zone "+0100" "Date" "julian" "..."
and
  if date :zone "-2300" "Date" "julian" "..."

make any difference, given the same mail header?

I.e. does "julian" in effect cause the test to "ignore" :zone; because
if I "translate" the same date-time to a different timezone, its
"distance" to the epoch (in this case, the one of the Modified Julian
Date) keeps staying the same?

While all other date-parts *are* influenced by different :zone values...

>- one of these points with the specification of the time zone for the second.

I don't confuse that, I think. I think you misunderstood my question.

>[...]

>between calling mktime (correct) to get that time_t value and timegm (wrong).

In fact, we use timegm, but then apply the time zone offset ourselves.
We have tests in order to check that that's correct. mktime uses the
*locale*'s timezone which isn't the timezone of the mail header's
date-time. We keep the original timezone value of the mail header in a
separate field (which will be needed for :originalzone).

BOOST_CHECK_EQUAL(parseDate("Thu, 1 Jan 1970 00:00:00 ut"),
    Date(0 /* timestamp */, 0 /* informational timezone offset */));
BOOST_CHECK_EQUAL(parseDate("Thu, 1 Jan 1970 01:00:00 +0100"),
    Date(0 /* timestamp */, 3600 /* informational timezone offset */));

Of course, we have additional other tests.

Kind regards,

Hannah.

---

From: [email-masked]
Date: Thu, 17 Sep 2009 17:38:41 -0700 (PDT)

> make any difference, given the same mail header?

Ah. That makes more sense then. The answer is no  - since a Julian day is an
interval between two points in time, not an absolute representation of a
particular point in time (unlike all the other date-parts) the use of :zone
ends up having no effect.

Of course this suggests a shortcut ot not applying :zone when the date-part is
"julian", but I'm skeptical the optimization is worth it.

> Date) keeps staying the same?

:zone ends up being effectively ignored because the Julian day calculation
requires normalization to GMT in order to get the internal right. So you can
apply the :zone if you want but any effect it has will be wiped out by the
subsequent normalization to GMT Julian day calculations require.

> While all other date-parts *are* influenced by different :zone values...

Yes.

> separate field (which will be needed for :originalzone).

Yes, use of mktime requires that you piddle around with the time zone setting
becauuse it won't be read from the structure. Bad API design... And that can
have thread safety issues. That said, I've also seen timegm implemented by
zeroing out the currently active time zone, calling mktime, and then restoring
it. So it may have the same problem.

				Ned