Clojure

instant literal

Details

  • Type: Enhancement Enhancement
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Completed
  • Affects Version/s: None
  • Fix Version/s: Release 1.4
  • Component/s: None
  • Labels:
    None
  • Patch:
    Code and Test

Description

  1. 0871-instant-reader.patch
    04/Nov/11 12:59 PM
    9 kB
    Stuart Halloway
  2. CLJ-871-data-readers-1.patch
    13/Nov/11 6:53 PM
    8 kB
    Stuart Sierra
  3. CLJ-871-jre-only.diff
    12/Nov/11 3:10 PM
    17 kB
    Ben Smith-Mannschott
  4. CLJ-871-with-defaults.patch
    27/Jan/12 9:24 AM
    24 kB
    Stuart Sierra
  5. CLJ-915-instant-literals.diff
    21/Jan/12 9:11 AM
    19 kB
    Fogus

Activity

Hide
Steve Miner added a comment -

divisible? and indivisible? should be normal functions, not macros. They're used only in leap-year? – it would be pretty simple to use zero? and mod? directly there.

Show
Steve Miner added a comment - divisible? and indivisible? should be normal functions, not macros. They're used only in leap-year? – it would be pretty simple to use zero? and mod? directly there.
Hide
Stuart Sierra added a comment -

New patch CLJ-871-with-defaults.patch.

Fixes problems described in previous comment by adding default-data-readers which can be overridden by *data-readers*. Also adds documentation for *data-readers*.

Show
Stuart Sierra added a comment - New patch CLJ-871-with-defaults.patch. Fixes problems described in previous comment by adding default-data-readers which can be overridden by *data-readers*. Also adds documentation for *data-readers*.
Hide
Stuart Sierra added a comment - - edited

2 problems:

1. You can't specify an alternate inst reader in data_readers.clj. Doing so causes an opaque error when Clojure starts. This is a flaw in CLJ-890

2. *data-readers* is intended to be a map of symbols to Vars, not symbols to functions. This doesn't really matter.

Show
Stuart Sierra added a comment - - edited 2 problems: 1. You can't specify an alternate inst reader in data_readers.clj. Doing so causes an opaque error when Clojure starts. This is a flaw in CLJ-890 2. *data-readers* is intended to be a map of symbols to Vars, not symbols to functions. This doesn't really matter.
Hide
Fogus added a comment -

Oddly, I made another case for this. My bad. Attached is the updated patch based off of Ben's work. This patch is merged into the tagged literal feature as implemented in v1.4-alpha4. I also fixed a fence-post error and very minor doc problems. The parser currently defaults to constructing j.u.Date instances of the following form:

date-year   = 4DIGIT
date-month      = 2DIGIT  ; 01-12
date-mday       = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on
                         ; month/year
time-hour       = 2DIGIT  ; 00-23
time-minute     = 2DIGIT  ; 00-59
time-second     = 2DIGIT  ; 00-58, 00-59, 00-60 based on leap second
                         ; rules
time-secfrac    = '.' 1*DIGIT
time-numoffset  = ('+' / '-') time-hour ':' time-minute
time-offset     = 'Z' / time-numoffset

time-part            = time-hour [ ':' time-minute [ ':' time-second [time-secfrac] [time-offset] ] ]

timestamp       = date-year [ '-' date-month [ '-' date-mday [ 'T' time-part ] ] ]

Or in other words, RFC 3339 .

Show
Fogus added a comment - Oddly, I made another case for this. My bad. Attached is the updated patch based off of Ben's work. This patch is merged into the tagged literal feature as implemented in v1.4-alpha4. I also fixed a fence-post error and very minor doc problems. The parser currently defaults to constructing j.u.Date instances of the following form:
date-year   = 4DIGIT
date-month      = 2DIGIT  ; 01-12
date-mday       = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on
                         ; month/year
time-hour       = 2DIGIT  ; 00-23
time-minute     = 2DIGIT  ; 00-59
time-second     = 2DIGIT  ; 00-58, 00-59, 00-60 based on leap second
                         ; rules
time-secfrac    = '.' 1*DIGIT
time-numoffset  = ('+' / '-') time-hour ':' time-minute
time-offset     = 'Z' / time-numoffset

time-part            = time-hour [ ':' time-minute [ ':' time-second [time-secfrac] [time-offset] ] ]

timestamp       = date-year [ '-' date-month [ '-' date-mday [ 'T' time-part ] ] ]
Or in other words, RFC 3339 .
Hide
Stuart Sierra added a comment -

CLJ-871-data-readers-1.patch

An alternative approach. The dynamic Var *data-readers* maps keywords to reader functions, triggered by reader syntax #:keyword. Default #:instant reader takes a vector like [year month day hrs min sec ms], all components optional.

Pros: No string parsing. Extensible.

Cons: Clojure 1.2 used the #: syntax to print records.

Show
Stuart Sierra added a comment - CLJ-871-data-readers-1.patch An alternative approach. The dynamic Var *data-readers* maps keywords to reader functions, triggered by reader syntax #:keyword. Default #:instant reader takes a vector like [year month day hrs min sec ms], all components optional. Pros: No string parsing. Extensible. Cons: Clojure 1.2 used the #: syntax to print records.
Hide
Ben Smith-Mannschott added a comment - - edited

This patch implements instant literals of the form #@yyyy-mm-ddThh:mm:ss.fff+hh:mm using only classes available in the JRE.

clojure.instant provides instant-readers producing instances of three different JDK classes. These functions accept a string representing a timestamp See (doc clojure.instant/parse-timestamp) for details.

  • read-instant-date (java.util.Date)
  • read-instant-calendar (java.util.Calendar)
  • read-instant-timestamp (java.sql.Timestamp)

By default *instant-reader* is bound to read-instant-date.

print-method and print-dup are provided for all three types.

Rough bits include:

I'm not yet certain about the exact public interface of clojure.instant. It's clear that read-instant-* need to be visible. It also seems likely that parse-timestamp and validated could usefully support alternate implementations for *instant-reader*.

fixup-offset and fixup-nanos are ugly warts necessitated by Java's pathetic built-in support for dates and times (possibly exacerbated by my own misunderstandings of the same).

Unit tests are very basic. For example, I'm not testing validated except in the good case where everything is valid.

See also https://github.com/bpsm/clojure/commit/753f991151847df53d624f7c09b7113cd2321793


I've made a few trivial fixes to doc strings, visible on my github branch. Those changes will be included when I re-roll the patch it to incorporate any feedback.

Show
Ben Smith-Mannschott added a comment - - edited This patch implements instant literals of the form #@yyyy-mm-ddThh:mm:ss.fff+hh:mm using only classes available in the JRE. clojure.instant provides instant-readers producing instances of three different JDK classes. These functions accept a string representing a timestamp See (doc clojure.instant/parse-timestamp) for details.
  • read-instant-date (java.util.Date)
  • read-instant-calendar (java.util.Calendar)
  • read-instant-timestamp (java.sql.Timestamp)
By default *instant-reader* is bound to read-instant-date. print-method and print-dup are provided for all three types. Rough bits include: I'm not yet certain about the exact public interface of clojure.instant. It's clear that read-instant-* need to be visible. It also seems likely that parse-timestamp and validated could usefully support alternate implementations for *instant-reader*. fixup-offset and fixup-nanos are ugly warts necessitated by Java's pathetic built-in support for dates and times (possibly exacerbated by my own misunderstandings of the same). Unit tests are very basic. For example, I'm not testing validated except in the good case where everything is valid. See also https://github.com/bpsm/clojure/commit/753f991151847df53d624f7c09b7113cd2321793
I've made a few trivial fixes to doc strings, visible on my github branch. Those changes will be included when I re-roll the patch it to incorporate any feedback.
Hide
Rich Hickey added a comment -

> UTC at the door.

No. Offsets are not localization, just arithmetic.

>idiom for dynamically loading code based on whether Joda on classpath

We'll need more explicit mechanisms for determining the programmatic representation. Dynamic Joda is just to avoid Joda as hard implementation dep.

> People using ant will have to configure path locally to include Joda.

People using ant = me.

Show
Rich Hickey added a comment - > UTC at the door. No. Offsets are not localization, just arithmetic. >idiom for dynamically loading code based on whether Joda on classpath We'll need more explicit mechanisms for determining the programmatic representation. Dynamic Joda is just to avoid Joda as hard implementation dep. > People using ant will have to configure path locally to include Joda. People using ant = me.
Hide
Aaron Brooks added a comment -

It seems like it would be nice to have time-delta literals as well. My usage cases deal more often with time-deltas applied as intervals or offsets in time. I presume the current scheme doesn't allow for that but could be adjusted. Is that outside of the scope of this discussion?

Show
Aaron Brooks added a comment - It seems like it would be nice to have time-delta literals as well. My usage cases deal more often with time-deltas applied as intervals or offsets in time. I presume the current scheme doesn't allow for that but could be adjusted. Is that outside of the scope of this discussion?
Hide
Kevin Downey added a comment -

dates should always be read and printed as UTC

Show
Kevin Downey added a comment - dates should always be read and printed as UTC
Hide
Kevin Downey added a comment -

using a bindable var for a read time setting is kind of a drag stuff like:

(binding [*instant-reader* some-other-instant-reader]
#@2011-11-04T14:42Z)

will not have the desired effect, so then what are the use cases for the bindable var? should the repl bind it? should the compiler?

Show
Kevin Downey added a comment - using a bindable var for a read time setting is kind of a drag stuff like: (binding [*instant-reader* some-other-instant-reader] #@2011-11-04T14:42Z) will not have the desired effect, so then what are the use cases for the bindable var? should the repl bind it? should the compiler?
Hide
Stuart Halloway added a comment -

I have tested patch locally with no Joda, 1.6.2 Joda, and 2.0 Joda. All work as intended in simple invocations.

Seeking feedback on

  • UTC at the door. Goal is to stay out of localization business. Is that a good goal, and is that the right way to achieve it?
  • idiom for dynamically loading code based on whether Joda on classpath
  • idiom for conveying maven classpath into the ant part of the build. People using ant will have to configure path locally to include Joda.
Show
Stuart Halloway added a comment - I have tested patch locally with no Joda, 1.6.2 Joda, and 2.0 Joda. All work as intended in simple invocations. Seeking feedback on
  • UTC at the door. Goal is to stay out of localization business. Is that a good goal, and is that the right way to achieve it?
  • idiom for dynamically loading code based on whether Joda on classpath
  • idiom for conveying maven classpath into the ant part of the build. People using ant will have to configure path locally to include Joda.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: