Date text converter/formatter

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

Date text converter/formatter

Esteban A. Maringolo
Does exist an "user friendly" Date text converter and/or formatter package?


I'd like to specify the format of certain dates, in the way you
normally do this, it is... with a string such as 'dd/mm/yyyy' or
'dd/mmm/yyyy'.

Date's #printOn:format: expects a different parameter, which seems
really convoluted. [1]

And because I'll convert back and forth from/to String I'd like to
know if there is a parser (other than DateParser).

Thank you!


Esteban A. Maringolo

[1] compared with popular casting/formatting functions found in other
languages/dialects

Reply | Threaded
Open this post in threaded view
|

Re: Date text converter/formatter

Sven Van Caekenberghe-2
Check out ZTimestampFormatter (load ConfigurationOfZTimestamp). From the class comment:

===
I am ZTimestampFormat, an implementation of a textual representation for a timestamp, date or time that can be used for formatting or parsing.

You instanciate me by specifying the textual format by example, based on a #reference timetamp.
Each component of the example representation is numbered from largest to smallest unit:
        1=year
        2=month
        3=dayInMonth
        4=hour (16 in 24 hour format)
        5=minute
        6=second
as in the ISO representation:
        2001-02-03T16:05:06Z which is a Saterday.
Example format strings can be found in my class accessing protocol or in the unit tests.

To specifiy a format, you write the reference date so that it matches the representation that you want.

        (ZTimestampFormat fromString: 'SAT, FEB 03 2001 (16:05:06)')
                format: ZTimestamp now.

I can be used for unabiguous, stricter parsing as well.

        (ZTimestampFormat fromString: '02/03/01 (16:05:06)')
                parse: '10/10/10 (12:01:01)'.
               
The list of possible keys and their interpretation #formatSpecifications.
I can translate month and weekday names to 4 different languages, English, French, German and Dutch.
I can optionally use a timezone to convert UTC/GMT/Zulu timestamps to local time.
===

Sven

On 02 Sep 2014, at 20:51, Esteban A. Maringolo <[hidden email]> wrote:

> Does exist an "user friendly" Date text converter and/or formatter package?
>
>
> I'd like to specify the format of certain dates, in the way you
> normally do this, it is... with a string such as 'dd/mm/yyyy' or
> 'dd/mmm/yyyy'.
>
> Date's #printOn:format: expects a different parameter, which seems
> really convoluted. [1]
>
> And because I'll convert back and forth from/to String I'd like to
> know if there is a parser (other than DateParser).
>
> Thank you!
>
>
> Esteban A. Maringolo
>
> [1] compared with popular casting/formatting functions found in other
> languages/dialects
>


Reply | Threaded
Open this post in threaded view
|

Re: Date text converter/formatter

Esteban A. Maringolo
Thank you. It is certainly better than the base parser.
But for formats I can't pass Date objects to #format:, I have to
convert them to ZTimestamp before.

Curiosity #1: Why did you use an example date string instead of using
regular patterns like yyyy, dd, hh/hh24, etc?

Regards!
Esteban A. Maringolo


2014-09-02 16:07 GMT-03:00 Sven Van Caekenberghe <[hidden email]>:

> Check out ZTimestampFormatter (load ConfigurationOfZTimestamp). From the class comment:
>
> ===
> I am ZTimestampFormat, an implementation of a textual representation for a timestamp, date or time that can be used for formatting or parsing.
>
> You instanciate me by specifying the textual format by example, based on a #reference timetamp.
> Each component of the example representation is numbered from largest to smallest unit:
>         1=year
>         2=month
>         3=dayInMonth
>         4=hour (16 in 24 hour format)
>         5=minute
>         6=second
> as in the ISO representation:
>         2001-02-03T16:05:06Z which is a Saterday.
> Example format strings can be found in my class accessing protocol or in the unit tests.
>
> To specifiy a format, you write the reference date so that it matches the representation that you want.
>
>         (ZTimestampFormat fromString: 'SAT, FEB 03 2001 (16:05:06)')
>                 format: ZTimestamp now.
>
> I can be used for unabiguous, stricter parsing as well.
>
>         (ZTimestampFormat fromString: '02/03/01 (16:05:06)')
>                 parse: '10/10/10 (12:01:01)'.
>
> The list of possible keys and their interpretation #formatSpecifications.
> I can translate month and weekday names to 4 different languages, English, French, German and Dutch.
> I can optionally use a timezone to convert UTC/GMT/Zulu timestamps to local time.
> ===
>
> Sven
>
> On 02 Sep 2014, at 20:51, Esteban A. Maringolo <[hidden email]> wrote:
>
>> Does exist an "user friendly" Date text converter and/or formatter package?
>>
>>
>> I'd like to specify the format of certain dates, in the way you
>> normally do this, it is... with a string such as 'dd/mm/yyyy' or
>> 'dd/mmm/yyyy'.
>>
>> Date's #printOn:format: expects a different parameter, which seems
>> really convoluted. [1]
>>
>> And because I'll convert back and forth from/to String I'd like to
>> know if there is a parser (other than DateParser).
>>
>> Thank you!
>>
>>
>> Esteban A. Maringolo
>>
>> [1] compared with popular casting/formatting functions found in other
>> languages/dialects
>>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Date text converter/formatter

Sven Van Caekenberghe-2

On 02 Sep 2014, at 21:39, Esteban A. Maringolo <[hidden email]> wrote:

> Thank you. It is certainly better than the base parser.
> But for formats I can't pass Date objects to #format:, I have to
> convert them to ZTimestamp before.

(ZTimestampFormat fromString: '2001/02/03') format: Date today.

Can you give an example of what does not work for you ?

> Curiosity #1: Why did you use an example date string instead of using
> regular patterns like yyyy, dd, hh/hh24, etc?

That is why the formatter/parser was written in the first place ;-) It is modelled after a Go standard library (http://golang.org/src/pkg/time/format.go) and some Ruby library I can't remember the name of. I implemented this as a proof of concept to see if/how it could be done.

> Regards!
> Esteban A. Maringolo
>
>
> 2014-09-02 16:07 GMT-03:00 Sven Van Caekenberghe <[hidden email]>:
>> Check out ZTimestampFormatter (load ConfigurationOfZTimestamp). From the class comment:
>>
>> ===
>> I am ZTimestampFormat, an implementation of a textual representation for a timestamp, date or time that can be used for formatting or parsing.
>>
>> You instanciate me by specifying the textual format by example, based on a #reference timetamp.
>> Each component of the example representation is numbered from largest to smallest unit:
>>        1=year
>>        2=month
>>        3=dayInMonth
>>        4=hour (16 in 24 hour format)
>>        5=minute
>>        6=second
>> as in the ISO representation:
>>        2001-02-03T16:05:06Z which is a Saterday.
>> Example format strings can be found in my class accessing protocol or in the unit tests.
>>
>> To specifiy a format, you write the reference date so that it matches the representation that you want.
>>
>>        (ZTimestampFormat fromString: 'SAT, FEB 03 2001 (16:05:06)')
>>                format: ZTimestamp now.
>>
>> I can be used for unabiguous, stricter parsing as well.
>>
>>        (ZTimestampFormat fromString: '02/03/01 (16:05:06)')
>>                parse: '10/10/10 (12:01:01)'.
>>
>> The list of possible keys and their interpretation #formatSpecifications.
>> I can translate month and weekday names to 4 different languages, English, French, German and Dutch.
>> I can optionally use a timezone to convert UTC/GMT/Zulu timestamps to local time.
>> ===
>>
>> Sven
>>
>> On 02 Sep 2014, at 20:51, Esteban A. Maringolo <[hidden email]> wrote:
>>
>>> Does exist an "user friendly" Date text converter and/or formatter package?
>>>
>>>
>>> I'd like to specify the format of certain dates, in the way you
>>> normally do this, it is... with a string such as 'dd/mm/yyyy' or
>>> 'dd/mmm/yyyy'.
>>>
>>> Date's #printOn:format: expects a different parameter, which seems
>>> really convoluted. [1]
>>>
>>> And because I'll convert back and forth from/to String I'd like to
>>> know if there is a parser (other than DateParser).
>>>
>>> Thank you!
>>>
>>>
>>> Esteban A. Maringolo
>>>
>>> [1] compared with popular casting/formatting functions found in other
>>> languages/dialects
>>>
>>
>>
>


Reply | Threaded
Open this post in threaded view
|

Re: Date text converter/formatter

Sean P. DeNigris
Administrator
In reply to this post by Esteban A. Maringolo
Esteban A. Maringolo wrote
Curiosity #1: Why did you use an example date string instead of using
regular patterns like yyyy, dd, hh/hh24, etc?
I like the example concept because the user has less to remember (even if those date patterns are pretty well-known). Although, I noticed an example date of 10/10/14 - how does it decide which is the month and which the day?
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: Date text converter/formatter

Sven Van Caekenberghe-2

On 02 Sep 2014, at 23:15, Sean P. DeNigris <[hidden email]> wrote:

> Esteban A. Maringolo wrote
>> Curiosity #1: Why did you use an example date string instead of using
>> regular patterns like yyyy, dd, hh/hh24, etc?
>
> I like the example concept because the user has less to remember (even if
> those date patterns are pretty well-known). Although, I noticed an example
> date of 10/10/14 - how does it decide which is the month and which the day?

Hmm, that is not possible, where did you see that ?
Maybe you got the example and the input mixed up ?

You instantiate the format based on a example (#fromString:) and then you use that to either #parse: or #format:


Reply | Threaded
Open this post in threaded view
|

Re: Date text converter/formatter

Sean P. DeNigris
Administrator
Sven Van Caekenberghe-2 wrote
Maybe you got the example and the input mixed up ?
Oh yeah, I did, but even the example in that case is ambiguous, no?

(ZTimestampFormat fromString: '02/03/01 (16:05:06)')
                parse: '10/10/10 (12:01:01)'.

How does it decide whether it's American i.e. Feb 3rd, or European i.e. Mar 2nd?
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: Date text converter/formatter

Sven Van Caekenberghe-2
Hi Sean,

On 03 Sep 2014, at 00:32, Sean P. DeNigris <[hidden email]> wrote:

> Sven Van Caekenberghe-2 wrote
>> Maybe you got the example and the input mixed up ?
>
> Oh yeah, I did, but even the example in that case is ambiguous, no?
>
> (ZTimestampFormat fromString: '02/03/01 (16:05:06)')
>                parse: '10/10/10 (12:01:01)'.
>
> How does it decide whether it's American i.e. Feb 3rd, or European i.e. Mar 2nd?

No, it is not ambiguous. The positions in the pattern are not used to determine the meaning of the elements, only the values. For example, limited to date elements only:

(ZTimestampFormat fromString: '02/03/01') format: Date today. => '09/03/14'

(ZTimestampFormat fromString: '03/02/01') format: Date today. => '03/09/14'

(ZTimestampFormat fromString: 'Feb 3, 2001') format: Date today. => 'Sep 3, 2014'

(ZTimestampFormat fromString: '02-FEB-2001') format: Date today. => '09-SEP-2014'

(ZTimestampFormat fromString: 'Saturday, Februari 3 ''01') format: Date today. =>  'Wednesday, September 3 ''14'

The reference date is 20010203 which was a Saturday, the recognised elements for dates are:

'2001' yearFourDigits
'01' yearTwoDigits
'02001' yearFull
'02' monthTwoDigits
'2' month
'February' monthNameCapitalized
'february' monthNameLowercased
'FEBRUARY' monthNameUppercased
'Feb' monthNameAbbreviatedCapitalized
'feb' monthNameAbbreviatedLowercased
'FEB' monthNameAbbreviatedUppercased
'3' day
'_3' dayTwoDigitsSpacePadded
'03' dayTwoDigits

See #formatSpecifications, each of those has parse and format methods, like #format:yearTwoDigitsOn: and #parseYearTwoDigitsFrom:

Sven






Reply | Threaded
Open this post in threaded view
|

Re: Date text converter/formatter

Ben Coman
Sven Van Caekenberghe wrote:
Hi Sean,

On 03 Sep 2014, at 00:32, Sean P. DeNigris [hidden email] wrote:

  
Sven Van Caekenberghe-2 wrote
    
Maybe you got the example and the input mixed up ?
      
Oh yeah, I did, but even the example in that case is ambiguous, no?

(ZTimestampFormat fromString: '02/03/01 (16:05:06)')
               parse: '10/10/10 (12:01:01)'. 

How does it decide whether it's American i.e. Feb 3rd, or European i.e. Mar 2nd?
    

No, it is not ambiguous. The positions in the pattern are not used to determine the meaning of the elements, only the values. 

Okay, but its ambiguous in the sense that, at a glance, without knowing the legend (even though you provided it), at least Sean and myself got confused. 

For me part of that confusion is that you said...
>        1=year
>        2=month
>        3=dayInMonth
>        4=hour (16 in 24 hour format)
>        5=minute
>        6=second

but the example used
02=month
03=day

In either case, its harder to remember which magnitude an arbitrary index number refers, than using the usual mnemonics like this...
yy=year
mm=month
mmm=month name
d=day of month
dd=zero padded day of month
hh=12 hour
HH=24 hour
etc... and thats just off the top of my head.  I think most people are familiar with this.

Alternatively, if you want to use numbers, the following would be more intuitive to anyone glancing at it without needing to know the legend.
99=year
12=month
31=day
24=24 hour
12=12 hour
60=minute
?=second.
etc...

btw, I missed the first part of the
For example, limited to date elements only:

(ZTimestampFormat fromString: '02/03/01') format: Date today. => '09/03/14'

(ZTimestampFormat fromString: '03/02/01') format: Date today. => '03/09/14'

(ZTimestampFormat fromString: 'Feb 3, 2001') format: Date today. => 'Sep 3, 2014'

(ZTimestampFormat fromString: '02-FEB-2001') format: Date today. => '09-SEP-2014'

(ZTimestampFormat fromString: 'Saturday, Februari 3 ''01') format: Date today. =>  'Wednesday, September 3 ''14'

The reference date is 20010203 which was a Saturday, the recognised elements for dates are:

'2001' yearFourDigits
'01' yearTwoDigits
'02001'	yearFull
'02' monthTwoDigits
'2' month
'February' monthNameCapitalized
'february' monthNameLowercased
'FEBRUARY' monthNameUppercased
'Feb' monthNameAbbreviatedCapitalized
'feb' monthNameAbbreviatedLowercased
'FEB' monthNameAbbreviatedUppercased
'3' day
'_3' dayTwoDigitsSpacePadded
'03' dayTwoDigits

See #formatSpecifications, each of those has parse and format methods, like #format:yearTwoDigitsOn: and #parseYearTwoDigitsFrom:

Sven







  
That interesting. With the call of #formatSpecifications from...
    ZTimestampFormat class >> initialize
        "Initialize this class, to be redone every time #formatSpecifications changes."
        Formats := Dictionary newFromPairs: self formatSpecifications.
        FormatKeys := Formats keys sorted: [ :x :y | x size >= y size ]

it looks like the format specifications could almost be pluggable.  What if /Formats/ was instead an instance variable, such that my project could provide an extention method like this...
ZTimestampFormat class >> myFormatSpecifications
    ^ #(
        'YYYY'         yearFourDigits
        'YY'             yearTwoDigits
        'MM'            monthTwoDigits
        'M'            month
        'Month'    monthNameCapitalized
        'month'    monthNameLowercased
        'MONTH'    monthNameUppercased
        'Mth'            monthNameAbbreviatedCapitalized
        'mth'            monthNameAbbreviatedLowercased
        'MTH'            monthNameAbbreviatedUppercased
        'D'            day
        '_D'            dayTwoDigitsSpacePadded
        'DD'            dayTwoDigits
        'h'            hour12
        'hh'            hour12TwoDigits
        'HH'            hour24TwoDigits
        'PM'            daypartUppercased
        'pm'            daypartLowercased
        'm'            minute
        'mm'            minuteTwoDigits
        's'            second
        'ss'            secondTwoDigits
        'Z'            timeZoneZ
        '+00:00'    timeZone
        'UTC'            timeZoneAbbreviated
        'UTCLong'        timeZoneAbbreviatedLong
        'Weekday'    weekdayNameCapitalized
        'weekday'    weekdayNameLowercased
        'WEEKDAY'    weekdayNameUppercased
        'Wday'            weekdayNameAbbreviatedCapitalized
        'wday'            weekdayNameAbbreviatedLowercased
        'WDAY'            weekdayNameAbbreviatedUppercased )

so I could go something like...
(ZTimestampFormat withSpecification: #myFormatSpecification fromString: 'MM/DD/YY') format: Date today. => '09/03/14'

That would be coool!
cheers -ben

btw, I didn't understand how yearFull in this line...
        '02001'        yearFull
was different from yearFourDigits.
Reply | Threaded
Open this post in threaded view
|

Re: Date text converter/formatter

Esteban A. Maringolo
In reply to this post by Sven Van Caekenberghe-2
Esteban A. Maringolo


2014-09-02 17:46 GMT-03:00 Sven Van Caekenberghe <[hidden email]>:

>
> On 02 Sep 2014, at 21:39, Esteban A. Maringolo <[hidden email]> wrote:
>
>> Thank you. It is certainly better than the base parser.
>> But for formats I can't pass Date objects to #format:, I have to
>> convert them to ZTimestamp before.
>
> (ZTimestampFormat fromString: '2001/02/03') format: Date today.
>
> Can you give an example of what does not work for you ?

My own brain doesn't work.
I don't know what I did yesterday, but it works as expected now :)

| format |
format := (ZTimestampFormat fromString: '03/02/2001') createDate.
format parse: '03/09/2014'.
format format: Date today

The only thing I'd change is to throw a specific Exception instead of
an AssertionFailure.
But I'm handling parsing errors fine with AssertionFailure handlers anyway.

>> Curiosity #1: Why did you use an example date string instead of using
>> regular patterns like yyyy, dd, hh/hh24, etc?
>
> That is why the formatter/parser was written in the first place ;-) It is modelled after a Go standard library (http://golang.org/src/pkg/time/format.go) and some Ruby library I can't remember the name of. I implemented this as a proof of concept to see if/how it could be done.

Fair enough. :)


Thank you!

Reply | Threaded
Open this post in threaded view
|

Re: Date text converter/formatter

Sven Van Caekenberghe-2
In reply to this post by Ben Coman

On 03 Sep 2014, at 15:24, Ben Coman <[hidden email]> wrote:

> Sven Van Caekenberghe wrote:
>> Hi Sean,
>>
>> On 03 Sep 2014, at 00:32, Sean P. DeNigris
>> <[hidden email]>
>>  wrote:
>>  
>>
>>> Sven Van Caekenberghe-2 wrote
>>>    
>>>
>>>> Maybe you got the example and the input mixed up ?
>>>>      
>>>>
>>> Oh yeah, I did, but even the example in that case is ambiguous, no?
>>>
>>> (ZTimestampFormat fromString: '02/03/01 (16:05:06)')
>>>                parse: '10/10/10 (12:01:01)'.
>>>
>>> How does it decide whether it's American i.e. Feb 3rd, or European i.e. Mar 2nd?
>>>    
>>>
>>
>> No, it is not ambiguous. The positions in the pattern are not used to determine the meaning of the elements, only the values.
>>
>
> Okay, but its ambiguous in the sense that, at a glance, without knowing the legend (even though you provided it), at least Sean and myself got confused.  
>
> For me part of that confusion is that you said...
> >        1=year
> >        2=month
> >        3=dayInMonth
> >        4=hour (16 in 24 hour format)
> >        5=minute
> >        6=second
>
> but the example used
> 02=month
> 03=day

No, it is not confusing: the rule is from largest to smallest unit, thus year, month, day, hour, minute and second. Which is the ISO 8601 representation order BTW, making the most scientific sense IMHO.

> In either case, its harder to remember which magnitude an arbitrary index number refers, than using the usual mnemonics like this...
> yy=year
> mm=month
> mmm=month name
> d=day of month
> dd=zero padded day of month
> hh=12 hour
> HH=24 hour
> etc... and thats just off the top of my head.  I think most people are familiar with this.
>
> Alternatively, if you want to use numbers, the following would be more intuitive to anyone glancing at it without needing to know the legend.
> 99=year
> 12=month
> 31=day
> 24=24 hour
> 12=12 hour
> 60=minute
> ?=second.
> etc...
>
> btw, I missed the first part of the
>> For example, limited to date elements only:
>>
>> (ZTimestampFormat fromString: '02/03/01') format: Date today. => '09/03/14'
>>
>> (ZTimestampFormat fromString: '03/02/01') format: Date today. => '03/09/14'
>>
>> (ZTimestampFormat fromString: 'Feb 3, 2001') format: Date today. => 'Sep 3, 2014'
>>
>> (ZTimestampFormat fromString: '02-FEB-2001') format: Date today. => '09-SEP-2014'
>>
>> (ZTimestampFormat fromString: 'Saturday, Februari 3 ''01') format: Date today. =>  'Wednesday, September 3 ''14'
>>
>> The reference date is 20010203 which was a Saturday, the recognised elements for dates are:
>>
>> '2001' yearFourDigits
>> '01' yearTwoDigits
>> '02001' yearFull
>> '02' monthTwoDigits
>> '2' month
>> 'February' monthNameCapitalized
>> 'february' monthNameLowercased
>> 'FEBRUARY' monthNameUppercased
>> 'Feb' monthNameAbbreviatedCapitalized
>> 'feb' monthNameAbbreviatedLowercased
>> 'FEB' monthNameAbbreviatedUppercased
>> '3' day
>> '_3' dayTwoDigitsSpacePadded
>> '03' dayTwoDigits
>>
>> See #formatSpecifications, each of those has parse and format methods, like #format:yearTwoDigitsOn: and #parseYearTwoDigitsFrom:
>>
>> Sven
>>
>>
>>
>>
>>
>>
>>
>>  
>>
> That interesting. With the call of #formatSpecifications from...
>     ZTimestampFormat class >> initialize
>         "Initialize this class, to be redone every time #formatSpecifications changes."
>         Formats := Dictionary newFromPairs: self formatSpecifications.
>         FormatKeys := Formats keys sorted: [ :x :y | x size >= y size ]
>
> it looks like the format specifications could almost be pluggable.  What if /Formats/ was instead an instance variable, such that my project could provide an extention method like this...
> ZTimestampFormat class >> myFormatSpecifications
>     ^ #(
>         'YYYY'         yearFourDigits
>         'YY'             yearTwoDigits
>         'MM'            monthTwoDigits
>         'M'            month
>         'Month'    monthNameCapitalized
>         'month'    monthNameLowercased
>         'MONTH'    monthNameUppercased
>         'Mth'            monthNameAbbreviatedCapitalized
>         'mth'            monthNameAbbreviatedLowercased
>         'MTH'            monthNameAbbreviatedUppercased
>         'D'            day
>         '_D'            dayTwoDigitsSpacePadded
>         'DD'            dayTwoDigits
>         'h'            hour12
>         'hh'            hour12TwoDigits
>         'HH'            hour24TwoDigits
>         'PM'            daypartUppercased
>         'pm'            daypartLowercased
>         'm'            minute
>         'mm'            minuteTwoDigits
>         's'            second
>         'ss'            secondTwoDigits
>         'Z'            timeZoneZ
>         '+00:00'    timeZone
>         'UTC'            timeZoneAbbreviated
>         'UTCLong'        timeZoneAbbreviatedLong
>         'Weekday'    weekdayNameCapitalized
>         'weekday'    weekdayNameLowercased
>         'WEEKDAY'    weekdayNameUppercased
>         'Wday'            weekdayNameAbbreviatedCapitalized
>         'wday'            weekdayNameAbbreviatedLowercased
>         'WDAY'            weekdayNameAbbreviatedUppercased )
>
> so I could go something like...
> (ZTimestampFormat withSpecification: #myFormatSpecification fromString: 'MM/DD/YY') format: Date today. => '09/03/14'
>
> That would be coool!
> cheers -ben

Yes, making it totally pluggable, or at least provide both an example based one and a more classic one makes sense. I'll think about that. Good idea.

But the whole concept of the example is that it is easy to remember. Or so it should be ;-)

> btw, I didn't understand how yearFull in this line...
>         '02001'        yearFull
> was different from yearFourDigits.

Some people insist on the fact that using 4 digit years is wrong (http://longnow.org) ;-)

For printing, 2001 and 02001 are the same because there is a natural overflow, but for parsing this is not the case: 02001 means using all digits until a non-digit, while 2001 always takes 4, and 01 always takes 2.

BTW, these specs are not perfectly deterministic/symmetrical. There are too many date/time formats and conventions.


Reply | Threaded
Open this post in threaded view
|

Re: Date text converter/formatter

Sven Van Caekenberghe-2
In reply to this post by Esteban A. Maringolo

On 03 Sep 2014, at 15:44, Esteban A. Maringolo <[hidden email]> wrote:

> Esteban A. Maringolo
>
>
> 2014-09-02 17:46 GMT-03:00 Sven Van Caekenberghe <[hidden email]>:
>>
>> On 02 Sep 2014, at 21:39, Esteban A. Maringolo <[hidden email]> wrote:
>>
>>> Thank you. It is certainly better than the base parser.
>>> But for formats I can't pass Date objects to #format:, I have to
>>> convert them to ZTimestamp before.
>>
>> (ZTimestampFormat fromString: '2001/02/03') format: Date today.
>>
>> Can you give an example of what does not work for you ?
>
> My own brain doesn't work.
> I don't know what I did yesterday, but it works as expected now :)
>
> | format |
> format := (ZTimestampFormat fromString: '03/02/2001') createDate.
> format parse: '03/09/2014'.
> format format: Date today

OK

> The only thing I'd change is to throw a specific Exception instead of
> an AssertionFailure.
> But I'm handling parsing errors fine with AssertionFailure handlers anyway.

Yes, using #assert: was laziness in the prototyping phase, I try to improve that part.

>>> Curiosity #1: Why did you use an example date string instead of using
>>> regular patterns like yyyy, dd, hh/hh24, etc?
>>
>> That is why the formatter/parser was written in the first place ;-) It is modelled after a Go standard library (http://golang.org/src/pkg/time/format.go) and some Ruby library I can't remember the name of. I implemented this as a proof of concept to see if/how it could be done.
>
> Fair enough. :)
>
>
> Thank you!


Reply | Threaded
Open this post in threaded view
|

Re: Date text converter/formatter

Ben Coman
In reply to this post by Sven Van Caekenberghe-2
Sven Van Caekenberghe wrote:
On 03 Sep 2014, at 15:24, Ben Coman [hidden email] wrote:

  
Sven Van Caekenberghe wrote:
    
Hi Sean,

On 03 Sep 2014, at 00:32, Sean P. DeNigris 
[hidden email]
 wrote:
  

      
Sven Van Caekenberghe-2 wrote
    

        
Maybe you got the example and the input mixed up ?
      

          
Oh yeah, I did, but even the example in that case is ambiguous, no?

(ZTimestampFormat fromString: '02/03/01 (16:05:06)')
               parse: '10/10/10 (12:01:01)'. 

How does it decide whether it's American i.e. Feb 3rd, or European i.e. Mar 2nd?
    

        
No, it is not ambiguous. The positions in the pattern are not used to determine the meaning of the elements, only the values. 

      
Okay, but its ambiguous in the sense that, at a glance, without knowing the legend (even though you provided it), at least Sean and myself got confused.  

For me part of that confusion is that you said...
    
       1=year
       2=month
       3=dayInMonth
       4=hour (16 in 24 hour format)
       5=minute
       6=second
      
but the example used 
02=month
03=day
    

No, it is not confusing: the rule is from largest to smallest unit, thus year, month, day, hour, minute and second. Which is the ISO 8601 representation order BTW, making the most scientific sense IMHO.

  
In either case, its harder to remember which magnitude an arbitrary index number refers, than using the usual mnemonics like this...
yy=year
mm=month
mmm=month name
d=day of month
dd=zero padded day of month
hh=12 hour
HH=24 hour
etc... and thats just off the top of my head.  I think most people are familiar with this.

Alternatively, if you want to use numbers, the following would be more intuitive to anyone glancing at it without needing to know the legend.
99=year
12=month
31=day
24=24 hour 
12=12 hour
60=minute
?=second.
etc...

btw, I missed the first part of the 
    
For example, limited to date elements only:

(ZTimestampFormat fromString: '02/03/01') format: Date today. => '09/03/14'

(ZTimestampFormat fromString: '03/02/01') format: Date today. => '03/09/14'

(ZTimestampFormat fromString: 'Feb 3, 2001') format: Date today. => 'Sep 3, 2014'

(ZTimestampFormat fromString: '02-FEB-2001') format: Date today. => '09-SEP-2014'

(ZTimestampFormat fromString: 'Saturday, Februari 3 ''01') format: Date today. =>  'Wednesday, September 3 ''14'

The reference date is 20010203 which was a Saturday, the recognised elements for dates are:

'2001' yearFourDigits
'01' yearTwoDigits
'02001'	yearFull
'02' monthTwoDigits
'2' month
'February' monthNameCapitalized
'february' monthNameLowercased
'FEBRUARY' monthNameUppercased
'Feb' monthNameAbbreviatedCapitalized
'feb' monthNameAbbreviatedLowercased
'FEB' monthNameAbbreviatedUppercased
'3' day
'_3' dayTwoDigitsSpacePadded
'03' dayTwoDigits

See #formatSpecifications, each of those has parse and format methods, like #format:yearTwoDigitsOn: and #parseYearTwoDigitsFrom:

Sven







  

      
That interesting. With the call of #formatSpecifications from...
    ZTimestampFormat class >> initialize 
        "Initialize this class, to be redone every time #formatSpecifications changes."
        Formats := Dictionary newFromPairs: self formatSpecifications.
        FormatKeys := Formats keys sorted: [ :x :y | x size >= y size ]

it looks like the format specifications could almost be pluggable.  What if /Formats/ was instead an instance variable, such that my project could provide an extention method like this...
ZTimestampFormat class >> myFormatSpecifications
    ^ #(
        'YYYY'         yearFourDigits
        'YY'             yearTwoDigits
        'MM'            monthTwoDigits
        'M'            month
        'Month'    monthNameCapitalized
        'month'    monthNameLowercased
        'MONTH'    monthNameUppercased
        'Mth'            monthNameAbbreviatedCapitalized
        'mth'            monthNameAbbreviatedLowercased
        'MTH'            monthNameAbbreviatedUppercased
        'D'            day
        '_D'            dayTwoDigitsSpacePadded
        'DD'            dayTwoDigits
        'h'            hour12
        'hh'            hour12TwoDigits
        'HH'            hour24TwoDigits
        'PM'            daypartUppercased
        'pm'            daypartLowercased
        'm'            minute
        'mm'            minuteTwoDigits
        's'            second
        'ss'            secondTwoDigits
        'Z'            timeZoneZ
        '+00:00'    timeZone
        'UTC'            timeZoneAbbreviated
        'UTCLong'        timeZoneAbbreviatedLong
        'Weekday'    weekdayNameCapitalized
        'weekday'    weekdayNameLowercased
        'WEEKDAY'    weekdayNameUppercased
        'Wday'            weekdayNameAbbreviatedCapitalized
        'wday'            weekdayNameAbbreviatedLowercased
        'WDAY'            weekdayNameAbbreviatedUppercased )

so I could go something like...
(ZTimestampFormat withSpecification: #myFormatSpecification fromString: 'MM/DD/YY') format: Date today. => '09/03/14'

That would be coool!
cheers -ben
    

Yes, making it totally pluggable, or at least provide both an example based one and a more classic one makes sense. I'll think about that. Good idea.

But the whole concept of the example is that it is easy to remember. Or so it should be ;-)

  
btw, I didn't understand how yearFull in this line...
        '02001'        yearFull
was different from yearFourDigits.
    

Some people insist on the fact that using 4 digit years is wrong (http://longnow.org) ;-)
  

Thanks I understand. Now off-topic, I like this... "Our crowd curated library of long-term thinking will be filled with the best 3,500 volumes to restart civilization."
I've sometimes had the urge to write a book on how to restart civilization.  A sort of real-life optimum path to producing the pre-requisites to advance tech levels.  The sort of thing you keep under the bed that is no use until the day you need it...

For printing, 2001 and 02001 are the same because there is a natural overflow, but for parsing this is not the case: 02001 means using all digits until a non-digit, while 2001 always takes 4, and 01 always takes 2.

BTW, these specs are not perfectly deterministic/symmetrical. There are too many date/time formats and conventions.



  

Reply | Threaded
Open this post in threaded view
|

Re: Date text converter/formatter

stepharo
In reply to this post by Sven Van Caekenberghe-2
> That is why the formatter/parser was written in the first place ;-) It is modelled after a Go standard library (http://golang.org/src/pkg/time/format.go) and some Ruby library I can't remember the name of. I implemented this as a proof of concept to see if/how it could be done.
>
Hi sven and this is cool that you did it :)