Hi Jeff,
You're asking the right questions. Jeff: "So how do these various packages handle indexing data by time?" Well, I won't presume to speak for the other packages, but here's the situation in Chronos: Firstly, Chronos dates, times, durations and time periods are all immutable objects, and fully support comparison operations--including answering a hash code. So they can be safely added to Sets, or used as keys in a Dictionary. Date equality works correctly between different calendars, and Timepoint equality works correctly between different time zones and/or different calendars. It's easy to convert a Chronos YearMonthDay or Timepoint into a count of days, or to convert a count of days into a YearMonthDay or Timepoint: YearMonthDay daysSinceEpoch: YearMonthDay today daysSinceEpoch. So the problem of indexing by a date resolves to the problem of indexing by an integer. It's also possible to convert a date into a count of months or years since the calendar epoch, and to convert a count of months or years since a calendar epoch into a date. Both YearMonthDay and Timepoint (which inherits from YearMonthDay) support date and time arithmetic operations: #addingYears: #subtractingYears: #addingMonths: #subtractingMonths: #addingDays: #subtractingDays: #addingYears:months:days: #subtractingYears:months:days: #addingHours: #subtractingHours: #addingMinutes: #subtractingMinutes: #addingSeconds: #subtractingSeconds: #addingSeconds:nanonseconds: #subtractingSeconds:nanoseconds: Or, durational objects can be used instead: Timepoint now + (ScientificDuration microseconds: 75) YearMonthDayToday - (CalendarDuration months: 3) Timepoint now + (CivilDuration years: 5 months: -3 days: 10 hours: -1 minutes: 30 seconds: -11) A method to compute the Timepoint N periods after a base timepoint might look like this: SomeClass>>at: index ^baseTimepoint + (duration * index) The "duration" instance variable might have the value "ScientificDuration hours: 3.5", or it might have the value "CalendarDuration months: 3." The "baseTimepoint" instance variable could hold either a Timepoint, a YearMonthDay--or even a Timeperiod (interval of time.) For example, "Timeperiod currentMonth + (CalendarDuration days: 5)" (if executed during the month of April, 2006) evaluates to "2006-04-06/P1M" (the one-month interval starting 6 April 2006.) Does that answer your question about indexing? Jeff: "What should happen if you start at January 28'th and advance by a month and then go back by a month? Jan28 --> Feb28 --> (Jan 28 or Jan 31?) Can we agree on some conventions? " (YearMonthDay year: 2006 month: 1 day: 28) + 1 months => 2006-02-28 (YearMonthDay year: 2006 month: 1 day: 31) + 1 months => 2006-02-28 (YearMonthDay year: 2006 month: 1 day: 28) + 1 months - 1 months => 2006-01-28 (YearMonthDay year: 2006 month: 1 day: 31) + 1 months - 1 months => 2006-01-28 (Note: "1 months" works in VW and Dolphin, but not in Squeak, where "(CalendarDuration months: 1)" must be used instead--or you could add a #months and #years method to Integer yourself.) Chronos implements date arithmetic to satisfy the typical business use case. If you want "scientific" behavior, use a ScientificDuration. If you want a "month" to always be 30 days, use a "monthDuration" value defined as "CalendarDuration days: 30." But these questions just scratch the surface. There's a lot more than can and should be asked. --Alan -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of Jeffrey J. Hallman Sent: Wednesday, April 19, 2006 9:10 AM To: [hidden email] Subject: Re: The Timing of Time I'm enjoying the discussion about calendars and times, but I'd like to direct some attention to the idea of a TimeIndex. I came at this from another direction, thinking of a TimeSeries as data indexed by time, which leads to the idea of a TimeIndex. In my current implementation, a TimeIndex has two instance variables: a freq symbol (such as #weeklyMonday, #monthly, #hourly, etc.) and an integer period, which represents the number of periods elapsed since the base period for that freq. TimeIndex understands '+' and '-', so if 'z' is the weeklyMonday time index for April 17 2006, then (z - 4) asYmd yields 20060320, and so on. My TimeSeries class is a subclass of Matrix with an additional instance variable called 'start' which is a TimeIndex, and has accessors like TimeSeries>>atTimeIndex: TimeSeries>>atTimeIndex:put: TimeSeries>>atTimeIndex:column: TimeSeries>>atTimeIndex:column:put: I've found this scheme works pretty well, and will probably generalize it a bit more by making TimeIndex an abstract class with subclasses for different kinds of sequences. I think a package that wants to handle date and time issues should have something like a TimeIndex in it that allows sequences of various frequencies to be defined. At the same time, the implementation should be simple enough to be easily understood, and indexing into a TimeSeries should be very fast. If indexing isn't fast, we'll end up with ugly code in every TimeSeries method that that converts TimeIndex'es to row numbers and back. Trust me, you really don't want that. So how do these various packages handle indexing data by time? A second issue is how to handle date arithmetic. Some durations are based on linear time (e.g., weeks, seconds, hours, etc.) and others are based on the calendar (months, years, etc.). The distinction between these two leads to questions like: What should happen if you start at January 28'th and advance by a month and then go back by a month? Jan28 --> Feb28 --> (Jan 28 or Jan 31?) Can we agree on some conventions? Jeff Hallman |
In reply to this post by Alan L. Lovejoy
Hi Jeff, I will answer your questions over Alan's responses to make it
easy to compare both solutions. (I hope Alan you don't mind...) Alan Lovejoy wrote: >Hi Jeff, > >You're asking the right questions. > > I agree, good questions. >Jeff: "So how do these various packages handle indexing data by time?" > >Well, I won't presume to speak for the other packages, but here's the >situation in Chronos: > >Firstly, Chronos dates, times, durations and time periods are all immutable >objects, > Chalten too. I believe that is a very important characteristic. >and fully support comparison operations--including answering a hash >code. So they can be safely added to Sets, or used as keys in a Dictionary. > > The same for Chalten. >Date equality works correctly between different calendars, and Timepoint >equality works correctly between different time zones and/or different >calendars. > > Chalten does not have support for time zone or different calendars. It just support the Gregorian Calendar; we are planning to add support to other calendars and time zone but in different packages... it is not common to use other calendars than the Gregorian and we don't want to make the most commonly used abstraction difficult to understand because of that support. >It's easy to convert a Chronos YearMonthDay or Timepoint into a count of >days, or to convert a count of days into a YearMonthDay or Timepoint: > > YearMonthDay daysSinceEpoch: YearMonthDay today daysSinceEpoch. > > > Same for Chalten. For example: ( January first, 2006) numberOfDaysFromBaseDate --> Returns "38351 days". But as you can see it returns a Measure. They also are immutable, comparable, can be put in Sets, Dictionaries, etc. I believe that the fact that we return a Measure and not just a numbers makes "explicit" the meaning of the returned object. It is not just 38351 but "38351 days" What's the advantage? Well, there are many, for example: 1) If you see the message #numberOfDaysFromBaseDate we, as programmer, know that it will return a number or a measure in this case, but what happens if you just see the object "38351"? You will not be able to know if they are days, seconds, years or what ever meaning it has. If instead you see "38351 days", now you know you are dealing with days. But not only we as programmers will notice that, the whole idea of Aconcagua is that the computer will handle any arithmetic mistake you can have mixing measure of different units. Using measures, you will never mix days and years. For example: a) If the model returns numbers instead of measures, you could write: ( January first, 2006) numberOfDaysFromBaseDate + ( January first, 2006) year yearsFromBaseDate --> That is 38351 + 106 = 40357 There is no way to know from the result that you added days and years. b) If the model returns measures: ( January first, 2006) numberOfDaysFromBaseDate + ( January first, 2006) year yearsFromBaseDate --> It will return "38351 days + 106 years" As you can see, it does not mix up days and years because they are not interchangeable. A year can be 365 or 366 days in the Gregorian calendar. 2) Because we use measures, if you want to know the number of hours from the base date, you can do: ( January first, 2006) numberOfDaysFromBaseDate convertTo: TimeUnits hour --> Returns " 920424 hours". Or seconds: ( January first, 2006) numberOfDaysFromBaseDate convertTo: TimeUnits hour --> Returns " 3313526400 seconds" There is no need for a class Duration or special messages to get the number of seconds from base date, etc. >So the problem of indexing by a date resolves to the problem of indexing by >an integer. It's also possible to convert a date into a count of months or >years since the calendar epoch, and to convert a count of months or years >since a calendar epoch into a date. > >Both YearMonthDay and Timepoint (which inherits from YearMonthDay) support >date and time arithmetic operations: > > #addingYears: > #subtractingYears: > #addingMonths: > #subtractingMonths: > #addingDays: > #subtractingDays: > #addingYears:months:days: > #subtractingYears:months:days: > #addingHours: > #subtractingHours: > #addingMinutes: > #subtractingMinutes: > #addingSeconds: > #subtractingSeconds: > #addingSeconds:nanonseconds: > #subtractingSeconds:nanoseconds: > > > PointInTime objects using measures. For the same porpouse that Alan shows in Chronos, we have only two messages: #next: and #previous: (we don't use add and subtract for semantinc issues, but that another problem it does not make sense to talk about now). For example: GregorianDate today next: 10 * TimeUnits day -> Will return " April 30, 2006" if today is " April 20, 2006" GregorianDate today previous: 10 * TimeUnits day -> Will return " April 10, 2006" if today is " April 20, 2006" GregorianDate today next: -10 * TimeUnits day -> Will return "April 10, 2006" if today is " April 20, 2006" GregorianDate today next: 48 * TimeUnits hour -> Will return " April 22, 2006" if today is " April 20, 2006" (See that we move the point in time by hours, not days... or) GregorianDate today next: 86400 * TimeUnits second -> Will return "April 21, 2006" if today is " April 20, 2006" We can do the same with years, months, days, times, etc. For example: GregorianYear current next: 10 * TimeUnits year -->Will return Year 2016 GregorianYear current previous: 24 * TimeUnits month -->Will return Year 2004 GregorianDay today next: 3 * TimeUnits day --> Will return "Sunday" if today is "Thursday" GregorianMonth current previous: 2 * TimeUnits month --> Will return " February" if the current month is " April" etc. >Or, durational objects can be used instead: > > Timepoint now + (ScientificDuration microseconds: 75) > YearMonthDayToday - (CalendarDuration months: 3) > Timepoint now + (CivilDuration years: 5 months: -3 days: 10 hours: >-1 minutes: 30 seconds: -11) > >A method to compute the Timepoint N periods after a base timepoint might >look like this: > >SomeClass>>at: index > ^baseTimepoint + (duration * index) > > SomeClass>>at: index ^basePointInTime numberOfDaysFromBaseDate + (duration * index) We do not implemented the #+, #-, etc. messages in PointInTime objects because those message do not keep the same semantic as the arithmetic message. For example. if you do "1 + 2" you get "3". That is, you are adding number, you get a number. But for dates is not the same... For example "GregorianDate today + 10 days" would not return a measure of days but a new date, so it does not match the semantics of the arithmetic +. Of course this is a decision we made and not everybody could like or agree with that... but we believe it makes more clear the model's language. >The "duration" instance variable might have the value "ScientificDuration >hours: 3.5", or it might have the value "CalendarDuration months: 3." The >"baseTimepoint" instance variable could hold either a Timepoint, a >YearMonthDay--or even a Timeperiod (interval of time.) For example, >"Timeperiod currentMonth + (CalendarDuration days: 5)" (if executed during >the month of April, 2006) evaluates to "2006-04-06/P1M" (the one-month >interval starting 6 April 2006.) > > Chalten also have an abstraction for this, it named Timespan. It represents segment of the time line. For example: GregorianTimespan from: GregorianDate today duration: 20 * TimeUnits day --> Returns "20 days from April 20, 2006" GregorianTimespan from: GregorianYear current duration: 10 * TimeUnits year --> Returns " 10 years from Year 2006" GregorianTimespan from: GregorianMonth current duration: 2 * TimeUnits month --> Returns " 2 months from April" GregorianTimespan from: GregorianDay today duration: 2 * TimeUnits day --> Returns " 2 days from Thursday" GregorianTimespan from: GregorianDayOfMonth today duration: 25 * TimeUnits day --> Returns " 25 days from April 20" GregorianTimespan from: GregorianMonthOfYear current duration: 12 * TimeUnits month --> Returns " 12 months from April of Year 2006" GregorianTimespan from: TimeOfDay now duration: 12 * TimeUnits hour --> Returns " 12 hours from 18:53:33" (I wrote the mail at 18:53:33) GregorianTimespan from: GregorianDateTime now duration: 12 * TimeUnits hour --> Returns " 12 hours from April 20, 2006 18:54:14" Look how easy is to use the same abstraction, GregorianTimespan, to any type of PointInTime. I think we could achieve that because we are using measures and all point in times are polymorphic. (By the way, we use GregorianTimespan because Chronology already defines Timespan) We also have time intervals, that are instances of the class "ArihtmeticObjectInterval" (I think not a good name). We could not use the Interval class for many reason. Anyway, ArihtmeticObjectInterval is an interval of any type of Magnitude, for example Measures, Numbers and of course PointInTimes. For example: GregorianDate today to: December first, 2006 --> Returns an interval from today to December fist 2006 by 1 day GregorianDate today to: December first, 2006 by: 10 * TimeUnits day --> Returns an interval from today to December fist 2006 with steps of 10 days GregorianMonth current to: December by: 2 * TimeUnits month --> Now, and interval of months.... the same for other time points... Because these objects are intervals, they are polymorphic with Collection: (GregorianDate today to: December first, 2006) select: [ :aDate | aDate isMonday ] --> Returns all Mondays from today to December first (GregorianYear current to: (GregorianYear number: 3000) ) select: [ :aYear | aYear isLeap ] --> Returns all leap year up to year 3000 (January first, 2006 to: GregorianDate today) collect: [ :aDate | aDate distanceTo: GregorianDate today ] --> Returns an array with measures from 109 days to 0 days >Does that answer your question about indexing? > >Jeff: "What should happen if you start at January 28'th and advance by a >month and then go back by a month? >Jan28 --> Feb28 --> (Jan 28 or Jan 31?) Can we agree on some >conventions? " > >(YearMonthDay year: 2006 month: 1 day: 28) + 1 months => 2006-02-28 >(YearMonthDay year: 2006 month: 1 day: 31) + 1 months => 2006-02-28 >(YearMonthDay year: 2006 month: 1 day: 28) + 1 months - 1 months => >2006-01-28 >(YearMonthDay year: 2006 month: 1 day: 31) + 1 months - 1 months => >2006-01-28 > >(Note: "1 months" works in VW and Dolphin, but not in Squeak, where >"(CalendarDuration months: 1)" must be used instead--or you could add a >#months and #years method to Integer yourself.) > > moths, decades, etc. and another for days, hours, seconds, weeks, etc. Notice that time units are not the same as time points (there is an object for years, ie. GregorianYear, and there is a unit to measure years, ie. TimeUnit year) That means that measures expressed in days can not be converted to months or years and vicersa. (Is 30 days a month? or 31 days? etc.) Because of the irregularity of the Gregorian calendar we decided not to allow movements of point in times with measure of units of less granularity that the point in time granularity. For example: GregorianDate today next: 1 * TimeUnits second --> Is not allowed But we added for convenience that possibility of doing: (January thirtyfirst, 2006 next: 1 * TimeUnits month) --> Returns February 28, 2006 (January thirtyfirst, 2006 next: 1 * TimeUnits month) previous: 1 * TimeUnits month --> Returns January 28, 2006 I don't like this behavior but we added because we people are used to it. Well, the mail became longer that I expected. I hope it helps you to understand Chalten and also compare it with other solutions. Bye, Hernan >Chronos implements date arithmetic to satisfy the typical business use case. >If you want "scientific" behavior, use a ScientificDuration. If you want a >"month" to always be 30 days, use a "monthDuration" value defined as >"CalendarDuration days: 30." > >But these questions just scratch the surface. There's a lot more than can >and should be asked. > >--Alan > >-----Original Message----- >From: [hidden email] >[mailto:[hidden email]] On Behalf Of Jeffrey >J. Hallman >Sent: Wednesday, April 19, 2006 9:10 AM >To: [hidden email] >Subject: Re: The Timing of Time > >I'm enjoying the discussion about calendars and times, but I'd like to >direct some attention to the idea of a TimeIndex. I came at this from >another direction, thinking of a TimeSeries as data indexed by time, which >leads to the idea of a TimeIndex. > >In my current implementation, a TimeIndex has two instance variables: a freq >symbol (such as #weeklyMonday, #monthly, #hourly, etc.) and an integer >period, which represents the number of periods elapsed since the base period >for that freq. TimeIndex understands '+' and '-', so if 'z' >is the weeklyMonday time index for April 17 2006, then (z - 4) asYmd yields >20060320, and so on. > >My TimeSeries class is a subclass of Matrix with an additional instance >variable called 'start' which is a TimeIndex, and has accessors like > >TimeSeries>>atTimeIndex: >TimeSeries>>atTimeIndex:put: >TimeSeries>>atTimeIndex:column: >TimeSeries>>atTimeIndex:column:put: > >I've found this scheme works pretty well, and will probably generalize it a >bit more by making TimeIndex an abstract class with subclasses for different >kinds of sequences. > >I think a package that wants to handle date and time issues should have >something like a TimeIndex in it that allows sequences of various >frequencies to be defined. At the same time, the implementation should be >simple enough to be easily understood, and indexing into a TimeSeries should >be very fast. If indexing isn't fast, we'll end up with ugly code in every >TimeSeries method that that converts TimeIndex'es to row numbers and back. >Trust me, you really don't want that. > >So how do these various packages handle indexing data by time? > >A second issue is how to handle date arithmetic. Some durations are based >on linear time (e.g., weeks, seconds, hours, etc.) and others are based on >the calendar (months, years, etc.). The distinction between these two leads >to questions like: What should happen if you start at January 28'th and >advance by a month and then go back by a month? >Jan28 --> Feb28 --> (Jan 28 or Jan 31?) Can we agree on some >conventions? > >Jeff Hallman > > > > > > > -- ______________________________ Lic. Hernán A. Wilkinson Gerente de Desarrollo y Tecnología Mercap S.R.L. Tacuari 202 - 7mo Piso - Tel: 54-11-4878-1118 Buenos Aires - Argentina http://www.mercapsoftware.com --------------------------------------------------------------------- Este mensaje es confidencial. Puede contener informacion amparada por el secreto profesional. Si usted ha recibido este e-mail por error, por favor comuniquenoslo inmediatamente via e-mail y tenga la amabilidad de eliminarlo de su sistema; no debera copiar el mensaje ni divulgar su contenido a ninguna persona. Muchas gracias. This message is confidential. It may also contain information that is privileged or otherwise legally exempt from disclosure. If you have received it by mistake please let us know by e-mail immediately and delete it from your system; you should also not copy the message nor disclose its contents to anyone. Thanks. --------------------------------------------------------------------- |
Jeff, Hernan:
I also will put my comments in-line, following Hernan's, preceded by ##: -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of Hernan Wilkinson Sent: Thursday, April 20, 2006 3:20 PM To: The general-purpose Squeak developers list Subject: Re: The Timing of Time Hi Jeff, I will answer your questions over Alan's responses to make it easy to compare both solutions. (I hope Alan you don't mind...) Alan Lovejoy wrote: [snip] >Date equality works correctly between different calendars, and >Timepoint equality works correctly between different time zones and/or >different calendars. > > Chalten does not have support for time zone or different calendars. It just support the Gregorian Calendar; we are planning to add support to other calendars and time zone but in different packages... it is not common to use other calendars than the Gregorian and we don't want to make the most commonly used abstraction difficult to understand because of that support. ## Non-gregorian calendars in Chronos are completely invisible to programmers who don't want or need them. In fact, all the non-Gregorian calendar classes could simply be removed, and the only Chronos code that would break would be example code in comments (if you can call such code-in-the-comments "Chronos code.") Where in any of the Chronos examples you've seen in this discussion can you spot the fact that Chronos even supports calendars other than the Gregorian? I mention it in passing, but there's no evidence of it in any of the code examples. ## Why not just use Chronos for time zones and for non-Gregorian calendars? I've already done the hard work--and you'll find the job is a lot harder than you currently imagine. The opportunity for synergy between Chalten and Chronos in this area seems very strong to me. >It's easy to convert a Chronos YearMonthDay or Timepoint into a count >of days, or to convert a count of days into a YearMonthDay or Timepoint: > > YearMonthDay daysSinceEpoch: YearMonthDay today daysSinceEpoch. > > > Same for Chalten. For example: ( January first, 2006) numberOfDaysFromBaseDate --> Returns "38351 days". But as you can see it returns a Measure. They also are immutable, comparable, can be put in Sets, Dictionaries, etc. I believe that the fact that we return a Measure and not just a numbers makes "explicit" the meaning of the returned object. It is not just 38351 but "38351 days" ## Chronos: ## ## 1) YearMonthDay today - (YearMonthDay year: 1901 day: 1) => 38460:00:00:00 (38460 days as a duration object) ## 2) YearMonthDay today civilDurationSince: (YearMonthDay year: 1901 day: 1)=> P105Y3M19D (also a duration object, representing 105 years, 3 months, 19 days) ## Chronos durational objects are immutable, comparable, can be used in Sets, Dictionaries, etc. What's the advantage? Well, there are many, for example: 1) If you see the message #numberOfDaysFromBaseDate we, as programmer, know that it will return a number or a measure in this case, but what happens if you just see the object "38351"? You will not be able to know if they are days, seconds, years or what ever meaning it has. If instead you see "38351 days", now you know you are dealing with days. But not only we as programmers will notice that, the whole idea of Aconcagua is that the computer will handle any arithmetic mistake you can have mixing measure of different units. Using measures, you will never mix days and years. For example: a) If the model returns numbers instead of measures, you could write: ( January first, 2006) numberOfDaysFromBaseDate + ( January first, 2006) year yearsFromBaseDate --> That is 38351 + 106 = 40357 There is no way to know from the result that you added days and years. b) If the model returns measures: ( January first, 2006) numberOfDaysFromBaseDate + ( January first, 2006) year yearsFromBaseDate --> It will return "38351 days + 106 years" As you can see, it does not mix up days and years because they are not interchangeable. A year can be 365 or 366 days in the Gregorian calendar. 2) Because we use measures, if you want to know the number of hours from the base date, you can do: ( January first, 2006) numberOfDaysFromBaseDate convertTo: TimeUnits hour --> Returns " 920424 hours". Or seconds: ( January first, 2006) numberOfDaysFromBaseDate convertTo: TimeUnits hour --> Returns " 3313526400 seconds" There is no need for a class Duration or special messages to get the number of seconds from base date, etc. ## I generally agree with Hernan's explanation of the motivation for using durational objects. But there are times when integer numbers are better. For one thing, the messages to get the count of days must exist in order to create the durational values. And whith a Chrohos durational object, there is no need to convert it from days to hours--the same object encompasses all units from nanoseconds to weeks. ## By the way, if you are intrigued by the Aconcagua domain-specific language for measures, you should also check out Frink: http://futureboy.homeip.net/frinkdocs/ >So the problem of indexing by a date resolves to the problem of >indexing by an integer. It's also possible to convert a date into a >count of months or years since the calendar epoch, and to convert a >count of months or years since a calendar epoch into a date. > >Both YearMonthDay and Timepoint (which inherits from YearMonthDay) >support date and time arithmetic operations: > > #addingYears: > #subtractingYears: > #addingMonths: > #subtractingMonths: > #addingDays: > #subtractingDays: > #addingYears:months:days: > #subtractingYears:months:days: > #addingHours: > #subtractingHours: > #addingMinutes: > #subtractingMinutes: > #addingSeconds: > #subtractingSeconds: > #addingSeconds:nanonseconds: > #subtractingSeconds:nanoseconds: > > > PointInTime objects using measures. For the same porpouse that Alan shows in Chronos, we have only two messages: #next: and #previous: (we don't use add and subtract for semantinc issues, but that another problem it does not make sense to talk about now). For example: GregorianDate today next: 10 * TimeUnits day -> Will return " April 30, 2006" if today is " April 20, 2006" ## YearMonthDay today + (CalendarDayDuration * 10) GregorianDate today previous: 10 * TimeUnits day -> Will return " April 10, 2006" if today is " April 20, 2006" ## YearMonthDay today - (CalendarDayDuration * 10) GregorianDate today next: -10 * TimeUnits day -> Will return "April 10, 2006" if today is " April 20, 2006" ## YearMonthDay today + (CalendarDayDuration * -10) GregorianDate today next: 48 * TimeUnits hour -> Will return " April 22, 2006" if today is " April 20, 2006" (See that we move the point in time by hours, not days... or) ## YearMonthDay today + (HourDuration * 48) GregorianDate today next: 86400 * TimeUnits second -> Will return "April 21, 2006" if today is " April 20, 2006" ## YearMonthDay today + (SecondDuration * 86400) We can do the same with years, months, days, times, etc. For example: GregorianYear current next: 10 * TimeUnits year -->Will return Year 2016 ## Timeperiod currentYear + (YearDuration * 10) GregorianYear current previous: 24 * TimeUnits month -->Will return Year 2004 ## Timeperiod currentYear - (MonthDuration * 24) GregorianDay today next: 3 * TimeUnits day --> Will return "Sunday" if today is "Thursday" ## YearMonthDay today + (CalendarDayDuration * 3) ## Timepoint today + (CalendarDayDuration * 3) ## Timeperiod today + (CalendarDayDuration * 3) GregorianMonth current previous: 2 * TimeUnits month --> Will return " February" if the current month is " April" etc. ## Timeperiod currentMonth - (MonthDuration * 2) >Or, durational objects can be used instead: > > Timepoint now + (ScientificDuration microseconds: 75) > YearMonthDayToday - (CalendarDuration months: 3) > Timepoint now + (CivilDuration years: 5 months: -3 days: 10 hours: >-1 minutes: 30 seconds: -11) > >A method to compute the Timepoint N periods after a base timepoint >might look like this: > >SomeClass>>at: index > ^baseTimepoint + (duration * index) > > SomeClass>>at: index ^basePointInTime numberOfDaysFromBaseDate + (duration * index) We do not implemented the #+, #-, etc. messages in PointInTime objects because those message do not keep the same semantic as the arithmetic message. For example. if you do "1 + 2" you get "3". That is, you are adding number, you get a number. But for dates is not the same... For example "GregorianDate today + 10 days" would not return a measure of days but a new date, so it does not match the semantics of the arithmetic +. Of course this is a decision we made and not everybody could like or agree with that... but we believe it makes more clear the model's language. ## Chronos implements the #+ and #- messages for two reasons: ## ## 1) It's required by the ANSI Smalltalk Standard. ## 2) In mathematics, the semantics of + and - depend upon the algebra one formally defines. There is no general requirement that both operands of the + or - opertor be of the same type. "Mixed mode" arithmetic expressions are common, useful and formally well defined. >The "duration" instance variable might have the value >"ScientificDuration >hours: 3.5", or it might have the value "CalendarDuration months: 3." >The "baseTimepoint" instance variable could hold either a Timepoint, a >YearMonthDay--or even a Timeperiod (interval of time.) For example, >"Timeperiod currentMonth + (CalendarDuration days: 5)" (if executed >during the month of April, 2006) evaluates to "2006-04-06/P1M" (the >one-month interval starting 6 April 2006.) > > segment of the time line. For example: GregorianTimespan from: GregorianDate today duration: 20 * TimeUnits day --> Returns "20 days from April 20, 2006" ## Timeperiod from: YearMonthDay today duration: CalendarDayDuration * 20 => 2006-04-20/P20D (ISO 8601 notation for "the 20-day period starting with 2006-04-20") GregorianTimespan from: GregorianYear current duration: 10 * TimeUnits year --> Returns " 10 years from Year 2006" ## Chronos doesn't have a "Year" class -- and that's one of the obvious opportunities for synergy between Chalten and Chronos ## It's also serendipitous that both Timeperiod and GregorianTimespan use #from:duration: as instance creation methods--must be the right method name. GregorianTimespan from: GregorianMonth current duration: 2 * TimeUnits month --> Returns " 2 months from April" ## Yet another opportunity for synergy... GregorianTimespan from: GregorianDay today duration: 2 * TimeUnits day --> Returns " 2 days from Thursday" GregorianTimespan from: GregorianDayOfMonth today duration: 25 * TimeUnits day --> Returns " 25 days from April 20" ## Timeperiod from: DayOfMonth today duration: CalendarDayDuration * 25 ## Timeperiod from: DayOfYear today duration: CalendarDayDuration * 25 ## Timeperiod from: WeekOfMonthDayOfWeek today duration: CalendarDayDuration * 25 ## Timeperiod from: GregorianEaster canonical duration: CalendarDayDuration * 25 GregorianTimespan from: GregorianMonthOfYear current duration: 12 * TimeUnits month --> Returns " 12 months from April of Year 2006" ## Yet another opportunity for synergy... GregorianTimespan from: TimeOfDay now duration: 12 * TimeUnits hour --> Returns " 12 hours from 18:53:33" (I wrote the mail at 18:53:33) ## Uh, oh: Both Chronos and Chalten use the class name TimeOfDay. This won't matter in VW, but Squeak really needs namespaces or class boxes... ## Timeperiod from: TimeOfDay now duration: 12 * HourDuration GregorianTimespan from: GregorianDateTime now duration: 12 * TimeUnits hour --> Returns " 12 hours from April 20, 2006 18:54:14" Look how easy is to use the same abstraction, GregorianTimespan, to any type of PointInTime. I think we could achieve that because we are using measures and all point in times are polymorphic. (By the way, we use GregorianTimespan because Chronology already defines Timespan) We also have time intervals, that are instances of the class "ArihtmeticObjectInterval" (I think not a good name). We could not use the Interval class for many reason. Anyway, ArihtmeticObjectInterval is an interval of any type of Magnitude, for example Measures, Numbers and of course PointInTimes. For example: GregorianDate today to: December first, 2006 --> Returns an interval from today to December fist 2006 by 1 day GregorianDate today to: December first, 2006 by: 10 * TimeUnits day --> Returns an interval from today to December fist 2006 with steps of 10 days ## I considered implementing a TemporalInterval where the step value would be specified. In the end, I decided to simply make it easy to enumerate between the endpoints of a Timeperiod using any ScientificDuration or CivilDuration as the step value, and let applications manage the step value as they care to. Implementing a TemporalInterval on top of Timeperiod would be easy to do. Perhaps this is another opportunity for synergy between Chronos and Chalten. GregorianMonth current to: December by: 2 * TimeUnits month --> Now, and interval of months.... the same for other time points... ## Yet another opportunity for synergy... Because these objects are intervals, they are polymorphic with Collection: (GregorianDate today to: December first, 2006) select: [ :aDate | aDate isMonday ] --> Returns all Mondays from today to December first (GregorianYear current to: (GregorianYear number: 3000) ) select: [ :aYear | aYear isLeap ] --> Returns all leap year up to year 3000 (January first, 2006 to: GregorianDate today) collect: [ :aDate | aDate distanceTo: GregorianDate today ] --> Returns an array with measures from 109 days to 0 days >Does that answer your question about indexing? > >Jeff: "What should happen if you start at January 28'th and advance by a >month and then go back by a month? >Jan28 --> Feb28 --> (Jan 28 or Jan 31?) Can we agree on some >conventions? " > >(YearMonthDay year: 2006 month: 1 day: 28) + 1 months => 2006-02-28 >(YearMonthDay year: 2006 month: 1 day: 31) + 1 months => 2006-02-28 >(YearMonthDay year: 2006 month: 1 day: 28) + 1 months - 1 months => >2006-01-28 >(YearMonthDay year: 2006 month: 1 day: 31) + 1 months - 1 months => >2006-01-28 > >(Note: "1 months" works in VW and Dolphin, but not in Squeak, where >"(CalendarDuration months: 1)" must be used instead--or you could add a >#months and #years method to Integer yourself.) > > moths, decades, etc. and another for days, hours, seconds, weeks, etc. Notice that time units are not the same as time points (there is an object for years, ie. GregorianYear, and there is a unit to measure years, ie. TimeUnit year) That means that measures expressed in days can not be converted to months or years and vicersa. (Is 30 days a month? or 31 days? etc.) Because of the irregularity of the Gregorian calendar we decided not to allow movements of point in times with measure of units of less granularity that the point in time granularity. For example: GregorianDate today next: 1 * TimeUnits second --> Is not allowed But we added for convenience that possibility of doing: (January thirtyfirst, 2006 next: 1 * TimeUnits month) --> Returns February 28, 2006 (January thirtyfirst, 2006 next: 1 * TimeUnits month) previous: 1 * TimeUnits month --> Returns January 28, 2006 I don't like this behavior but we added because we people are used to it. ## YearMonthDay today addingSeconds: 1000 => 2006-04-20T00:16:40 ## This case is no different than "3 / 4" or "100 factorial." Autoconvervion/autopromotion is the Smalltalk way. Well, the mail became longer that I expected. I hope it helps you to understand Chalten and also compare it with other solutions. Bye, Hernan >Chronos implements date arithmetic to satisfy the typical business use case. >If you want "scientific" behavior, use a ScientificDuration. If you want a >"month" to always be 30 days, use a "monthDuration" value defined as >"CalendarDuration days: 30." > >But these questions just scratch the surface. There's a lot more than can >and should be asked. > >--Alan > >-----Original Message----- >From: [hidden email] >[mailto:[hidden email]] On Behalf Of Jeffrey >J. Hallman >Sent: Wednesday, April 19, 2006 9:10 AM >To: [hidden email] >Subject: Re: The Timing of Time > >I'm enjoying the discussion about calendars and times, but I'd like to >direct some attention to the idea of a TimeIndex. I came at this from >another direction, thinking of a TimeSeries as data indexed by time, which >leads to the idea of a TimeIndex. > >In my current implementation, a TimeIndex has two instance variables: a >symbol (such as #weeklyMonday, #monthly, #hourly, etc.) and an integer >period, which represents the number of periods elapsed since the base period >for that freq. TimeIndex understands '+' and '-', so if 'z' >is the weeklyMonday time index for April 17 2006, then (z - 4) asYmd yields >20060320, and so on. > >My TimeSeries class is a subclass of Matrix with an additional instance >variable called 'start' which is a TimeIndex, and has accessors like > >TimeSeries>>atTimeIndex: >TimeSeries>>atTimeIndex:put: >TimeSeries>>atTimeIndex:column: >TimeSeries>>atTimeIndex:column:put: > >I've found this scheme works pretty well, and will probably generalize it a >bit more by making TimeIndex an abstract class with subclasses for >kinds of sequences. > >I think a package that wants to handle date and time issues should have >something like a TimeIndex in it that allows sequences of various >frequencies to be defined. At the same time, the implementation should be >simple enough to be easily understood, and indexing into a TimeSeries should >be very fast. If indexing isn't fast, we'll end up with ugly code in every >TimeSeries method that that converts TimeIndex'es to row numbers and back. >Trust me, you really don't want that. > >So how do these various packages handle indexing data by time? > >A second issue is how to handle date arithmetic. Some durations are based >on linear time (e.g., weeks, seconds, hours, etc.) and others are based on >the calendar (months, years, etc.). The distinction between these two leads >to questions like: What should happen if you start at January 28'th and >advance by a month and then go back by a month? >Jan28 --> Feb28 --> (Jan 28 or Jan 31?) Can we agree on some >conventions? > >Jeff Hallman > > > > > > > -- ______________________________ Lic. Hernán A. Wilkinson Gerente de Desarrollo y Tecnología Mercap S.R.L. Tacuari 202 - 7mo Piso - Tel: 54-11-4878-1118 Buenos Aires - Argentina http://www.mercapsoftware.com --------------------------------------------------------------------- Este mensaje es confidencial. Puede contener informacion amparada por el secreto profesional. Si usted ha recibido este e-mail por error, por favor comuniquenoslo inmediatamente via e-mail y tenga la amabilidad de eliminarlo de su sistema; no debera copiar el mensaje ni divulgar su contenido a ninguna persona. Muchas gracias. This message is confidential. It may also contain information that is privileged or otherwise legally exempt from disclosure. If you have received it by mistake please let us know by e-mail immediately and delete it from your system; you should also not copy the message nor disclose its contents to anyone. Thanks. --------------------------------------------------------------------- |
In reply to this post by Alan L. Lovejoy
Alan Lovejoy wrote:
You are right, but I did not say that Chronos had that problem, I just said what we wanted to avoid, that's all...Jeff, Hernan: I also will put my comments in-line, following Hernan's, preceded by ##: -----Original Message----- From: [hidden email] [[hidden email]] On Behalf Of Hernan Wilkinson Sent: Thursday, April 20, 2006 3:20 PM To: The general-purpose Squeak developers list Subject: Re: The Timing of Time Hi Jeff, I will answer your questions over Alan's responses to make it easy to compare both solutions. (I hope Alan you don't mind...) Alan Lovejoy wrote: [snip]Date equality works correctly between different calendars, and Timepoint equality works correctly between different time zones and/or different calendars.Chalten does not have support for time zone or different calendars. It just support the Gregorian Calendar; we are planning to add support to other calendars and time zone but in different packages... it is not common to use other calendars than the Gregorian and we don't want to make the most commonly used abstraction difficult to understand because of that support. ## Non-gregorian calendars in Chronos are completely invisible to programmers who don't want or need them. In fact, all the non-Gregorian calendar classes could simply be removed, and the only Chronos code that would break would be example code in comments (if you can call such code-in-the-comments "Chronos code.") Where in any of the Chronos examples you've seen in this discussion can you spot the fact that Chronos even supports calendars other than the Gregorian? I mention it in passing, but there's no evidence of it in any of the code examples. I agree. As I said in other mails:## Why not just use Chronos for time zones and for non-Gregorian calendars? I've already done the hard work--and you'll find the job is a lot harder than you currently imagine. The opportunity for synergy between Chalten and Chronos in this area seems very strong to me. 1) We have to add that functionality to Chalten because it is part of the thesis that Maxi has to write. It would be of great help to "use" what you did with Chronos, to merge your ideas with ours, but first we have to analyze Chronos, understand how it is design and implemented, etc. So, yeah, I agree with what you say. I'll let you know personally (I think it does not make sense to use the squeak list for this) what are the next steps once we decide them 2) I believe, as you say, that we and all the smalltalk community can benefit from merging Chronos and Chalten, so if I say something that Chalten does is not to say that Chronos does not, I don't know how Chronos is implemented, all the functionality it covers, etc. Defenitly you know more than we know about the time domain. We have not gone into too much detail on the civil calendars, etc. But I like the idea of using measure instead of duration because as conceptual entities, they represent the same. The only difference is that measures are more generic because they can be use as measure of time, length, money, etc. So, I like the idea of using measure because when you get used to it, you don't have to care anymore about all the different classes that represent, in an abstract way, the same concept, like Duration, Money, Length, etc. All those concept can be represented as Measures. But hey, that's my idea and not everybody has to agree with me...It's easy to convert a Chronos YearMonthDay or Timepoint into a count of days, or to convert a count of days into a YearMonthDay or Timepoint: YearMonthDay daysSinceEpoch: YearMonthDay today daysSinceEpoch.Same for Chalten. For example: ( January first, 2006) numberOfDaysFromBaseDate --> Returns "38351 days". But as you can see it returns a Measure. They also are immutable, comparable, can be put in Sets, Dictionaries, etc. I believe that the fact that we return a Measure and not just a numbers makes "explicit" the meaning of the returned object. It is not just 38351 but "38351 days" ## Chronos: ## ## 1) YearMonthDay today - (YearMonthDay year: 1901 day: 1) => 38460:00:00:00 (38460 days as a duration object) ## 2) YearMonthDay today civilDurationSince: (YearMonthDay year: 1901 day: 1)=> P105Y3M19D (also a duration object, representing 105 years, 3 months, 19 days) ## Chronos durational objects are immutable, comparable, can be used in Sets, Dictionaries, etc. But I think that if you have a Duration and want its value in seconds you will have to send it the message #asSeconds or something like that... Maybe I'm wrong, but if that is the case I prefer to have more polymorphic objects (measures) and less messages, for me is easier to remember.What's the advantage? Well, there are many, for example: 1) If you see the message #numberOfDaysFromBaseDate we, as programmer, know that it will return a number or a measure in this case, but what happens if you just see the object "38351"? You will not be able to know if they are days, seconds, years or what ever meaning it has. If instead you see "38351 days", now you know you are dealing with days. But not only we as programmers will notice that, the whole idea of Aconcagua is that the computer will handle any arithmetic mistake you can have mixing measure of different units. Using measures, you will never mix days and years. For example: a) If the model returns numbers instead of measures, you could write: ( January first, 2006) numberOfDaysFromBaseDate + ( January first, 2006) year yearsFromBaseDate --> That is 38351 + 106 = 40357 There is no way to know from the result that you added days and years. b) If the model returns measures: ( January first, 2006) numberOfDaysFromBaseDate + ( January first, 2006) year yearsFromBaseDate --> It will return "38351 days + 106 years" As you can see, it does not mix up days and years because they are not interchangeable. A year can be 365 or 366 days in the Gregorian calendar. 2) Because we use measures, if you want to know the number of hours from the base date, you can do: ( January first, 2006) numberOfDaysFromBaseDate convertTo: TimeUnits hour --> Returns " 920424 hours". Or seconds: ( January first, 2006) numberOfDaysFromBaseDate convertTo: TimeUnits hour --> Returns " 3313526400 seconds" There is no need for a class Duration or special messages to get the number of seconds from base date, etc. ## I generally agree with Hernan's explanation of the motivation for using durational objects. But there are times when integer numbers are better. For one thing, the messages to get the count of days must exist in order to create the durational values. And whith a Chrohos durational object, there is no need to convert it from days to hours--the same object encompasses all units from nanoseconds to weeks. Ok, thanks!. I'll check that out## By the way, if you are intrigued by the Aconcagua domain-specific language for measures, you should also check out Frink: http://futureboy.homeip.net/frinkdocs/ Cool, I'm learning about Chronos. From the functionality point of view, they are equal, but for me is difficult to understand at first sight what CalendarDayDuration mean. I understand now, but I tried "10 * CalendarDayDuration" and it did not work... so they do not conform to the commutative property that one expect from arithmetic operations... We face those problems when doing Aconcagua, that's why we create a new abstraction called ArithmeticObject (that if we could, Number should subclass it).So the problem of indexing by a date resolves to the problem of indexing by an integer. It's also possible to convert a date into a count of months or years since the calendar epoch, and to convert a count of months or years since a calendar epoch into a date. Both YearMonthDay and Timepoint (which inherits from YearMonthDay) support date and time arithmetic operations: #addingYears: #subtractingYears: #addingMonths: #subtractingMonths: #addingDays: #subtractingDays: #addingYears:months:days: #subtractingYears:months:days: #addingHours: #subtractingHours: #addingMinutes: #subtractingMinutes: #addingSeconds: #subtractingSeconds: #addingSeconds:nanonseconds: #subtractingSeconds:nanoseconds:Well, here is an example of how we simplified the protocol of all PointInTime objects using measures. For the same porpouse that Alan shows in Chronos, we have only two messages: #next: and #previous: (we don't use add and subtract for semantinc issues, but that another problem it does not make sense to talk about now). For example: GregorianDate today next: 10 * TimeUnits day -> Will return " April 30, 2006" if today is " April 20, 2006" ## YearMonthDay today + (CalendarDayDuration * 10) Anyway, as I said before, I believe that Measure is a more generic and abstract way of representing time durations and the good thing about measures is that all measures are polymorphic!. The same is not true for Duration, Money (if it existed), Length (if it is created) etc. [I erased some of the examples because they are equivalent to the one above] But this examples you provide do not have the same result as in Chalten.GregorianDay today next: 3 * TimeUnits day --> Will return "Sunday" if today is "Thursday" ## YearMonthDay today + (CalendarDayDuration * 3) ## Timepoint today + (CalendarDayDuration * 3) ## Timeperiod today + (CalendarDayDuration * 3) YearMonthDay today + (CalendarDayDuration * 3) --> Returns an instance of YearMonthDay instead of an object that represent a day in a week, like in Chalten that returns "Thursday", and instance of GregorianDay (it is not the same as GregorianDate). The other two examples do not return a day also. (By the way, what is the difference between YearMonthDay and Timepoint? I see you use it in a different way as we do...) This example also is not the same as what I showed with Chalten. My example return a Month, in this case "February" that is instance of GregorianMonth...GregorianMonth current previous: 2 * TimeUnits month --> Will return " February" if the current month is " April" etc. ## Timeperiod currentMonth - (MonthDuration * 2) [snip] That's find. When we did Chalten we decided not to follow the ANSI standard because we do not agree with some abstractions they propose.We do not implemented the #+, #-, etc. messages in PointInTime objects because those message do not keep the same semantic as the arithmetic message. For example. if you do "1 + 2" you get "3". That is, you are adding number, you get a number. But for dates is not the same... For example "GregorianDate today + 10 days" would not return a measure of days but a new date, so it does not match the semantics of the arithmetic +. Of course this is a decision we made and not everybody could like or agree with that... but we believe it makes more clear the model's language. ## Chronos implements the #+ and #- messages for two reasons: ## ## 1) It's required by the ANSI Smalltalk Standard. ## 2) In mathematics, the semantics of + and - depend upon the algebra one formally defines. There is no general requirement that both operands of the + or - opertor be of the same type. "Mixed mode" arithmetic expressions are common, useful and formally well defined. About the mathematic semantics, as you say, you can define what ever you want for the + and -, we just believe that doing so you loose polymorphisms and we did not what to do that. I mean, you can not use the + with number and duration polymorphically. Instead in Aconcagua, the +, - , etc. can be used with number and measures polymorphically. Definitively you have more idea about time standards that we do....The "duration" instance variable might have the value "ScientificDuration hours: 3.5", or it might have the value "CalendarDuration months: 3." The "baseTimepoint" instance variable could hold either a Timepoint, a YearMonthDay--or even a Timeperiod (interval of time.) For example, "Timeperiod currentMonth + (CalendarDuration days: 5)" (if executed during the month of April, 2006) evaluates to "2006-04-06/P1M" (the one-month interval starting 6 April 2006.)Chalten also have an abstraction for this, it named Timespan. It represents segment of the time line. For example: GregorianTimespan from: GregorianDate today duration: 20 * TimeUnits day --> Returns "20 days from April 20, 2006" ## Timeperiod from: YearMonthDay today duration: CalendarDayDuration * 20 => 2006-04-20/P20D (ISO 8601 notation for "the 20-day period starting with 2006-04-20") We also have the abstraction GregorianDay (ie. Monday) , GregorianDayOfMonth (ie. January 1) and GregorianMonthOfYear (January 2006)GregorianTimespan from: GregorianYear current duration: 10 * TimeUnits year --> Returns " 10 years from Year 2006" ## Chronos doesn't have a "Year" class -- and that's one of the obvious opportunities for synergy between Chalten and Chronos Just to understand a little bit more about Chronos, does it have those abstractions? ## It's also serendipitous that both Timeperiod and GregorianTimespan use jaja. I agree....#from:duration: as instance creation methods--must be the right method name. Ok, I made a question before about this... It is answered now.GregorianTimespan from: GregorianMonth current duration: 2 * TimeUnits month --> Returns " 2 months from April" ## Yet another opportunity for synergy... Ok, cool.GregorianTimespan from: GregorianDay today duration: 2 * TimeUnits day --> Returns " 2 days from Thursday" GregorianTimespan from: GregorianDayOfMonth today duration: 25 * TimeUnits day --> Returns " 25 days from April 20" ## Timeperiod from: DayOfMonth today duration: CalendarDayDuration * 25 ## Timeperiod from: DayOfYear today duration: CalendarDayDuration * 25 ## Timeperiod from: WeekOfMonthDayOfWeek today duration: CalendarDayDuration * 25 ## Timeperiod from: GregorianEaster canonical duration: CalendarDayDuration * 25 GregorianTimespan from: GregorianMonthOfYear current duration: 12 * TimeUnits month --> Returns " 12 months from April of Year 2006" ## Yet another opportunity for synergy... It is good to see we use the same names...GregorianTimespan from: TimeOfDay now duration: 12 * TimeUnits hour --> Returns " 12 hours from 18:53:33" (I wrote the mail at 18:53:33) ## Uh, oh: Both Chronos and Chalten use the class name TimeOfDay. This won't matter in VW, but Squeak really needs namespaces or class boxes... ## Timeperiod from: TimeOfDay now duration: 12 * HourDuration Cool.... we have a lot of thing to talk about... Maxi is taken notes on this so we can take advantage of what we have talk so farGregorianTimespan from: GregorianDateTime now duration: 12 * TimeUnits hour --> Returns " 12 hours from April 20, 2006 18:54:14" Look how easy is to use the same abstraction, GregorianTimespan, to any type of PointInTime. I think we could achieve that because we are using measures and all point in times are polymorphic. (By the way, we use GregorianTimespan because Chronology already defines Timespan) We also have time intervals, that are instances of the class "ArihtmeticObjectInterval" (I think not a good name). We could not use the Interval class for many reason. Anyway, ArihtmeticObjectInterval is an interval of any type of Magnitude, for example Measures, Numbers and of course PointInTimes. For example: GregorianDate today to: December first, 2006 --> Returns an interval from today to December fist 2006 by 1 day GregorianDate today to: December first, 2006 by: 10 * TimeUnits day --> Returns an interval from today to December fist 2006 with steps of 10 days ## I considered implementing a TemporalInterval where the step value would be specified. In the end, I decided to simply make it easy to enumerate between the endpoints of a Timeperiod using any ScientificDuration or CivilDuration as the step value, and let applications manage the step value as they care to. Implementing a TemporalInterval on top of Timeperiod would be easy to do. Perhaps this is another opportunity for synergy between Chronos and Chalten. GregorianMonth current to: December by: 2 * TimeUnits month --> Now, and interval of months.... the same for other time points... ## Yet another opportunity for synergy... Because these objects are intervals, they are polymorphic with Collection: (GregorianDate today to: December first, 2006) select: [ :aDate | aDate isMonday ] --> Returns all Mondays from today to December first (GregorianYear current to: (GregorianYear number: 3000) ) select: [ :aYear | aYear isLeap ] --> Returns all leap year up to year 3000 (January first, 2006 to: GregorianDate today) collect: [ :aDate | aDate distanceTo: GregorianDate today ] --> Returns an array with measures from 109 days to 0 days Ok, your solution is different.Does that answer your question about indexing? Jeff: "What should happen if you start at January 28'th and advance by a month and then go back by a month? Jan28 --> Feb28 --> (Jan 28 or Jan 31?) Can we agree on some conventions? " (YearMonthDay year: 2006 month: 1 day: 28) + 1 months => 2006-02-28 (YearMonthDay year: 2006 month: 1 day: 31) + 1 months => 2006-02-28 (YearMonthDay year: 2006 month: 1 day: 28) + 1 months - 1 months => 2006-01-28 (YearMonthDay year: 2006 month: 1 day: 31) + 1 months - 1 months => 2006-01-28 (Note: "1 months" works in VW and Dolphin, but not in Squeak, where "(CalendarDuration months: 1)" must be used instead--or you could add a #months and #years method to Integer yourself.)In Chalten we have a set of units that are interchangeable for years, moths, decades, etc. and another for days, hours, seconds, weeks, etc. Notice that time units are not the same as time points (there is an object for years, ie. GregorianYear, and there is a unit to measure years, ie. TimeUnit year) That means that measures expressed in days can not be converted to months or years and vicersa. (Is 30 days a month? or 31 days? etc.) Because of the irregularity of the Gregorian calendar we decided not to allow movements of point in times with measure of units of less granularity that the point in time granularity. For example: GregorianDate today next: 1 * TimeUnits second --> Is not allowed But we added for convenience that possibility of doing: (January thirtyfirst, 2006 next: 1 * TimeUnits month) --> Returns February 28, 2006 (January thirtyfirst, 2006 next: 1 * TimeUnits month) previous: 1 * TimeUnits month --> Returns January 28, 2006 I don't like this behavior but we added because we people are used to it. ## YearMonthDay today addingSeconds: 1000 => 2006-04-20T00:16:40 ## This case is no different than "3 / 4" or "100 factorial." Autoconvervion/autopromotion is the Smalltalk way. Well, Alan, this helped us to understand more about Chronos... as you say we should find the way to merge the models. I'll let you know what our ideas are as soon as we decide them. Let's keep in touch. Bye, Hernan. Well, the mail became longer that I expected. I hope it helps you to understand Chalten and also compare it with other solutions. Bye, HernanChronos implements date arithmetic to satisfy the typical business usecase.If you want "scientific" behavior, use a ScientificDuration. If you want a "month" to always be 30 days, use a "monthDuration" value defined as "CalendarDuration days: 30." But these questions just scratch the surface. There's a lot more than can and should be asked. --Alan -----Original Message----- From: [hidden email] [[hidden email]] On Behalf Of Jeffrey J. Hallman Sent: Wednesday, April 19, 2006 9:10 AM To: [hidden email] Subject: Re: The Timing of Time I'm enjoying the discussion about calendars and times, but I'd like to direct some attention to the idea of a TimeIndex. I came at this from another direction, thinking of a TimeSeries as data indexed by time, which leads to the idea of a TimeIndex. In my current implementation, a TimeIndex has two instance variables: afreqsymbol (such as #weeklyMonday, #monthly, #hourly, etc.) and an integer period, which represents the number of periods elapsed since the baseperiodfor that freq. TimeIndex understands '+' and '-', so if 'z' is the weeklyMonday time index for April 17 2006, then (z - 4) asYmd yields 20060320, and so on. My TimeSeries class is a subclass of Matrix with an additional instance variable called 'start' which is a TimeIndex, and has accessors like TimeSeries>>atTimeIndex: TimeSeries>>atTimeIndex:put: TimeSeries>>atTimeIndex:column: TimeSeries>>atTimeIndex:column:put: I've found this scheme works pretty well, and will probably generalize it a bit more by making TimeIndex an abstract class with subclasses fordifferentkinds of sequences. I think a package that wants to handle date and time issues should have something like a TimeIndex in it that allows sequences of various frequencies to be defined. At the same time, the implementation should be simple enough to be easily understood, and indexing into a TimeSeriesshouldbe very fast. If indexing isn't fast, we'll end up with ugly code in every TimeSeries method that that converts TimeIndex'es to row numbers and back. Trust me, you really don't want that. So how do these various packages handle indexing data by time? A second issue is how to handle date arithmetic. Some durations are based on linear time (e.g., weeks, seconds, hours, etc.) and others are based on the calendar (months, years, etc.). The distinction between these twoleadsto questions like: What should happen if you start at January 28'th and advance by a month and then go back by a month? Jan28 --> Feb28 --> (Jan 28 or Jan 31?) Can we agree on some conventions? Jeff Hallman-- ______________________________ Lic. Hernán A. Wilkinson Gerente de Desarrollo y Tecnología Mercap S.R.L. Tacuari 202 - 7mo Piso - Tel: 54-11-4878-1118 Buenos Aires - Argentina http://www.mercapsoftware.com --------------------------------------------------------------------- Este mensaje es confidencial. Puede contener informacion amparada por el secreto profesional. Si usted ha recibido este e-mail por error, por favor comuniquenoslo inmediatamente via e-mail y tenga la amabilidad de eliminarlo de su sistema; no debera copiar el mensaje ni divulgar su contenido a ninguna persona. Muchas gracias. This message is confidential. It may also contain information that is privileged or otherwise legally exempt from disclosure. If you have received it by mistake please let us know by e-mail immediately and delete it from your system; you should also not copy the message nor disclose its contents to anyone. Thanks. --------------------------------------------------------------------- -- ______________________________ Lic. Hernán A. Wilkinson Gerente de Desarrollo y Tecnología Mercap S.R.L. Tacuari 202 - 7mo Piso - Tel: 54-11-4878-1118 Buenos Aires - Argentina http://www.mercapsoftware.com --------------------------------------------------------------------- Este mensaje es confidencial. Puede contener informacion amparada por el secreto profesional. Si usted ha recibido este e-mail por error, por favor comuniquenoslo inmediatamente via e-mail y tenga la amabilidad de eliminarlo de su sistema; no debera copiar el mensaje ni divulgar su contenido a ninguna persona. Muchas gracias. This message is confidential. It may also contain information that is privileged or otherwise legally exempt from disclosure. If you have received it by mistake please let us know by e-mail immediately and delete it from your system; you should also not copy the message nor disclose its contents to anyone. Thanks. --------------------------------------------------------------------- |
Hernan: "I did not say that Chronos had that problem, I just said what we wanted
to avoid, that's all... "
Ok, understood.
Hernan: "We have to add that functionality to Chalten because it is part of the
thesis that Maxi has to write."
Is the thesis requirement just that time zone and
multi-calendar functionality must be in the functional set, or also that Maxi
must design and implement the whole protocol stack, soup to
nuts?
Whatever the case, a thesis requirement (or a desire to
learn by doing) is admittedly a valid reason to reinvent the wheel. I've
done the same myself.
Hernan: "I like the idea of using measure instead of duration because as
conceptual entities, they represent the same. The only difference is that
measures are more generic because they can be use as measure of time, length,
money, etc. So, I like the idea of using measure because when you get used to
it, you don't have to care anymore about all the different classes that
represent, in an abstract way, the same concept, like Duration, Money, Length,
etc. All those concept can be represented as Measures. But hey, that's my idea
and not everybody has to agree with
me..."
I like Measures too--for the reasons you give.
But sometimes, you just need simple numbers (or integers)--the Measure
implementation may need them internally, for example. In the case of Chronos, my
policy was to strictly conform to the ANSI Smalltalk Standard (which requires
Durations to work the way Chronos and Chronology implement them,) and to leave
the implementation of "Measures" to either some other time, or to some other
developer. I neither can nor should do everyting, and am actually looking
forward to collaborating with others for help with a) porting to other Smalltalk
environments,) b) getting low-level extensions implemented that Chronos can use
(in Squeak, the opportunities are in the area of locales and system time zone
discovery,) and c) implementing higher-level abstractions on top of Chronos, of
which Measures is a good example.
Hernan: "But I think that if you have a Duration and want its value in seconds you
will have to send it the message #asSeconds or something like that... Maybe I'm
wrong, but if that is the case I prefer to have more polymorphic objects
(measures) and less messages, for me is easier to
remember."
Yes, you have to send messages such as #asSeconds or
#asHours to a durational object (as required by the ANSI Smalltalk
Standard.)
And as I said, Measures are a great idea--especially if
they provide Frink-like functionality (http://futureboy.homeip.net/frinkdocs/)
Hernan: "I tried "10 * CalendarDayDuration" and it did not work... so they do not
conform to the commutative property that one expect from arithmetic
operations... We face those problems when doing Aconcagua, that's why we create
a new abstraction called ArithmeticObject (that if we could, Number should
subclass it). "
Implementing the commutative property, while highly
desirable, has one drawback: it exposes Chronos to the danger of contention with
the methods added to base-library classes by others to do the same for
their date/time objects. If Chronos were just an application whose code was not
meant to be widely shared among many different applications and other libraries,
I'd have implemented the commutative property for all appropriate cases.
The case for library code is much more problematical--and this problem is a high
priority issue to be solved by the language
designers.
Hernan: "But this examples you provide do not have the same result as in
Chalten."
At first, I didn't understand why you said that.
Then I realized it was because the Chalten expresssions were evaluating to
DayOfTheWeek objects, and not to Date objects.
My
mistake.
Chronos doesn't have "DayOfTheWeek" objects. It
does define the constants Sunday, Monday, etc. containing the integers 1, 2,
etc. It also uses the Symbols #Sunday, #Monday, etc. One reason is because
the ANSI Smalltalk Standard defines dayOfWeek as returning an integer between 1
and 7, whith 1 = Sunday.
Hernan: "This example also is not the same as what I showed with Chalten. My
example return a Month, in this case "February" that is instance of
GregorianMonth..."
Again, Chronos doesn't have a "Month" object that
exactly corresponds to Chalten's. It does define the constants January,
February, etc containing the integers 1, 2 etc. It also uses the Symbols
#January, #February etc. The ANSI Standard is one reason. Another is
to preserve polymorphism across different
calendars.
Chronos also has the class MonthOfYear--but it's an
AnnualDate, which although similar in some ways to the Chalten concept, is also
different Then there's MonthlyCalendar, which again is different, since
it's a singleton that encapsulates all knowledge regarding the
characteristics of a particular month in a partcicular type of year for a
particular calendar (e.g. the Hebrew month 'Adar Rishon' in a Hebrew deficient
leap year--there are six different year types in the Hebrew calendar; 'Adar
Rishon' is a leap month; Hebrew years may have either 12 or 13
months.)
For most cases, my belief is that a Timeperiod with a
duration of 1 month provides all needed functionality to represent a month in
the timeline, and a Timeperiod with duration 1 year does the same for the
representation of a year in the timeline. But I'm open to
counterexamples. And I have no objection to having objects other than
Timeperiods that can represent "a month in the timeline" or "a year in the
timeline" available as optional extensions to
Chronos.
Hernan: "we just believe that doing so you loose polymorphisms and we did not what
to do that. I mean, you can not use the + with number and duration
polymorphically. Instead in Aconcagua, the +, - , etc. can be used with number
and measures polymorphically."
Well, I haven't tried it, but my hunch would be that
double-dispatching should enable the desired polymorphism. I'll look into
the matter at some point.
--Alan
P.S. I'm sure we'll have more to talk about "as
time goes by." (Heh)
From: [hidden email] [mailto:[hidden email]] On Behalf Of Hernan Wilkinson Sent: Friday, April 21, 2006 5:49 AM To: The general-purpose Squeak developers list Subject: Re: The Timing of Time You are right, but I did not say that Chronos had that problem, I just said what we wanted to avoid, that's all...Jeff, Hernan: I also will put my comments in-line, following Hernan's, preceded by ##: -----Original Message----- From: [hidden email] [[hidden email]] On Behalf Of Hernan Wilkinson Sent: Thursday, April 20, 2006 3:20 PM To: The general-purpose Squeak developers list Subject: Re: The Timing of Time Hi Jeff, I will answer your questions over Alan's responses to make it easy to compare both solutions. (I hope Alan you don't mind...) Alan Lovejoy wrote: [snip]Date equality works correctly between different calendars, and Timepoint equality works correctly between different time zones and/or different calendars.Chalten does not have support for time zone or different calendars. It just support the Gregorian Calendar; we are planning to add support to other calendars and time zone but in different packages... it is not common to use other calendars than the Gregorian and we don't want to make the most commonly used abstraction difficult to understand because of that support. ## Non-gregorian calendars in Chronos are completely invisible to programmers who don't want or need them. In fact, all the non-Gregorian calendar classes could simply be removed, and the only Chronos code that would break would be example code in comments (if you can call such code-in-the-comments "Chronos code.") Where in any of the Chronos examples you've seen in this discussion can you spot the fact that Chronos even supports calendars other than the Gregorian? I mention it in passing, but there's no evidence of it in any of the code examples. I agree. As I said in other mails:## Why not just use Chronos for time zones and for non-Gregorian calendars? I've already done the hard work--and you'll find the job is a lot harder than you currently imagine. The opportunity for synergy between Chalten and Chronos in this area seems very strong to me. 1) We have to add that functionality to Chalten because it is part of the thesis that Maxi has to write. It would be of great help to "use" what you did with Chronos, to merge your ideas with ours, but first we have to analyze Chronos, understand how it is design and implemented, etc. So, yeah, I agree with what you say. I'll let you know personally (I think it does not make sense to use the squeak list for this) what are the next steps once we decide them 2) I believe, as you say, that we and all the smalltalk community can benefit from merging Chronos and Chalten, so if I say something that Chalten does is not to say that Chronos does not, I don't know how Chronos is implemented, all the functionality it covers, etc. Defenitly you know more than we know about the time domain. We have not gone into too much detail on the civil calendars, etc. But I like the idea of using measure instead of duration because as conceptual entities, they represent the same. The only difference is that measures are more generic because they can be use as measure of time, length, money, etc. So, I like the idea of using measure because when you get used to it, you don't have to care anymore about all the different classes that represent, in an abstract way, the same concept, like Duration, Money, Length, etc. All those concept can be represented as Measures. But hey, that's my idea and not everybody has to agree with me...It's easy to convert a Chronos YearMonthDay or Timepoint into a count of days, or to convert a count of days into a YearMonthDay or Timepoint: YearMonthDay daysSinceEpoch: YearMonthDay today daysSinceEpoch.Same for Chalten. For example: ( January first, 2006) numberOfDaysFromBaseDate --> Returns "38351 days". But as you can see it returns a Measure. They also are immutable, comparable, can be put in Sets, Dictionaries, etc. I believe that the fact that we return a Measure and not just a numbers makes "explicit" the meaning of the returned object. It is not just 38351 but "38351 days" ## Chronos: ## ## 1) YearMonthDay today - (YearMonthDay year: 1901 day: 1) => 38460:00:00:00 (38460 days as a duration object) ## 2) YearMonthDay today civilDurationSince: (YearMonthDay year: 1901 day: 1)=> P105Y3M19D (also a duration object, representing 105 years, 3 months, 19 days) ## Chronos durational objects are immutable, comparable, can be used in Sets, Dictionaries, etc. But I think that if you have a Duration and want its value in seconds you will have to send it the message #asSeconds or something like that... Maybe I'm wrong, but if that is the case I prefer to have more polymorphic objects (measures) and less messages, for me is easier to remember.What's the advantage? Well, there are many, for example: 1) If you see the message #numberOfDaysFromBaseDate we, as programmer, know that it will return a number or a measure in this case, but what happens if you just see the object "38351"? You will not be able to know if they are days, seconds, years or what ever meaning it has. If instead you see "38351 days", now you know you are dealing with days. But not only we as programmers will notice that, the whole idea of Aconcagua is that the computer will handle any arithmetic mistake you can have mixing measure of different units. Using measures, you will never mix days and years. For example: a) If the model returns numbers instead of measures, you could write: ( January first, 2006) numberOfDaysFromBaseDate + ( January first, 2006) year yearsFromBaseDate --> That is 38351 + 106 = 40357 There is no way to know from the result that you added days and years. b) If the model returns measures: ( January first, 2006) numberOfDaysFromBaseDate + ( January first, 2006) year yearsFromBaseDate --> It will return "38351 days + 106 years" As you can see, it does not mix up days and years because they are not interchangeable. A year can be 365 or 366 days in the Gregorian calendar. 2) Because we use measures, if you want to know the number of hours from the base date, you can do: ( January first, 2006) numberOfDaysFromBaseDate convertTo: TimeUnits hour --> Returns " 920424 hours". Or seconds: ( January first, 2006) numberOfDaysFromBaseDate convertTo: TimeUnits hour --> Returns " 3313526400 seconds" There is no need for a class Duration or special messages to get the number of seconds from base date, etc. ## I generally agree with Hernan's explanation of the motivation for using durational objects. But there are times when integer numbers are better. For one thing, the messages to get the count of days must exist in order to create the durational values. And whith a Chrohos durational object, there is no need to convert it from days to hours--the same object encompasses all units from nanoseconds to weeks. Ok, thanks!. I'll check that out## By the way, if you are intrigued by the Aconcagua domain-specific language for measures, you should also check out Frink: http://futureboy.homeip.net/frinkdocs/ Cool, I'm learning about Chronos. From the functionality point of view, they are equal, but for me is difficult to understand at first sight what CalendarDayDuration mean. I understand now, but I tried "10 * CalendarDayDuration" and it did not work... so they do not conform to the commutative property that one expect from arithmetic operations... We face those problems when doing Aconcagua, that's why we create a new abstraction called ArithmeticObject (that if we could, Number should subclass it).So the problem of indexing by a date resolves to the problem of indexing by an integer. It's also possible to convert a date into a count of months or years since the calendar epoch, and to convert a count of months or years since a calendar epoch into a date. Both YearMonthDay and Timepoint (which inherits from YearMonthDay) support date and time arithmetic operations: #addingYears: #subtractingYears: #addingMonths: #subtractingMonths: #addingDays: #subtractingDays: #addingYears:months:days: #subtractingYears:months:days: #addingHours: #subtractingHours: #addingMinutes: #subtractingMinutes: #addingSeconds: #subtractingSeconds: #addingSeconds:nanonseconds: #subtractingSeconds:nanoseconds:Well, here is an example of how we simplified the protocol of all PointInTime objects using measures. For the same porpouse that Alan shows in Chronos, we have only two messages: #next: and #previous: (we don't use add and subtract for semantinc issues, but that another problem it does not make sense to talk about now). For example: GregorianDate today next: 10 * TimeUnits day -> Will return " April 30, 2006" if today is " April 20, 2006" ## YearMonthDay today + (CalendarDayDuration * 10) Anyway, as I said before, I believe that Measure is a more generic and abstract way of representing time durations and the good thing about measures is that all measures are polymorphic!. The same is not true for Duration, Money (if it existed), Length (if it is created) etc. [I erased some of the examples because they are equivalent to the one above] But this examples you provide do not have the same result as in Chalten.GregorianDay today next: 3 * TimeUnits day --> Will return "Sunday" if today is "Thursday" ## YearMonthDay today + (CalendarDayDuration * 3) ## Timepoint today + (CalendarDayDuration * 3) ## Timeperiod today + (CalendarDayDuration * 3) YearMonthDay today + (CalendarDayDuration * 3) --> Returns an instance of YearMonthDay instead of an object that represent a day in a week, like in Chalten that returns "Thursday", and instance of GregorianDay (it is not the same as GregorianDate). The other two examples do not return a day also. (By the way, what is the difference between YearMonthDay and Timepoint? I see you use it in a different way as we do...) This example also is not the same as what I showed with Chalten. My example return a Month, in this case "February" that is instance of GregorianMonth...GregorianMonth current previous: 2 * TimeUnits month --> Will return " February" if the current month is " April" etc. ## Timeperiod currentMonth - (MonthDuration * 2) [snip] That's find. When we did Chalten we decided not to follow the ANSI standard because we do not agree with some abstractions they propose.We do not implemented the #+, #-, etc. messages in PointInTime objects because those message do not keep the same semantic as the arithmetic message. For example. if you do "1 + 2" you get "3". That is, you are adding number, you get a number. But for dates is not the same... For example "GregorianDate today + 10 days" would not return a measure of days but a new date, so it does not match the semantics of the arithmetic +. Of course this is a decision we made and not everybody could like or agree with that... but we believe it makes more clear the model's language. ## Chronos implements the #+ and #- messages for two reasons: ## ## 1) It's required by the ANSI Smalltalk Standard. ## 2) In mathematics, the semantics of + and - depend upon the algebra one formally defines. There is no general requirement that both operands of the + or - opertor be of the same type. "Mixed mode" arithmetic expressions are common, useful and formally well defined. About the mathematic semantics, as you say, you can define what ever you want for the + and -, we just believe that doing so you loose polymorphisms and we did not what to do that. I mean, you can not use the + with number and duration polymorphically. Instead in Aconcagua, the +, - , etc. can be used with number and measures polymorphically. Definitively you have more idea about time standards that we do....The "duration" instance variable might have the value "ScientificDuration hours: 3.5", or it might have the value "CalendarDuration months: 3." The "baseTimepoint" instance variable could hold either a Timepoint, a YearMonthDay--or even a Timeperiod (interval of time.) For example, "Timeperiod currentMonth + (CalendarDuration days: 5)" (if executed during the month of April, 2006) evaluates to "2006-04-06/P1M" (the one-month interval starting 6 April 2006.)Chalten also have an abstraction for this, it named Timespan. It represents segment of the time line. For example: GregorianTimespan from: GregorianDate today duration: 20 * TimeUnits day --> Returns "20 days from April 20, 2006" ## Timeperiod from: YearMonthDay today duration: CalendarDayDuration * 20 => 2006-04-20/P20D (ISO 8601 notation for "the 20-day period starting with 2006-04-20") GregorianTimespan from: GregorianYear current duration: 10 |
In reply to this post by Alan L. Lovejoy
Alan Lovejoy wrote:
You are right! We planned this thesis after me going to ESUG last year... [snip] Cool!, let's keep in touch. Hernan.
-- ______________________________ Lic. Hernán A. Wilkinson Gerente de Desarrollo y Tecnología Mercap S.R.L. Tacuari 202 - 7mo Piso - Tel: 54-11-4878-1118 Buenos Aires - Argentina http://www.mercapsoftware.com --------------------------------------------------------------------- Este mensaje es confidencial. Puede contener informacion amparada por el secreto profesional. Si usted ha recibido este e-mail por error, por favor comuniquenoslo inmediatamente via e-mail y tenga la amabilidad de eliminarlo de su sistema; no debera copiar el mensaje ni divulgar su contenido a ninguna persona. Muchas gracias. This message is confidential. It may also contain information that is privileged or otherwise legally exempt from disclosure. If you have received it by mistake please let us know by e-mail immediately and delete it from your system; you should also not copy the message nor disclose its contents to anyone. Thanks. --------------------------------------------------------------------- |
In reply to this post by Francisco Garau-2
Alan,
> Francisco: "I don't understand why you need so many different calendars. For > the example that I first posted (adjust a schedule to the japanese > calendar), you suggested that the Japanese imperial calendar would need to > be implemented. I would like to know what kind of applications are you > dealing with, in which expressing the dates in the original calendar is > important. For a financial application, the japanese calendar is just > another gregorian calendar with certain dates defined as bank > holidays." By the way, the Japanese calendar in last 100 year or so uses the same day and month as the Gregorian's, but the years are counted differently. If someone is writing an application that will be used by a financial institution or a school or such, it should handle that. For example, today (Apr 26th, 2006) is 18th year of Heisei, 4th month, 26th day, but 20 years ago was 61st year of Showa, 4th month, 26th day. -- Yoshiki |
Yoshiki: "By the way, the Japanese calendar in last 100 year or so uses the
same day and month as the Gregorian's, but the years are counted differently." In that case, adding a subclass of Calendar class to support the Japanese calendar would be relatively easy to do. And if the issue is holidays, those usually occur according to the same annual-recurrence rule each year--so the Gregorian calendar could be used. --Alan -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of Yoshiki Ohshima Sent: Wednesday, April 26, 2006 2:13 PM To: The general-purpose Squeak developers list Subject: Re: The Timing of Time Alan, > Francisco: "I don't understand why you need so many different > calendars. For the example that I first posted (adjust a schedule to > the japanese calendar), you suggested that the Japanese imperial > calendar would need to be implemented. I would like to know what kind > of applications are you dealing with, in which expressing the dates in > the original calendar is important. For a financial application, the > japanese calendar is just another gregorian calendar with certain > dates defined as bank holidays." By the way, the Japanese calendar in last 100 year or so uses the same day and month as the Gregorian's, but the years are counted differently. If someone is writing an application that will be used by a financial institution or a school or such, it should handle that. For example, today (Apr 26th, 2006) is 18th year of Heisei, 4th month, 26th day, but 20 years ago was 61st year of Showa, 4th month, 26th day. -- Yoshiki |
Free forum by Nabble | Edit this page |