Re: Date-Only NSTimestamps
Re: Date-Only NSTimestamps
- Subject: Re: Date-Only NSTimestamps
- From: Chuck Hill <email@hidden>
- Date: Wed, 2 Jan 2008 13:49:06 -0800
I am getting really sorry I started reading this thread! :-)
On Jan 2, 2008, at 1:25 PM, Pierce T. Wetter III wrote:
On Jan 2, 2008, at 1:01 PM, David Avendasora wrote:
Hi all,
I am working on some date-related calculations for a report. On
the report the user specifies a date, and I want to match to a
NSTimestamp-typed attribute in my Entity. The problem is that, of
course, the attribute also contains time information which for
this report is meaningless.
I've come up with a couple ways to achieve what I'm trying to do,
and they seem to work, but they feel _very_ clunky and overly
difficult, which brings me back to the old WO axiom: if it's hard,
you're probably not doing it the WO-way.
So, what are the best practices for working with an NSTimestamp
field, when all you really want is the date, not the time?
There's not really a good solution, in my experience. I'm A bit of
a date/time wonk, so this may be an overly long and opinionated
answer, but I feel like venting.
Vent on McDuff!
First off, setting the time to 00:00:00 sucks. It sucks because at
midnight, there is no different between Monday and Tuesday. Monday
is 23:59.999999999999999999999999 (repeat ad infinitum).
Is that right? IIRC, java.util.Date (which is what NSTimestamp
extends) is only measured to the millisecond. So Monday is 23:59:59.999
Why does this matter? Because you can easily ass-raped by time zones.
Yes, yes, you certainly can. Stings too.
Tuesday midnight can very easily turn into Monday midnight-almost.
Monday not-quite-midnight can very easily turn into Tuesday
midnight. I'll just skip over daylight savings time woes.
A typical hack is to normalize everything to noon in a particular
time zone instead. So anytime you get a date, you immediately move
it to noon. In Objective-C, you could do this via a category, which
could return a subclass of NSCalendarDate which knew it was
normalized and would do the right thing, and it would override
things so the math would work correctly (DST can screw up date
calculations). So then you could go crazy calling "normalize" every
time you got a date, and be safe, because the subclass knew that
normalize was a no-op.
Of course, we're in Java, so we're screwed. You'll have to add a
completely separate class to do the normalization, which then just
gives you a normal NSTimestamp back, so you can find that your app
will spend an inordinate amount of time normalizing the dates.
For as long as I've been using WebObjects, I've been submitting
feature requests to be able to map the basic number types to custom
alternative classes. That would have solved the problem directly,
because then WO could pull an integer out of the database, which
could then be mapped to a date class and back again.
It might be possible now using the new enum support in 5.4, but
only as a hack, and I haven't looked at it.
Anyways, on to your problem, because none of that really affects
you except the midnight issue.
In your case, you're doing a report, so you have 2 date ranges. So
this then becomes a UI question. Let's say someone wants to do a
query for 2007. In most reporting software, that becomes:
WHERE date >= TIMESTAMP '2007-01-01 00:00:00' and date <
TIMESTAMP '2008-01-01 00:00:00'
that is, to get all of 2007, you really have to put the end date
in as midnight of the first second of 2008. Which is weird UI,
because the dates themselves are:
2007-01-01 to 2007-12-31
without the times...
Similarly, putting in:
2007-01-01 to 2007-01-01 gets you _zero_ days, because that's
midnight to midnight of the same day.
So.... What you can do is basically tweak the inputs. The low date
is rounded _down_ to midnight, the high date is converted to the
_next_ day then rounded down.
where date >= input_low.beginningOfDay() and date <
input_high.nextDay().beginningOfDay()
Note that this conflicts with the previous responses which tell you
to do:
WHERE date >= input_low.beginningOfDay and date <=
input_high.endOfDay()
David LeBer and Chuck Hill actually have a subtle bug, because
they probably have endOfDay() coded as 23:59:59.0000, but that
means there's a whole second they won't be including, the time
between 23:59:59.00000000000000000000000000001 and the next day...
There's a whole second there that shows up in limbo. Which would
really bum you out if say, the bank was adding up transactions for
the day, and missed your paycheck if it was deposited right then...
I am not convinced. My end of day is 23:59:59.999, the next instant
that can be measured is 1 millisecond later, 00:00:00.000. There is
no gap, but the underlying OS needs to round the internal clock ticks
(nanos or whatever) up or down to the nearest millisecond.
Am I missing something here?
Having both <= and >= in a where clause dealing with dates is
always a tip off for me. It should always be >= and <.
You can make the "endOfDay()" limbo arbitrarily small, by
encloding endOfDay() as 23:59:59.99999999999 or some such, but
then its really easy to have things roll over when you didn't want
them to. It's better to use < instead of <=, and use midnight of
the following day instead.
Chuck
--
Practical WebObjects - for developers who want to increase their
overall knowledge of WebObjects or who are trying to solve specific
problems.
http://www.global-village.net/products/practical_webobjects
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden