Giter Club home page Giter Club logo

clj-time's Introduction

Build Status Dependencies Status Downloads Join the chat at https://gitter.im/clj-time/clj-time

clj-time

A date and time library for Clojure, wrapping the Joda Time library. DEPRECATED

Project Status

The Joda Time website says:

Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.

If you are using Java 8 or later, please use the built-in Java Time instead of Joda Time -- or look at clojure.java-time if you want a Clojure wrapper for that, or cljc.java-time for a thin Clojure(Script) wrapper, or juxt/tick for another cross-platform option. See Converting from Joda Time to java.time for more details about the similarities and differences between the two libraries.

Artifacts

clj-time artifacts are released to Clojars.

If you are using Maven, add the following repository definition to your pom.xml:

<repository>
  <id>clojars.org</id>
  <url>http://clojars.org/repo</url>
</repository>

The Most Recent Release

With Leiningen:

[clj-time "0.15.2"]

With Maven:

<dependency>
  <groupId>clj-time</groupId>
  <artifactId>clj-time</artifactId>
  <version>0.15.2</version>
</dependency>

Bugs and Enhancements

Please open issues against the official clj-time repo on Github. clj-time is a very thin wrapper around Joda Time. That means that if Joda Time has a "peculiar behavior", it's likely to be surfaced directly in clj-time as well. A good example of this is clj-time.format/unparse which simply calls Joda Time's .print method -- and if the date passed in happens to be nil, you silently get back the current date/time (many people would expect an exception!).

Mailing List

Please ask questions on the clj-time mailing list.

Usage

clj-time.core

The main namespace for date-time operations in the clj-time library is clj-time.core.

(require '[clj-time.core :as t])

Create a DateTime instance with date-time, specifying the year, month, day, hour, minute, second, and millisecond:

(t/date-time 1986 10 14 4 3 27 456)
=> #<DateTime 1986-10-14T04:03:27.456Z>

Less-significant fields can be omitted:

(t/date-time 1986 10 14)
=> #<DateTime 1986-10-14T00:00:00.000Z>

Get the current time with now and the start of the Unix epoch with epoch.

Once you have a date-time, use accessors like hour and second to access the corresponding fields:

(t/hour (t/date-time 1986 10 14 22))
=> 22

The date-time constructor always returns times in the UTC time zone. If you want a time with the specified fields in a different time zone, use from-time-zone:

(t/from-time-zone (t/date-time 1986 10 22) (t/time-zone-for-offset -2))
=> #<DateTime 1986-10-22T00:00:00.000-02:00>

If on the other hand you want a given absolute instant in time in a different time zone, use to-time-zone:

(t/to-time-zone (t/date-time 1986 10 22) (t/time-zone-for-offset -2))
=> #<DateTime 1986-10-21T22:00:00.000-02:00>

In addition to time-zone-for-offset, you can use the time-zone-for-id and default-time-zone functions and the utc Var to construct or get DateTimeZone instances.

If you only want a date with no time component, consider using the local-date and today functions. These return LocalDate instances that do not have time components (and thus don't suffer from timezone-related shifting).

(t/local-date 2013 3 20)
=> #<LocalDate 2013-03-20>

The functions equal?, after?, and before? determine the relative position of two DateTime instances:

(t/equal? (t/date-time 1986 10) (t/date-time 1986 10))
=> true
(t/after? (t/date-time 1986 10) (t/date-time 1986 9))
=> true
(t/before? (t/date-time 1986 9) (t/date-time 1986 10))
=> true

Often you will want to find a date some amount of time from a given date. For example, to find the time 1 month and 3 weeks from a given date-time:

(t/plus (t/date-time 1986 10 14) (t/months 1) (t/weeks 3))
=> #<DateTime 1986-12-05T00:00:00.000Z>

You can perform also minus operations

(t/minus (t/date-time 1986 10 14 6) (t/hours 2))
=> #<DateTime 1986-10-14T04:00:00.000Z>

An Interval is used to represent the span of time between two DateTime instances. Construct one using interval, then query them using within?, overlaps?, and abuts?

(t/within? (t/interval (t/date-time 1986) (t/date-time 1990))
              (t/date-time 1987))
=> true

The in-seconds and in-minutes functions can be used to describe intervals in the corresponding temporal units:

(t/in-minutes (t/interval (t/date-time 1986 10 2) (t/date-time 1986 10 14)))
=> 17280

The overlap function can be used to get an Interval representing the overlap between two intervals:

(t/overlap (t/interval (t/date-time 1986) (t/date-time 1990))
         (t/interval (t/date-time 1987) (t/date-time 1991)))
=> #<Interval 1987-01-01T00:00:00.000Z/1990-01-01T00:00:00.000Z>

today-at returns a moment in time at the given hour, minute and second on the current date UTC; not the current system date:

(t/today-at 12 00)
=> #<DateTime 2013-03-29T12:00:00.000Z>
(t/today-at 12 00 05)
=> #<DateTime 2013-03-29T12:00:05.000Z>

;; System clock says 11PM on 12/20/2016 UTC-5
(t/today-at 7 00 00)
=> #<DateTime 2016-12-21T7:00:00.000Z>

clj-time.format

If you need to parse or print date-times, use clj-time.format:

(require '[clj-time.format :as f])

Parsing and printing are controlled by formatters. You can either use one of the built in ISO8601 formatters or define your own, e.g.:

(def built-in-formatter (f/formatters :basic-date-time))
(def custom-formatter (f/formatter "yyyyMMdd"))

To see a list of available built-in formatters and an example of a date-time printed in their format:

(f/show-formatters)

Remember that mm is minutes, MM is months, ss is seconds and SS is milliseconds. You can find a complete list of patterns on the Joda Time website.

Once you have a formatter, parsing and printing are straightforward:

(f/parse custom-formatter "20100311")
=> #<DateTime 2010-03-11T00:00:00.000Z>
(f/unparse custom-formatter (t/date-time 2010 10 3))
=> "20101003"

To parse dates in multiple formats and format dates in just one format, you can do this:

(def multi-parser (f/formatter (t/default-time-zone) "YYYY-MM-dd" "YYYY/MM/dd"))

(f/unparse multi-parser (f/parse multi-parser "2012-02-01"))
=> "2012-02-01"

(f/unparse multi-parser (f/parse multi-parser "2012/02/01"))
=> "2012-02-01"

Note: Joda Time's .print method accepts a null date/time object and substitutes the current date/time, so (f/unparse my-fmt nil) will not throw an exception -- it will just silently return the current date/time!

clj-time.coerce

The namespace clj-time.coerce contains utility functions for coercing Joda DateTime instances to and from various other types:

(require '[clj-time.coerce :as c])

For example, to convert a Joda DateTime to and from a Java long:

(c/to-long (t/date-time 1998 4 25))
=> 893462400000
(c/from-long 893462400000)
=> #<DateTime 1998-04-25T00:00:00.000Z>

And by the magic of protocols you can pass in an isoformat string and get the unix epoch milliseconds:

(c/to-long "2013-08-01")
=> 1375315200000

There are also conversions to and from java.util.Date (to-date and from-date), java.sql.Date (to-sql-date and from-sql-date), java.sql.Timestamp (to-sql-time and from-sql-time) and several other types.

To support serialization to the ubiquitous EDN format, pr, prn etc. will serialize Joda DateTime in a tagged-literal format, that clojure.edn/read will deserialize. There is a data_readers.clj file, or if not loaded a data-readers var to use with clojure.edn.

(pr-str (t/date-time 1998 4 25))
=> "#clj-time/date-time \"1998-04-25T00:00:00.000Z\""
(require '[clojure.edn :as edn])
=> nil
(def x (edn/read-string {:readers c/data-readers}
                        (pr-str (t/date-time 1998 4 25))))
(type x)
=> org.joda.time.DateTime
x
=> #clj-time/date-time "1998-04-25T00:00:00.000Z"

clj-time.local

The namespace clj-time.local contains functions for working with local time without having to shift to/from utc, the preferred time zone of clj-time.core.

(require '[clj-time.local :as l])

Get the current local time with

(l/local-now)

Get a local date-time instance retaining the time fields with

(l/to-local-date-time obj)

The following all return 1986-10-14 04:03:27.246 with the local time zone.

(l/to-local-date-time (clj-time.core/date-time 1986 10 14 4 3 27 246))
(l/to-local-date-time "1986-10-14T04:03:27.246")
(l/to-local-date-time "1986-10-14T04:03:27.246Z")

The dynamic var *local-formatters* contains a map of local formatters for parsing and printing. It is initialized with all the formatters in clj-time.format localized.

to-local-date-time for strings uses *local-formatters* to parse.

Format an obj using a formatter in *local-formatters* corresponding to the format-key passed in with

(l/format-local-time (l/local-now) :basic-date-time)

clj-time.periodic

clj-time.periodic/periodic-seq returns an infinite sequence of instants separated by a time period starting with the given point in time:

(require '[clj-time.periodic :as p])
(require '[clj-time.core :as t])

;; returns 10 instants starting with current time separated
;; by 12 hours
(take 10 (p/periodic-seq (t/now) (t/hours 12)))

In particular, if you ask for a sequence of instants separated by a month, you will get dates where the month increases each time (rather than being, say, 30 days apart).

clj-time.predicates

clj-time.predicates comes with a set of handy predicates to check for common conditions. For instance:

(require '[clj-time.core :as t])
(require '[clj-time.predicates :as pr])
(pr/monday? (t/date-time 1999 9 9))
=> false

(pr/january? (t/date-time 2011 1 1))
=> true

(pr/weekend? (t/date-time 2014 1 26))
=> true

(pr/weekday? (t/date-time 2014 1 26))
=> false

(pr/last-day-of-month? (t/date-time 2014 1 26))
=> false

(pr/first-day-of-month? (t/date-time 2014 1 26))
=> false

clj-time.jdbc

clj-time.jdbc registers protocol extensions so you don’t have to use clj-time.coerce yourself to coerce to and from SQL timestamps.

From the REPL:

(require 'clj-time.jdbc)

In your project:

(ns my.neat.project
  (:require [clj-time.jdbc]))

; They're registered and ready to use.

Now you can use org.joda.time.DateTime objects when "writing" to the database in place of java.sql.Timestamp objects, and expect org.joda.time.DateTime objects when "reading" where you would have previously expected java.sql.Timestamp objects.

Development

Running the tests:

$ rm -f test/readme.clj && lein test-all

(assumes Leiningen 2.x)

Documentation

The complete API documentation is also available (codox generated).

License

Released under the MIT License: https://github.com/clj-time/clj-time/blob/master/MIT-LICENSE.txt

clj-time's People

Contributors

adomokos avatar alexbaranosky avatar aria42 avatar aviflax avatar bhaskarsaraogi avatar bitemyapp avatar cap10morgan avatar cgore avatar coltnz avatar davidsantiago avatar devn avatar drone29a avatar duelinmarkers avatar edtsech avatar firesofmay avatar gws avatar lummax avatar lunkdjedi avatar michaelklishin avatar mmcgrana avatar mpenet avatar mw10013 avatar pangloss avatar r0man avatar seancorfield avatar sfnelson avatar siscia avatar slr71 avatar thiagotnunes avatar vedang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

clj-time's Issues

Inconsistency between clj-time.coerce/{from, to}-sql-date

(clj-time.coerce/to-sql-date nil)
=> nil
(clj-time.coerce/from-sql-date nil)
=> NullPointerException

IMHO they should both return nil, or at least both an Exception.

If I get the green light I write the code that I am a little busy right now...

java.lang.NoClassDefFoundError: clj_time/core/DateTimeProtocol

Hi,

I am running into an error that is maddening and must have some kind of stupid explanation.

I created a simple test project repo to see if anybody else can reproduce: [https://github.com/arnaudsj/clj-time-break-case]

All I do is to run: lein repl and I get this:

$ lein repl Compiling myproject.core Exception in thread "main" java.lang.NoClassDefFoundError: clj_time/core/DateTimeProtocol at clj_time.coerce__init.load(Unknown Source) at clj_time.coerce__init.<clinit>(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:270) at clojure.lang.RT.loadClassForName(RT.java:2098) at clojure.lang.RT.load(RT.java:430) at clojure.lang.RT.load(RT.java:411) at clojure.core$load$fn__5018.invoke(core.clj:5530) at clojure.core$load.doInvoke(core.clj:5529) at clojure.lang.RestFn.invoke(RestFn.java:408) at clojure.core$load_one.invoke(core.clj:5336) at clojure.core$load_lib$fn__4967.invoke(core.clj:5375) at clojure.core$load_lib.doInvoke(core.clj:5374) at clojure.lang.RestFn.applyTo(RestFn.java:142) at clojure.core$apply.invoke(core.clj:619) at clojure.core$load_libs.doInvoke(core.clj:5413) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.core$apply.invoke(core.clj:619) at clojure.core$require.doInvoke(core.clj:5496) at clojure.lang.RestFn.invoke(RestFn.java:408) at myproject.core$loading__4910__auto__.invoke(core.clj:1) at myproject.core__init.load(Unknown Source) at myproject.core__init.<clinit>(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:270) at clojure.lang.RT.loadClassForName(RT.java:2098) at clojure.lang.RT.load(RT.java:430) at clojure.lang.RT.load(RT.java:411) at clojure.core$load$fn__5018.invoke(core.clj:5530) at clojure.core$load.doInvoke(core.clj:5529) at clojure.lang.RestFn.invoke(RestFn.java:408) at clojure.core$load_one.invoke(core.clj:5336) at clojure.core$load_lib$fn__4967.invoke(core.clj:5375) at clojure.core$load_lib.doInvoke(core.clj:5374) at clojure.lang.RestFn.applyTo(RestFn.java:142) at clojure.core$apply.invoke(core.clj:619) at clojure.core$load_libs.doInvoke(core.clj:5413) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.core$apply.invoke(core.clj:619) at clojure.core$require.doInvoke(core.clj:5496) at clojure.lang.RestFn.invoke(RestFn.java:408) at user$eval5.invoke(form-init4450441270712540651.clj:1) at clojure.lang.Compiler.eval(Compiler.java:6619) at clojure.lang.Compiler.eval(Compiler.java:6608) at clojure.lang.Compiler.eval(Compiler.java:6608) at clojure.lang.Compiler.load(Compiler.java:7064) at clojure.lang.Compiler.loadFile(Compiler.java:7020) at clojure.main$load_script.invoke(main.clj:294) at clojure.main$init_opt.invoke(main.clj:299) at clojure.main$initialize.invoke(main.clj:327) at clojure.main$null_opt.invoke(main.clj:362) at clojure.main$main.doInvoke(main.clj:440) at clojure.lang.RestFn.invoke(RestFn.java:421) at clojure.lang.Var.invoke(Var.java:419) at clojure.lang.AFn.applyToHelper(AFn.java:163) at clojure.lang.Var.applyTo(Var.java:532) at clojure.main.main(main.java:37) Caused by: java.lang.ClassNotFoundException: clj_time.core.DateTimeProtocol at java.net.URLClassLoader$1.run(URLClassLoader.java:366) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:425) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:358) ... 57 more Exception in thread "Thread-4" clojure.lang.ExceptionInfo: Subprocess failed {:exit-code 1} at clojure.core$ex_info.invoke(core.clj:4327) at leiningen.core.eval$fn__3532.invoke(eval.clj:226) at clojure.lang.MultiFn.invoke(MultiFn.java:231) at leiningen.core.eval$eval_in_project.invoke(eval.clj:326) at clojure.lang.AFn.applyToHelper(AFn.java:167) at clojure.lang.AFn.applyTo(AFn.java:151) at clojure.core$apply.invoke(core.clj:619) at leiningen.repl$server$fn__7443.invoke(repl.clj:201) at clojure.lang.AFn.applyToHelper(AFn.java:159) at clojure.lang.AFn.applyTo(AFn.java:151) at clojure.core$apply.invoke(core.clj:617) at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1788) at clojure.lang.RestFn.invoke(RestFn.java:425) at clojure.lang.AFn.applyToHelper(AFn.java:163) at clojure.lang.RestFn.applyTo(RestFn.java:132) at clojure.core$apply.invoke(core.clj:621) at clojure.core$bound_fn_STAR_$fn__4102.doInvoke(core.clj:1810) at clojure.lang.RestFn.invoke(RestFn.java:397) at clojure.lang.AFn.run(AFn.java:24) at java.lang.Thread.run(Thread.java:744)

Any ideas?

I am under OS X 10.9.2 and using the following leiningen/Oracle Java version:
Leiningen 2.3.4 on Java 1.7.0_51 Java HotSpot(TM) 64-Bit Server VM

I have tried everything I can think of, lein clean, blowing away ~/.m2 folder, reinstallingn leiningen, etc...

earliest, latest

I use these a lot, seem useful additions?

(defn earliest [& dts]
  (reduce (fn [dt1 dt2]
            (if (pos? (compare dt1 dt2))
              dt2
              dt1))
          dts))

(defn latest [& dts]
  (reduce (fn [dt1 dt2]
            (if (neg? (compare dt1 dt2))
              dt2
              dt1))
          dts))

in-seconds can't handle large intervals

I am getting this error when I try in-seconds with very large interval values.

user> (in-seconds (interval (now) (-> (*  3 1000) years from-now)))
ArithmeticException Value cannot fit in an int: 94670812800 org.joda.time.field.FieldUtils.safeToInt (FieldUtils.java:190)

Extend DateTimeProtocol with java.util.Date?

I am getting a java.util.Date returned from another library I'm using and want to compare it using clj-time methods, so in the first instance I used (from-date blah) everywhere I needed to convert between the two, however this is a little clunky and gets annoying quickly.

Then I realised I could extend DateTimeProtocol to just use (from-date this) internally and everything works as expected. Is there any reason this isn't done by default as part of the library to aid interop? Or is there some issue I've not noticed around losing timezone information or something like that?

(extend-protocol DateTimeProtocol
  java.util.Date
  (year [this] (.getYear (from-date this)))
  (month [this] (.getMonthOfYear (from-date this)))
  (day [this] (.getDayOfMonth (from-date this)))
  (day-of-week [this] (.getDayOfWeek (from-date this)))
  (hour [this] (.getHourOfDay (from-date this)))
  (minute [this] (.getMinuteOfHour (from-date this)))
  (sec [this] (.getSecondOfMinute (from-date this)))
  (milli [this] (.getMillisOfSecond (from-date this)))
  (after? [this #^ReadableInstant that] (.isAfter (from-date this) that))
  (before? [this #^ReadableInstant that] (.isBefore (from-date this) that))
  (plus- [this #^ReadablePeriod period] (.plus (from-date this) period))
  (minus- [this #^ReadablePeriod period] (.minus (from-date this) period)))

truncate function

There can be a function for truncation... i had to write my own for getting rid of the ms and it looks ugly, especially if the time has to be in local time:

(defn truncate-ms [dt]
   (t/to-time-zone
   (apply t/date-time
          (map #(% dt)
               [t/year t/month t/day t/hour t/minute t/sec]))
   (t/default-time-zone)))

something in the library that can work like this would be nice:

(truncate (local-now) days)

(milli) returning wrong number

Hi,
I'm trying to get the number of milliseconds related to the current date in this way:

(milli (now))

but I'm getting unreasonable numbers (like 45 which is definitely an incorrect number).
Is this an issue or am I doing the wrong thing?

Thanks,
Nico

in-msecs breaks in 0.3.3

I recently upgraded from 0.3.1 to 0.3.3 and noticed that the new implementation of in-msecs is broken, even for small intervals. In 0.3.1:

(use clj-time.core) ;; 0.3.1
(in-msecs (interval (date-time 2000 1) (date-time 2000 2)))
;=>  949363200000

0.3.3 breaks for the same call:

(use clj-time.core) ;; 0.3.3
(in-msecs (interval (date-time 2000 1) (date-time 2000 2)))

;; throws
;; Value cannot fit in an int: 2678400000
;;  [Thrown class java.lang.ArithmeticException]

The breakage occurs because 0.3.3 converts to a period first, while 0.3.1 goes straight to millis:

;; 0.3.1
(defn in-msecs [^Interval in]
  (.toDurationMillis in))

;; 0.3.3
(defn in-msecs [^Interval in]
  (.getMillis (.toPeriod in (millis))))

Would it be possible to move back to the old implementation, at least for milliseconds?

WARNING: extend already refers to: #'clojure.core/extend

My code:

(ns rollup
    (use [clojure.java.io :only [reader]])
    (use clj-time.core)
    (use clj-time.format)
    (:import (org.joda.time Hours Days Weeks)))

When I run my script, I get this message:

WARNING: extend already refers to: #'clojure.core/extend in namespace: rollup, being replaced by: #'clj-time.core/extend

I'm using Clojure 1.3.0 installed with Homebrew, on Java 1.6.0_29-b11-402-11M3527 on Mac OS X 10.7.2.

My project.clj:

(defproject rollups "0.0.1"
  :description "Exercises in writing time-window rollups in various languages"
  :dependencies [[org.clojure/clojure "1.3.0"]
                 [clj-time "0.3.4"]])

I installed the libs with lein install.

I run the script from bash, the first line is #!/usr/bin/env java -cp lib/* clojure.main

in-* interval functions could use toPeriod?

I looked for in-years but it isn't present. The obvious implementation would be:

(defn in-years [in] (.getYears (.toPeriod in (PeriodType/years))))

(suitably type hinted).

Given that, it would make sense to implement the other in-* functions in terms of .toPeriod.

Given clj-time provides (years n) - and similarly for months, weeks, days etc - perhaps add zero-argument versions that provide Period objects?

(defn years ([] (PeriodType/years)) ([n] (Period n)))
(defn in-years [in] (.getYears (.toPeriod in (years))))

Add support for Instant literals (introduced in Clojure 1.4)

I solved the problem for my own use case with the following:

(defmethod print-dup org.joda.time.DateTime
  [^org.joda.time.DateTime d out]
  (print-dup (.toDate d) out))

(defmethod print-method org.joda.time.DateTime
  [^org.joda.time.DateTime d out]
  (print-method (.toDate d) out))

If the above is a general solution I do not know.

Also the above seems work well with Clojure versions prior to version 1.4 because Clojure falls back to using .toString instead.

Some might find the following relevant reading:
http://stackoverflow.com/questions/17554560/how-to-print-time-as-inst

clj-time.periodic/periodic-seq handles months incorrectly

(require '[clj-time.periodic :as p] '[clj-time.core :as t])
(take 10 (p/periodic-seq (t/date-time 2014 1 30) (t/months 1)))
=> 2014-01-30, 2014-02-28, 2014-03-28, 2014-04-28, ...
;; while it should be:
;; 2014-01-30, 2014-02-28, 2014-03-30, 2014-04-30, ...

Better implementation:

(defn periodic-seq [start-time step-type step-size]
  (map #(t/plus start-time (step-type (* step-size %1)))
       (iterate inc 0)))

(take 10 (periodic-seq (t/date-time 2014 1 30) t/months 1))
=>  2014-01-30, 2014-02-28, 2014-03-30, 2014-04-30, ...

(take 10 (periodic-seq (t/date-time 2014 1 30) t/days 3))
=>  2014-01-30, 2014-02-02, 2014-02-05, 2014-02-08, ...

You may want to change periodic-seq parameters - pass interval (t/days 3) instead of separate arguments t/days and 3. But the function implementation needs to access the 3, I don't know how to extract it from interval object.

Generic Coercion

Is a generic coercion a good idea ? For instance within coerce.clj, something like:

;; Single protocol that convert a value to a Joda value
(defprotocol JodaCoercible
  (to-clj-time [x]))

(extend-protocol JodaCoercible
  java.lang.String
    (to-clj-time [x] (c/from-string x))
  org.joda.time.DateTime
    (to-clj-time [x] x)
  java.lang.Long
    (to-clj-time [x] (c/from-long x)))

and etc for Date or others.

I'd be happy to submit a patch / pull request if so

Code duplication in clj-time.coerce/from-string and clj-time.format/parse

I noticed this duplication and would like to point it out:

(defn parse
  "Returns a DateTime instance in the UTC time zone obtained by parsing the
   given string according to the given formatter."
  ([#^DateTimeFormatter fmt #^String s]
     (.parseDateTime fmt s))
  ([#^String s]
     (first
      (for [f (vals formatters)
            :let [d (try (parse f s) (catch Exception _ nil))]
            :when d] d))))
(defn from-string
  "return DateTime instance from string using
   formatters in clj-time.format, returning first
   which parses"
  [s]
  (first
   (for [f (vals time-fmt/formatters)
         :let [d (try (time-fmt/parse f s) (catch Exception _ nil))]
         :when d] d)))

I see a couple of options:

  1. Change the API. (Perhaps remove the single argument version of parse?)
  2. Factor out the shared behavior.

Get interval in ETA

Perhaps a way to get an interval back in ETA (0 years, 2 months, 28 days, 2 hours 5 minutes, 10 seconds)?

(readable (interval (date-time 1986 9 2 0 0 2) (date-time 1986 11 30 2 5 12)))

rfc822 formatter is wrong

hello

here is some snippet using rfc822 formatter:

=> (parse (formatters :rfc822) "Wed, 20 Nov 2013 09:57:08 GMT")
IllegalArgumentException Invalid format: "Wed, 20 Nov 2013 09:57:08 GMT" is malformed at "GMT"  org.joda.time.format.DateTimeFormatter.parseDateTime (DateTimeFormatter.java:866)
=> (parse (formatters :rfc822) "Mon, 02 Dec 2013 22:16:42 +0000")
#<DateTime 2013-12-02T22:16:42.000Z>

according to rfc both dates should be ok. pls see rfc here: http://www.ietf.org/rfc/rfc0822.txt

grep for 5.1. then see zone section.

thanks for developing clj-time :)
regards!

Misleading doc string or bug?

Found a bug in wait-for: CircleCI-Archived/wait-for#2

It was caused by trying to call . toStandardSeconds on the instance returned by (clj-time.core/secs 1).

According to the doc string this should return an instance of Period:

(defn secs
  "Given a number, returns a Period representing that many seconds.
   Without an argument, returns a PeriodType representing only seconds."
  ([]
     (PeriodType/seconds))
  ([#^Integer n]
     (Seconds/seconds n)))

Shouldn't the last line be:

(Period/seconds n)

From an api perspective that would make sense, since it would allow users to specify a period in there preferred time unit like in the wait-for library?

(wait-for {:sleep (time/secs 1)} ...)

(wait-for {:sleep (time/hours 1)} ...)

The same pattern can be found in weeks, months, hours etc. so maybe there is a good reason for this?

Please start a mailing list

I have a few functions related to date and time that I am extracting from my applications to move into Quartzite. It will incubate there for a while and I think some of them may be good fit for clj-time. However, I am not sure where to discuss this. The main Clojure mailing list is pretty high-volume and is not really suited for individual project contributions/issues.

So, it's time clj-time has its own mailing list.

Automatically promote minutes to hours to days

As I've been working with cli-time I've thought it would be nice to have time periods automatically promote, particularly when doing date/time math. Would this be a good/interesting/desired addition?

Date-time comparison semantic with time-zone-for-id versus time-zone-for-offset

I would expect the comparison on date-time to have a value semantic but it seems that equal instants are not compared equals when built with different timezone "constructors" (FixedDateTimeZone vs. CachedDateTimeZone):

(def a (t/from-time-zone (t/date-time 2012 4 1 6 35) (t/time-zone-for-id "Europe/Paris")))
; #<DateTime 2012-04-01T06:35:00.000+02:00>
(def b (t/from-time-zone (t/date-time 2012 4 1 6 35) (t/time-zone-for-offset 2)))
; #<DateTime 2012-04-01T06:35:00.000+02:00>
(= a b)
; false

Reflection Warnings

I’m checking one of my programs for reflection warnings, and a few came up for clj-time:

Reflection warning, clj_time/core.clj:98 - call to org.joda.time.DateMidnight ctor can't be resolved.
Reflection warning, clj_time/core.clj:187 - call to withZone can't be resolved.
Reflection warning, clj_time/core.clj:194 - call to withZoneRetainFields can't be resolved.
Reflection warning, clj_time/core.clj:274 - call to plus can't be resolved.
Reflection warning, clj_time/core.clj:282 - call to minus can't be resolved.

Add a yesterday function

I've often found myself creating a local function to compute yesterday.

I think this would be a useful addition to clj-time.core

Consider changing formatter to default to the default time zone

My program turned out to have a subtle bug because I assumed that formatter would create a DateTimeFormatter using the default time zone, just as using DateTimeFormat.forPattern() does. But it defaults to utc for some reason. Since clj-time is a “wrapper” for Joda Time, its behavior should be consistent with that of Joda Time, so that developers who are used to Joda Time’s semantics will be able to use it without introducing bugs.

Reflaction warnings

Reflection warning, clj_time/core.clj:577:10 - reference to field getDayOfMonth can't be resolved.

Let `formatter` accept formatters (and/or keywords)

This is an enhancement.

When writing formatters that accept several formats:

;; I'd like to write:
(formatter (formatters :year-month-day)))
;; => ClassCastException org.joda.time.format.DateTimeFormatter cannot
;; be cast to java.lang.String  clj-time.format/formatter

;; or even
(formatter :year-month-day) ; use built-in automatically

;; then I could say
(formatter (default-time-zone) :year-month-day :basic-date "YY/dd/MM")

The current code seems to try to avoid reflection, but I feel some is acceptable here, because hopefully a formatter will be constructed once and used many times.

print-dup

Hi all,

when I try to print-dup a joda time I get an error:

IllegalArgumentException No method in multimethod 'print-dup' for dispatch value: class org.joda.time.DateTime  clojure.lang.MultiFn.getFn (MultiFn.java:160)

I am pretty sure that is not a big issues to solve, but right now I don't have much time to spend on it.

If anybody is willing to fix it would be awesome.

For print-dup I mean this process here:

(binding [*print-dup* true]
  (pr (clj-time.core/now)))
IllegalArgumentException No method in multimethod 'print-dup' for dispatch value: class org.joda.time.DateTime  clojure.lang.MultiFn.getFn (MultiFn.java:160)
(binding [*print-dup* true]
  (pr {:a :b :c [1 2 3]}))
#=(clojure.lang.PersistentArrayMap/create {:a :b, :c [1 2 3]})
nil

Provide do-at

At the moment, your test-suite is importing utilize for the do-at function.

This seems like a useful function for anyone using clj-time who wants to test their stuff, but pulling in a year old dependency that just contains a bunch of unrelated functions seems a bit heavy (compared to clj-time, which is clearly still getting updates)

Would it be possible to pull do-at into clj-time, and expose it publically?

date-midnight coerce

(extend-protocol ICoerce
org.joda.time.DateMidnight
(to-date-time [date-time] date-time))

would be nice to have built-in.

thanks!

Parsing of duration/periods and converting them.

Hi,

I've just had to parse a time duration and I don't think this functionality is implemented in clj-time.

I'd suggest to have a namespace like

(clj-time.duration/parse "<iso 8601 duration string>")

A few annoying facts for Joda time:

  • Joda uses Period to mean what everybody else calls Duration.
  • Duration/parse only works for seconds and ms and will fail for anything else.
  • Period/parse will work for all ISO 8601 duration strings
  • A Period object's (.getMillis) doesn't actually tell you the number of ms in that period. It only gets the MS of the period which would be 0 for a period of 5s.
(.getMillis (Duration/parse "PT5.32S")) ; 5320
(.getMillis (Period/parse "PT5.32S")) ; 320
; Adding 1 Day:
(Duration/parse "P1DT5.32S") ; error
(Period/parse "P1DT5.32S") ; works
; "workaround":
(.getMillis (.toStandardDuration (Period/parse "PT12H30M5.345S"))) ; 45005345

I'm not sure what's the best way to incorporate this into clj-time? Just figured I'd drop it here for now.

Cheers

LICENSE file

Hi,

Can you include a specific LICENSE file in the project? The MIT license requires users to redistribute the license notice, but currently there isn't one, and the link to the MIT license in the readme is a link to a template that requires the author and copyright dates to be filled in.

clj-time.coerce fails to compile on Clojure 1.6.0

I'm not sure if this is new breakage or something strange about my environment, but when I try to require clj-time.coerce, I get a compilation error:

: jmglov@alhana; lein repl
nREPL server started on port 53061 on host 127.0.0.1
REPL-y 0.2.1
Clojure 1.6.0
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)

user=> (require '[clj-time.core :as dt])
nil
user=> (require '[clj-time.coerce :as c])

CompilerException java.lang.RuntimeException: Unable to resolve symbol: second in this context, compiling:(clj_time/coerce.clj:146:64) 

My project.clj looks like this:

(defproject foo "1.0-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.6.0"]
                 [cheshire "5.2.0"]
                 [clj-time "0.7.0"]
                 [compojure "1.1.6"]
                 [hiccup "1.0.5"]
                 [korma "0.3.0-RC6"]
                 [liberator "0.10.0"]
                 [mysql/mysql-connector-java "5.1.29"]
                 [org.clojure/tools.logging "0.2.6"]
                 [log4j "1.2.17" :exclusions [javax.mail/mail
                                              javax.jms/jms
                                              com.sun.jdmk/jmxtools
                                              com.sun.jmx/jmxri]]
                 [ring/ring-json "0.3.1"]
                 [ring-server "0.3.1"]]

  :plugins [[lein-ring "0.8.10"]
            [lein-beanstalk "0.2.7"]])

POM compile invalid for joda 2.1?

I cant seem to install clj-time from leinengen. to replicate the issue, create a new project with lein 1.7.1. to replicate

create a new project with lein

setup the project.clj as so:

(defproject clj-test "1.0.0-SNAPSHOT"
  :description "FIXME: write description"
  :dependencies [[org.clojure/clojure "1.4.0"]
                               [clj-time "0.4.3"]])

run lein deps

you should see:

[WARNING] POM for 'joda-time:joda-time:pom:2.1:compile' is invalid.

Its dependencies (if any) will NOT be available to the current build.
Copying 3 files to /Users/jed/Desktop/clj-test/lib
Exception in thread "main" java.lang.RuntimeException: java.util.zip.ZipException: error in opening zip file   (NO_SOURCE_FILE:0)
...

Improve naming consistency

Unfortunately, clj-time was designed to be used with :use and :require :refer :all and that's not a good way to use any library. The names are designed purposely to avoid shadowing and are thus inconsistent. We should change this.

For example, https://github.com/clj-time/clj-time/blob/master/src/clj_time/core.clj#L98-L99. We have sec and minute. Either minute should be renamed to min or sec should be renamed to second, which would (completely justifiably) shadow clojure.core/second and would a) be more consistent and b) discourage all inclusive referring.

Other issues:

  • in-secs vs in-minutes
  • in-msecs vs milli. It should be in-milli or milli should be msecs or something similar.

Parsing/unparsing confuses seconds and milliseconds

The milliseconds are used for seconds after parsing and seconds for millis after unparsing:

user=> (def fmt (formatter  "dd/MM/yyyy hh:mm:ss.s")) 
#'user/fmt
user=> (parse fmt "25/03/2009 06:03:00.20")
#<DateTime 2009-03-25T06:03:20.000Z>
user=> (unparse fmt (parse fmt "25/03/2009 06:03:00.20"))
"25/03/2009 06:03:20.20"

Possibly caused by the fact that ISO-8601 uses the same letter 's' for both seconds and milliseconds.

Why was "Duration" support removed?

Early in the beginning there was support for "Duration" but this was removed almost immediately. Any specific reason? Otherwise I propose that it should be added again.

reflection warning on lein check

reflection warning: clj_time/core.clj:604:10 - reference to field getDayOfMonth on java.lang.Object can't be resolved.
(using clj_time 0.7.0)
(using jre7)

Time for 0.7.0

0.6.0 was released about 6 months ago, I think it's time for 0.7.0.

Tagged reader literal for org.joda.time.DateTimes

I'm conscious that there's already a related issue (#93) asking to support the #inst literal, but I think this is different enough to warrant a separate issue!

Would it be preferable to serialise o.j.t.DateTimes with a different tag - e.g. #joda/date-time, #clj-time/date-time or equivalent? This would mean that they'd be correctly de-serialised back to DateTimes rather than j.u.Dates.

It'd be quite a simple change - the addition of a print-dup defmethod and a small data_readers.clj file, but would have the benefit that users of clj-time wouldn't ever have to worry about manually serialising DateTimes, or (as seems to be quite common in code that I come across) using Joda times in some parts of an application and conversions to/from j.u.Dates in other parts where serialisation is required.

Happy to submit a PR if you're ok with the approach. Likewise, if I'm doing something wrong in my usage of clj-time, please let me know!

Thanks for a really useful library :)

James

= does not return correct result across time zones

In the base Joda code, two DateTime objects are considered equal if they have the same basic millis value. This does not appear to carry over to clj-time:

(clj-time.coerce/to-long (time/date-time 2013 01 01 00)) = 1356998400000

(clj-time.coerce/to-long (time/from-time-zone (time/date-time 2013 01 01 01) (time/time-zone-for-offset 1))) = 1356998400000

(= (time/date-time 2013 01 01 00)
(time/from-time-zone (time/date-time 2013 01 01 01) (time/time-zone-for-offset 1)))
is false, but should be true

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.