Chronos is one of the many Smalltalk-related blogs syndicated on Planet Smalltalk
χρόνος

Discussion of the Essence# programming language, and related issues and technologies.

Blog Timezone: America/Los_Angeles [Winter: -0800 hhmm | Summer: -0700 hhmm] 
Your local time:  

2006-02-16

Chronos Version B1.55 Published; Date/Time Parsing Now Supported

Version B1.55 of Chronos has been published. It's available from the Chronos web site, or from the Cincom Public StORE Repository.

Unless you have installed Chronos before, you will also need to download and install the Chronos Time Zone Repository, as detailed in the Chronos Installation Instructions.

What's new and/or changed in Chronos version B1.55

Firstly, the major change is that date/time parsing has beem implemented! More on that below.

Secondly, the administrivia and minor changes:

  • Bundle/Package reorganization:

    • Moved Chronos-Timescales, Chronos-Calendars and Chronos-TimeZones from the bundle Chronos to the bundle Chronos-Kernel.

    • Created the Bundle Chronos-Platform-Abstraction under Chronos, and moved the packages Chronos-Environment and Chronos-System from Chronos-Kernel to Chronos-Platform-Abstraction. So Chronos-Kernel now contains Chronos-Foundation, Chronos-Timescales, Chronos-Calendars and Chronos-TimeZones (all the classes that constitute the underlying date/time "engine" that enables Chronos to do what it does--stuff that casual users of the Chronos codebase wouldn't normally need to be concerned with.)

    • Renamed the package Chronos-Calendars-Kernel to Chronos-Calendars-Foundation (for consistency with Chronos-Kernel and Chronos-Foundation.)

    • Renamed the package Chronos-Calendars-Arithmetical to Chronos-Calendars-Regular, and renamed the class ArithmeticalCalendar to RegularCalendar (to better reflect the intent and implementation.)

    • Renamed the package Chronos-Calendars-Astronomical to Chronos-Calendars-Irregular, and renamed the class AstronomicalCalendar to IrregularCalendar (to better reflect the intent and implementation.)

    • Created the package Chronos-Parsing under Chronos (more on that below.)

    • Created the bundle Chronos-Platform Extensions under Chronos, and moved the packages Chronos-ST80 (and VW) Compatibility and Chronos-VW-Extensions there from the bundle Chronos.

    • Created the bundle Chronos-Load under Chronos, and moved the packages Chronos-Class Initialization and Chronos-Installation there from Chronos.

  • Moved the following methods to the package "Chronos-Class Initialization" (as extension methods):

    • ChronosEnvironment class>>setPlatformClass

    • CalendarDuration class>>initialize

    • ChronosLocale class>>initialize

    • ScientificDuration class>>initialize

  • Moved all the methods in TimeOfDay's 'ST80/VW compatiblity' protocol to the "Chronos-ST80 (and VW) Compatibility" package.

  • Renamed #printCalendarDuration:on: to #printCivilDuration:on: (to better reflect the actual behavior.)

  • Changed the method ChronosEnvironment class>>preInstall so that it is a no-op if a) ChronosEnvironment has no subclasses, or b) there is a global defined whose name is ChronosInstallationFlag and whose value is false. The purpose is both to aid porting out of VW and also as a failsafe mechanism for installing the Chronos code in cases where the installation/initialization logic is broken (for whatever reason.)


Date/Time Parsing

The classes ChronosParser and ConfigurableChronosParser have been added, in the new package Chronos-Parsing. ChronosParser is an abstract class; ConfigurableChronosParser is a concrete subclass of ChronosParser. ChronosParser defines the API.

ConfigurableChronosParser is implemented to be very flexible and forgiving, as opposed to being very rigid and strict. Those who require rigid/strict parsing, or for whom ConfigurableChronosParser is not suitable (for whatever reason,) have the option of defining their own subclass of ChronosParser to suit their specific requirements (perhaps using SmaCC to generate the parsing logic.)

One unavoidable consequence of the forgiving, flexible behavior of ConfigurableChronosParser is that it cannot claim to be the fastest date/time parser available. However, it should be more than adequate for use in UIs, for casual use, or to quickly get up and running (First make it work, then make it fast.)

A ConfigurableChronosParser will try its best to interpret the date/time as a human would. It handles two-digit years, "am" and "pm," time zone names, time zone abbreviations, time zone offsets, multiple locales and multiple calendars. With a few exceptions, it doesn't care about separators--including no separators at all. If no valid interpretation of the data can be inferred with strong certainty, an exception is thrown.

The following configuration messages can be sent to a (mutable) instance of ConfigurableChronosParser:

  • setDefaultTimeZone: (used only if no time zone is explicitly specified from the parsed data)

  • setLocale: (each instance is specific to a particular locale)

  • setCalendar: (each instance is specific to a particular calendar)
  • setTwoDigitYearBackwardBias: (to set the number of years back from the current year for which the parser will assume that the 2 least significant digits of such years correspond to those of a given two-digit-year)

  • interpretMonthNumberAsNumericDesignator (for Hebrew dates using the religious month numbering convention)

  • interpretMonthNumberAsOrdinal (for Hebrew dates using the secular month numbering convention)

  • doNotExpectDayOfWeekName (default)

  • expectDayOfWeekName (so that RFC 2822 can be parsed)

  • expectDMY (makes the parser resolve any ambiguities in favor of a day-month-year ordering of the elements of a date)

  • expectMDY (makes the parser resolve any ambiguities in favor of a month-day-year ordering of the elements of a date)

  • expectYDM (makes the parser resolve any ambiguities in favor of a year-day-month ordering of the elements of a date)

  • expectYMD (makes the parser resolve any ambiguities in favor of a year-month-day ordering of the elements of a date)


Here are some executable examples of what a ConfigurableChronosParser can do:

ChronosParser default nextDateFrom: 'February 16, 2006'readStream
DateAndTime readFromString: '1976-07-04T17:00 EDT'
DateAndTime readFromString: '1976-07-04T12:00 am EDT'
DateAndTime readFromString: '1976-07-04T12:00 pm MST'
'1776-07-04' asDateAndTimeUsing: #iso8601
" ^-- Default time zone is Universal Time--as required by IS0 8601,
RFC 2822, WS-I Basic Profile 1.0, and various other standards."
'1776-07-04' asDateAndTimeUsing: #ansiStandard
" ^-- Default time zone is system local time--which is how most
time-zone-enabled applications operate."
'1776-07-04' asDateAndTimeUsing: #default
" ^-- Default time zone is nominal time--which is how most VisualWorks
and Squeak applications actually operate--even though most think otherwise."

'20040229' asDateAndTimeUsing: #iso8601
'2004-060' asDateAndTimeUsing: #iso8601
'2004060' asDateAndTimeUsing: #iso8601
'2004-W09-7' asDateAndTimeUsing: #iso8601
'2004W097' asDateAndTimeUsing: #iso8601
'7/4/76-07:00' asDateAndTimeUsing: #mdy
'7/4/1776+10:30' asDateAndTimeUsing: #mdy
'4 July 1776-04' asDateAndTimeUsing: #dmy
'04-JUL-1776Z' asDateAndTimeUsing: #dmy
'1776-07-04T09:22:12 America/New_York' asDateAndTimeUsing: #iso8601
'Thu, 04 Jul 1776 19:15:00 -0500' asDateAndTimeUsing: #rfc2822
'7/4/76 at 9:22:12 pm MDT' asDateAndTimeUsing: #mdy
'4 July ''76 9:22:12 pm MDT' asDateAndTimeUsing: #mdy
'9:22:12 am 7/4/76 MST' asDateAndTimeUsing: #(expectTimeThenDate expectMDY)
'Thursday, July 4, 1776 @ 7:15 pm +0530' asDateAndTimeUsing:
#(#expectDayOfWeekName #expectMDY)
'4 juillet 1776 7h15' asDateAndTimeUsing:
#(expectDMY setLocale: #fr_FR setDefaultTimeZone: 'Europe/Paris')
('5536 Tammuz 17, 07:15' asDateAndTimeUsing:
#(setCalendar: #Hebrew setDefaultTimeZone: 'Asia/Jerusalem')) localePrintString
('5765 Adar Rishon 14, 18:00' asDateAndTimeUsing:
#(setCalendar: #Hebrew setDefaultTimeZone: 'Asia/Jerusalem')) localePrintString
('5765 Adar Sheni 14, 18:00' asDateAndTimeUsing:
#(setCalendar: #Hebrew setDefaultTimeZone: 'Asia/Jerusalem')) localePrintString
('5765 Adar 14, 18:00' asDateAndTimeUsing:
#(setCalendar: #Hebrew setDefaultTimeZone: 'Asia/Jerusalem')) localePrintString
('5765-13-14T18:00' asDateAndTimeUsing:
#(setCalendar: #Hebrew
#interpretMonthNumberAsNumericDesignator
setDefaultTimeZone: 'Asia/Jerusalem')) localePrintString
('5765-07-14T18:00' asDateAndTimeUsing:
#(setCalendar: #Hebrew setDefaultTimeZone: 'Asia/Jerusalem')) localePrintString



No comments: