|
NotesDateTime And International Formats Please see the update to this article!
This article is a result of a correspondence with Manfred Dillaman, creator of the really cool madicon RSS Reader for Notes. As a result of a post in Volker's blog, which indicated that Manfred's application was having problems on systems confiugured to use the US date format (MM/DD/YYYY), Manfred and I began to correspond by email, and by putting our heads together we've learned a lot about what really goes on in the NotesDateTime object. When I read about the problem with dates, I took a closer look at what I was seeing when I used Manfred's app, and this is what I saw:
Figure 1: madicon RSS Reader - two different date formats
It didn't take long for me to realize the significance of what I saw, and I immediately emailed Manfred with the information. Dates with the day number of 12 or below displayed one way -- in the European format which is not the preference on my machine, and dates with the day number of 13 or above displayed the other way -- in the US format. The obvious implication is that some code, somewhere, is trying to be "smart" in dealing with "impossible" dates. If you give it a date that looks like it has a month greater than 12, it tries swapping the month and day, and if that works it assumes that you must have meant it that way.
RSS feeds contain a wide variety of date formats. Between the fact that there are so many different standards that fall under the label RSS, and the fact that there are so many different implementations of those standards, a good aggregator has to be able to deal with just about anything that even remotely resembles a date in either a pubDate date, or dc:date tag. Here are a couple of fragments of code from my bloggregator:
Figure 2. dealing with different date tags in an RSS feed
Figure 3. dealing with different date formats in various tags
As you can see in these code fragments, I've found that you simply can't count on any consistency between RSS feeds (and I've pulled more than 100 different feeds into my aggregator during testing) in terms of what tag will be used or what format will be used for the data contained in the tag for the date. You can't even count on the fact that there is a tag with date information. The safest approach was to recognize any of the tags, with any of the formats, hence the nested if-thens calling the same routine to check three different tags in Figure 2, and the nested if-thens using the Like keyword to pattern match different date formats in Figure 3.
Consequently, the apparent attempt at "intelligent" behavior that I observed in the date fields in Manred's application didn't really surprise me at all. I presumed at first that Manfred had probably programmed this behavior himself, but had probably made a small coding error somewhere. Manfred's response to my email, however, indicated otherwise. Whatever is going on, it is apparently happening within the "New" operator of the NotesDateTime object. New NotesDateTime() takes a string argument. The string needs to be a representation of a date or a date and time. As Manfred pointed out to me via email, the documentation doesn't actually specify what date and time string formats are acceptable. What I've managed to surmise is that Manfred's code is parsing the XML from an RSS feed into day, month, and year components, and it is creating a new NotesDateTime object using a string that concatenates these components together as follows day + "/" + month + "/" + year. This works on a system that has the normal Eurpoean date format configuration, but on a system with the US preference for month/day/year, it sometimes works and sometimes doesn't. It doesn't work when the day is less than or equal to 12. It does work when the day is greater than 12, but this is an accidental consequence of intelligence built into the NotesDateTime object, which recognizes an impossible date format and adjusts its behavior accordingly.
My immediate thought upon surmising this was that my bloggregator code would fail similarly, but in the opposite situation. Since I'm here in the USA, it would work properly on systems with the USA date preference, but fail on systems configured for DD/MM/YYYY -- except when the day is greater than 12. One of the reasons I haven't released my bloggregator, other than the fact that the Notes UI is even more embarassing than the web UI, is that I haven't had time to go over it to remove all the hard-coded shortcuts, and ignoring international date formats seemed logically to be one of the shortcuts that I would have to go in and fix. Most of us Americans suffer from forgetfulness in this area, and even though I spent the first portion of my career as a specialist in software localization for Wang Labs, I tend to be just as lazy as most other programmers when I'm just hacking something up quickly.
A quick test of my bloggregator app, however, revealed that my code actually works no matter what the system's date format preference is. The reason it works is that, for some reason that I really can't explain, I coded all my date-time handling routines using the following pattern: Figure 4. NotesDateTime initialization pattern
I programmed my code to create NotesDateTime objects using the YYYY/MM/DD format, with four digit years. Yes, I am an American, and when I'm required to use a short format date I do tend to use MM/DD/YYYY format, but my actual personal habit has long been that I write long format dates in the form "15 February 2004" whereas most Americans will write "February 15, 2004", and when I'm programming I tend to use YYYY/MM/DD. I tend to do this without thinking about it.
This technique works despite the fact that all my computers are configured with MM/DD/YYYY preference. Obviously, the code for the New operator has logic that works something like this: if the first part has four digits, assume that the format is YYYY/MM/DD, otherwise assume the format follows the preferences configured for the computer, unless the month value is greater than twelve in which case try the opposite format. So, you can consider this a tip: When initializing a NotesDateTime object using the New operator, you can use YYYY/MM/DD format for the date string argument, and your code will work no matter what the date format preference is on the machine where your code executes. I wouldn't be surprised, by the way, if using a 24 hour clock format for the time portion of a date-time string in the New NotesDateTime operator also works no matter what the system preferences are. It's likely that on a system configured for 12 hour AM/PM time, an "impossible" hour triggers code that reinterprets the time in 24 hour format. I haven't tested this, but it seems logical. I should conclude this article by observing that although the technique I use to initialize the NotesDateTime objects does work properly, the "correct" way to do it is really to check the NotesSession.International.IsDateMDY, IsDateDMY and IsDateYMD settings and format the string argument for New NotesDateTime() accordingly. Formatting the string as YYYY/MM/DD works for now, but this isn't documented and in theory it could stop working in a future version of Notes and Domino. I doubt it ever will stop working, but it would be better practice to explicitly check the preferences in the NotesInternational object.
Please see the update to this article!
|