Re: Need localization-proof method of transporting dates.
Re: Need localization-proof method of transporting dates.
- Subject: Re: Need localization-proof method of transporting dates.
- From: Christopher Kane <email@hidden>
- Date: Tue, 7 Apr 2009 11:18:23 -0700
Now that everybody else has had their say, I'll throw in my two
bits: ;-)
* as others have pointed out, never store the hash of an object or
data computed from the hash, nor transmit the hash of an object
outside a process, if your goal is to compare it in any way with
anything else (for example, storing it as [part of] keys in a database
with the later hope of using the hash to retrieve records).
* the best thing to compare against (and include in your SHA-1 hash)
is the result of the -timeIntervalSinceReferenceDate method (-
timeIntervalSince1970 is equivalent, just shifted by a constant
offset); the time interval is an absolute timescale that is not
affected by time zones, locales, or calendars.
* the current time interval of the machine can be gotten with +[NSDate
timeIntervalSinceReferenceDate], and you need not mess with an NSDate
object itself if you don't want to.
* NSDates just store a time interval in the absolute scale; they
themselves are not affected by time zones, locales, or calendars.
However, when you produce a different representation of the date, that
different representation can be affected by other factors. For
example, breaking down the time interval into calendrical components
(year, month, day, ...) must be done in relation to some calendar, and
often in relation to some time zone. So, if you ever rely on the
user's settings of these on their machine for their account, you've
lost. Plus the algorithms for "breaking down" and "reconstituting"
from components can have bugs or get changes from OS release to OS
release (unless you just write your own), and of course time zone data
can change between OS releases (and software updates), so going
through the extra steps of using calendrical components would have you
relying on a lot more stuff remaining unchanged.
* Using a string representation of a date is the absolute worst
possibility, since it's affected by all those things listed above
(time zones, locales, and calendars), plus involves components, plus
is a different representation. There might be some people who would
say "an all-numeric components representation would be fine [if you
made sure to generate it with respect to some specific fixed calendar
and time zone]", but beyond what I've already noted, with a string
representation you have the excitement of different Unicode code
points that could be used to represent the digits (e.g., try running
in an Arabic locale) or even different number representation systems
(e.g., the Roman numerals of the Romans or the base-60 of the
Babylonians -- I don't know if any locales have such a thing today,
but unless _you_ know, it's best to just stay away). So you should be
sure to also generate the string description entirely yourself as
well; don't use the system code for that.
So all that is why I suggest skipping all the extra work and
intermediate steps and just use the timeIntervalSinceReferenceDate.
It's a nice double, and you can compare with <, >, etc. (Of course,
if you choose to hash the 8 bytes of the double as a chunk of bytes,
then you have to take machine representation of doubles into account
and make sure you know what you're doing there.)
Chris Kane
Cocoa Frameworks, Apple
On Apr 4, 2009, at 5:01 AM, Graham Cox wrote:
My app encodes expiry dates for demo versions, etc.
One problem I've had occasional reports of is that the expiry is
prematurely detected, and it seems to be on systems with system
language set other than English. I need to store and check the dates
in a way that is not sensitive to this. I thought I was, yet the
reports persist.
Here's what I'm doing:
The stored date originally comes from a NSDatePicker control,
textual with stepper. I retrieve the date using its -dateValue method.
The date, along with other data, is digitally signed with a SHA-1
hash, which in turn is based on the object's -hash method. As far as
I could tell, the -hash method returns a value that is sensitive to
the actual stored date, but not to the date localization on the
system.
At runtime, the date is recovered and verified by rehashing and
comparing the hash, then the date value is simply compared to see if
the current date is before or after it using [[NSDate date]
timeIntervalSinceDate:expiryDate] (if negative, hasn't expired).
Can anyone spot any problem with this approach? Note that the SHA-1
check appears to pass OK - it's the date comparison that seems to be
wrong. Unfortunately I can't reproduce the bug locally so I'm
relying on reports from relatively non-technical testers who aren't
able to give me much to go on.
--Graham
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden