elm-community / elm-time Goto Github PK
View Code? Open in Web Editor NEWA pure Elm date and time library.
Home Page: http://package.elm-lang.org/packages/elm-community/elm-time/latest
License: BSD 3-Clause "New" or "Revised" License
A pure Elm date and time library.
Home Page: http://package.elm-lang.org/packages/elm-community/elm-time/latest
License: BSD 3-Clause "New" or "Revised" License
I believe the difference between
"2017-12-11T23:30:00+09:00" and
"2017-12-12T09:30:00+09:00"
is less than 1 day, but delta
says it is not.
dates =
{ d1 = fromISO8601 "2017-12-11T23:30:00+09:00"
, d2 = fromISO8601 "2017-12-12T08:30:00+09:00"
, d3 = fromISO8601 "2017-12-12T09:30:00+09:00"
}
fromISO8601 : String -> DateTime
fromISO8601 s =
case DateTime.fromISO8601 s of
Ok dt ->
dt
Err e ->
Debug.crash e
suite : Test
suite =
describe "DateTime"
[ test "d2 - d1 should be less than 1 day" <|
\_ ->
DateTime.delta dates.d2 dates.d1
|> Debug.log "d2 - d1"
|> .days
|> Expect.equal 0
, test "d3 - d1 should be still less than 1 day" <|
\_ ->
DateTime.delta dates.d3 dates.d1
|> Debug.log "d3 - d1"
|> .days
|> Expect.equal 0
]
Running 2 tests. To reproduce these results, run: elm-test --fuzz 100 --seed 773854204
d2 - d1: { years = 0, months = 0, days = 0, hours = 9, minutes = 540, seconds = 32400, milliseconds = 32400000 }
d3 - d1: { years = 0, months = 0, days = 1, hours = 10, minutes = 600, seconds = 36000, milliseconds = 36000000 }
↓ Example
↓ DateTime
✗ d3 - d1 should be still less than day
1
╷
│ Expect.equal
╵
0
Is this a bug?
As I understand it, ISO 1601 considers the separators in dates (-) and times (:) optional. Negative offsets can also be indicated by minus '-' or a hyphen '−'.
elm-time's fromISO8601
will fail to parse a string without separators, or one using a hyphen to indicate a negative UTC offset.
I'd open a PR, but I'm unable to get elm-test to run. The best I can do right now is provide a few examples here: https://ellie-app.com/3t6yxCjFpbma1/1
As a point of reference, I discovered this attempting to parse dates from JIRA's API, which do not contain an offset separator (2017-04-28T14:37:51.887-0400), so there's at least one significant API in the wild that this causes issues for.
References:
https://www.cs.tut.fi/~jkorpela/iso8601.html#sep
https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC
When using the Time.Date.fromISO8601
an error is thrown for a correct date. The same is true in reverse as well. When generating an ISO8601 string from the date 0001-01-01 a non ISO8601 string is returned.
Example:
> import Time.Date
> Time.Date.fromISO8601 "0001-01-01"
Err "Errors encountered at position 1: expected \"-\""
: Result.Result String Time.Date.Date
> Time.Date.date 1 1 1 |> Time.Date.toISO8601
"1-01-01" : String
Referencing the README:
Use date
to construct Date
values. If given invalid values for
the month and day, they are both clamped and the nearest valid date is
returned.
This is wrong on the basis of the #create
function is doing two things:
This would be tolerable if there was any other way to create the object, but unfortunately there isn't. Hence, in my mind the #create
function is broken, and if I want to use this module, I have to write a wrapper around this class. I will probably instead fork the module, modify it, and then publish it as a "better" competitor. As the maintainer, I say #ugh
Here's my suggested solution that still allows clamping:
#create_clamped
, that will do exactly that, AND the name of the function explains what it is doing.Everybody wins.
Hi, I have a problem with incorrect dates generated in my forms and I have found the problem is in toISO8601
function, it skips the milliseconds part of the date.
See this: https://runelm.io/c/3cr
Time.DateTime.fromISO8601 "2017-04-22T19:05:31.040Z"
|> Result.map Time.DateTime.toISO8601
|> Result.withDefault ""
input: 2017-04-22T19:05:31.040Z
output: 2017-04-22T19:05:31Z
1970-01-01T00:00:00.000Z (this is how dateObj.toISOString()
works)
Err "Errors encountered at position 19: expected \"Z\" or expected an integer"
1970-01-01T00:00:00Z
Ok (DateTime { date = Date { year = 1970, month = 1, day = 1 }, offset = 0 })
Workaround:
DateTime.fromISO8601 <| Regex.replace Regex.All (regex "[.]000Z") (\_ -> "Z") str
Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
It would be great that elm-time could give me the beginning of a day in a particular timezone
This is what I'm doing now. based on a reference time and an offset
beginningOfDay : Int -> Time -> DT.DateTime
beginningOfDay offset referenceTime =
referenceTime
|> DT.fromTimestamp
|> DT.addMilliseconds -offset
|> DT.setHour 0
|> DT.setMinute 0
|> DT.setSecond 0
|> DT.addMilliseconds offset
This is a request to implement a dayDiff
or dayDelta
function that would return the number of days between 2 dates.
This fails because it's expecting the "Z" to be after "03:56:12"
DT.fromISO8601 "2016-11-14T03:56:12.123Z"
Err "Errors encountered at position 19: expected "Z" or expected an integer"
: Result.Result String Time.DateTime.DateTime
Hello!
Currently documentation for DateTime.zero
mention record updates for the DateTimeData
.
This is a bit weird since DateTimeData
is not part of a public interface. So to figure out what you can update there, you need to check source code for it. By reading the code I assume you want to keep it internal.
What about removing DateTime.dateTime
function and making DateTime.zero
return DateTime
? This way nothing gets exposed and the previous behavior is still possible with functions like setYear
or setMonth
.
Examples from the readme will then change like this:
-- OLD
dateTime { zero | year = 2016 }
-- NEW
zero |> setYear 2016
I think that this will follow Elm idea of "one way to do thing" (now you can actually use both ways) pretty nicely. Also with current compiler behavior it is inconvenient to use DateTime.zero
if you use qualified imports - { DateTime.zero | year = 2016 }
won't work.
Would be happy to make a PR with the change if it makes sense.
What do you think?
Hello!
thanks for the awesome package! any update for elm 0.19?
Sometimes, I find myself writing a function to generate a list of dates between two given dates, like this:
dateRange : Date -> Date -> List Date
dateRange firstDate lastDate =
case Date.compare firstDate lastDate of
GT ->
[]
_ ->
firstDate :: dateRange (Date.addDays 1 firstDate) lastDate
With the available library functions addMonths
, addHours
, addMinutes
, etc.., the range
function can be generalised to create ranges for different intervals (months, hours, minutes, etc...).
Would you consider adding such a function to the elm-time
library?
exemple of times
"22:00:00Z"
"00:00+02:00"
Which could be translated to date at 1970
In the README, there's this section:
...
addDays
can be used to add an exact number of days to a Date
.
addYears
and addMonths
add a relative number of years and months
to a date. If the target date is invalid, these functions continually
subtract one day until a valid date is found.
There is no need to clamp. Other packages I use (in Ruby for example), simply add into the following month or subtract from the previous month(s) as necessary.
Hence, here's how they would work:
--- Spill over into following month
> date 1992 1 31
| |> Date.addDays 1
| |> Date.toISO8601
"1993-02-01" : String
-- Back up to previous month
> date 1992 2 1
| |> Date.addDays -1
| |> Date.toISO8601
"1993-01-31" : String
-- Use length of spilled-into month as length for each month
> date 1992 1 31
| |> Date.addMonths 3
| |> Date.toISO8601
"1992-04-30" : String
--- Use average of 30 days per month:
> date 1992 1 1
| |> Date.addDays (3 * 30)
| |> Date.toISO8601
"1992-03-31" : String
I have a working pure-elm implementation of (Julian) dayOfWeek, based on this:
http://stackoverflow.com/questions/6054016/c-program-to-find-day-of-week-given-date#6054071
Would you be interested in adding this to elm-time ? I would need to add some tests, which seems a bit challenging but maybe there's a test suite for this kind of thing out there I could steal.
The other question is, if so, would you want to use elm-core's Date.Day type for compatibility, or redefine it?
At least temporarily (or permanently) address concerns in #49
This library supports converting to/from ISO 8601, but does not support one of the features I need, which is indicated in the Wikipedia article describing the standard.
I should be able to set the time to either 00:00 or 24:00, depending on whether the time is meant to indicate the beginning or the end of a day. Currently the library clamps to 23 hours. It would be nice for this limit to be increased to 24. Note that the time would still be equivalent to 00:00 of the next day.
Hello,
the toString
representation of ZonedDateTime is a huge amount of text. It looks like each and every instance keeps the time zone data. It's getting painful when debugging.
It would be great if the instances of ZonedDateTime (or TimeZone?) did not hold everything within.
Suggesion:
Maybe ZoneId
could be created to replace TimeZone
embedded in ZonedDateTime
?
A sample of
zonedDateTime
(europe_warsaw ())
{ zero | year = 2017, month = 2, day = 27, hour = 23 }
|> toString
ZonedDateTime { timeZone = TimeZone { name = "Europe/Warsaw", spans = [{ from = -Infinity, until = -1717032240000, abbreviation = "WMT", offset = -5040000 },{ from = -1717032240000, until = -1693706400000, abbreviation = "CET", offset = -3600000 },{ from = -1693706400000, until = -1680483600000, abbreviation = "CEST", offset = -7200000 },{ from = -1680483600000, until = -1663455600000, abbreviation = "CET", offset = -3600000 },{ from = -1663455600000, until = -1650150000000, abbreviation = "CEST", offset = -7200000 },{ from = -1650150000000, until = -1632006000000, abbreviation = "CET", offset = -3600000 },{ from = -1632006000000, until = -1618700400000, abbreviation = "CEST", offset = -7200000 },{ from = -1618700400000, until = -1600473600000, abbreviation = "EET", offset = -7200000 },{ from = -1600473600000, until = -1587168000000, abbreviation = "EEST", offset = -10800000 },{ from = -1587168000000, until = -1501725600000, abbreviation = "EET", offset = -7200000 },{ from = -1501725600000, until = -931734000000, abbreviation = "CET", offset = -3600000 },{ from = -931734000000, until = -857257200000, abbreviation = "CEST", offset = -7200000 },{ from = -857257200000, until = -844556400000, abbreviation = "CET", offset = -3600000 },{ from = -844556400000, until = -828226800000, abbreviation = "CEST", offset = -7200000 },{ from = -828226800000, until = -812502000000, abbreviation = "CET", offset = -3600000 },{ from = -812502000000, until = -796608000000, abbreviation = "CEST", offset = -7200000 },{ from = -796608000000, until = -778726800000, abbreviation = "CET", offset = -3600000 },{ from = -778726800000, until = -762660000000, abbreviation = "CEST", offset = -7200000 },{ from = -762660000000, until = -748486800000, abbreviation = "CET", offset = -3600000 },{ from = -748486800000, until = -733273200000, abbreviation = "CEST", offset = -7200000 },{ from = -733273200000, until = -715215600000, abbreviation = "CET", offset = -3600000 },{ from = -715215600000, until = -701910000000, abbreviation = "CEST", offset = -7200000 },{ from = -701910000000, until = -684975600000, abbreviation = "CET", offset = -3600000 },{ from = -684975600000, until = -670460400000, abbreviation = "CEST", offset = -7200000 },{ from = -670460400000, until = -654130800000, abbreviation = "CET", offset = -3600000 },{ from = -654130800000, until = -639010800000, abbreviation = "CEST", offset = -7200000 },{ from = -639010800000, until = -397094400000, abbreviation = "CET", offset = -3600000 },{ from = -397094400000, until = -386812800000, abbreviation = "CEST", offset = -7200000 },{ from = -386812800000, until = -371088000000, abbreviation = "CET", offset = -3600000 },{ from = -371088000000, until = -355363200000, abbreviation = "CEST", offset = -7200000 },{ from = -355363200000, until = -334195200000, abbreviation = "CET", offset = -3600000 },{ from = -334195200000, until = -323308800000, abbreviation = "CEST", offset = -7200000 },{ from = -323308800000, until = -307584000000, abbreviation = "CET", offset = -3600000 },{ from = -307584000000, until = -291859200000, abbreviation = "CEST", offset = -7200000 },{ from = -291859200000, until = -271296000000, abbreviation = "CET", offset = -3600000 },{ from = -271296000000, until = -260409600000, abbreviation = "CEST", offset = -7200000 },{ from = -260409600000, until = -239846400000, abbreviation = "CET", offset = -3600000 },{ from = -239846400000, until = -228960000000, abbreviation = "CEST", offset = -7200000 },{ from = -228960000000, until = -208396800000, abbreviation = "CET", offset = -3600000 },{ from = -208396800000, until = -197510400000, abbreviation = "CEST", offset = -7200000 },{ from = -197510400000, until = -176342400000, abbreviation = "CET", offset = -3600000 },{ from = -176342400000, until = -166060800000, abbreviation = "CEST", offset = -7200000 },{ from = -166060800000, until = 228873600000, abbreviation = "CET", offset = -3600000 },{ from = 228873600000, until = 243993600000, abbreviation = "CEST", offset = -7200000 },{ from = 243993600000, until = 260323200000, abbreviation = "CET", offset = -3600000 },{ from = 260323200000, until = 276048000000, abbreviation = "CEST", offset = -7200000 },{ from = 276048000000, until = 291772800000, abbreviation = "CET", offset = -3600000 },{ from = 291772800000, until = 307497600000, abbreviation = "CEST", offset = -7200000 },{ from = 307497600000, until = 323827200000, abbreviation = "CET", offset = -3600000 },{ from = 323827200000, until = 338947200000, abbreviation = "CEST", offset = -7200000 },{ from = 338947200000, until = 354672000000, abbreviation = "CET", offset = -3600000 },{ from = 354672000000, until = 370396800000, abbreviation = "CEST", offset = -7200000 },{ from = 370396800000, until = 386121600000, abbreviation = "CET", offset = -3600000 },{ from = 386121600000, until = 401846400000, abbreviation = "CEST", offset = -7200000 },{ from = 401846400000, until = 417571200000, abbreviation = "CET", offset = -3600000 },{ from = 417571200000, until = 433296000000, abbreviation = "CEST", offset = -7200000 },{ from = 433296000000, until = 449020800000, abbreviation = "CET", offset = -3600000 },{ from = 449020800000, until = 465350400000, abbreviation = "CEST", offset = -7200000 },{ from = 465350400000, until = 481075200000, abbreviation = "CET", offset = -3600000 },{ from = 481075200000, until = 496800000000, abbreviation = "CEST", offset = -7200000 },{ from = 496800000000, until = 512524800000, abbreviation = "CET", offset = -3600000 },{ from = 512524800000, until = 528249600000, abbreviation = "CEST", offset = -7200000 },{ from = 528249600000, until = 543974400000, abbreviation = "CET", offset = -3600000 },{ from = 543974400000, until = 559699200000, abbreviation = "CEST", offset = -7200000 },{ from = 559699200000, until = 575427600000, abbreviation = "CET", offset = -3600000 },{ from = 575427600000, until = 591152400000, abbreviation = "CEST", offset = -7200000 },{ from = 591152400000, until = 606877200000, abbreviation = "CET", offset = -3600000 },{ from = 606877200000, until = 622602000000, abbreviation = "CEST", offset = -7200000 },{ from = 622602000000, until = 638326800000, abbreviation = "CET", offset = -3600000 },{ from = 638326800000, until = 654656400000, abbreviation = "CEST", offset = -7200000 },{ from = 654656400000, until = 670381200000, abbreviation = "CET", offset = -3600000 },{ from = 670381200000, until = 686106000000, abbreviation = "CEST", offset = -7200000 },{ from = 686106000000, until = 701830800000, abbreviation = "CET", offset = -3600000 },{ from = 701830800000, until = 717555600000, abbreviation = "CEST", offset = -7200000 },{ from = 717555600000, until = 733280400000, abbreviation = "CET", offset = -3600000 },{ from = 733280400000, until = 749005200000, abbreviation = "CEST", offset = -7200000 },{ from = 749005200000, until = 764730000000, abbreviation = "CET", offset = -3600000 },{ from = 764730000000, until = 780454800000, abbreviation = "CEST", offset = -7200000 },{ from = 780454800000, until = 796179600000, abbreviation = "CET", offset = -3600000 },{ from = 796179600000, until = 811904400000, abbreviation = "CEST", offset = -7200000 },{ from = 811904400000, until = 828234000000, abbreviation = "CET", offset = -3600000 },{ from = 828234000000, until = 846378000000, abbreviation = "CEST", offset = -7200000 },{ from = 846378000000, until = 859683600000, abbreviation = "CET", offset = -3600000 },{ from = 859683600000, until = 877827600000, abbreviation = "CEST", offset = -7200000 },{ from = 877827600000, until = 891133200000, abbreviation = "CET", offset = -3600000 },{ from = 891133200000, until = 909277200000, abbreviation = "CEST", offset = -7200000 },{ from = 909277200000, until = 922582800000, abbreviation = "CET", offset = -3600000 },{ from = 922582800000, until = 941331600000, abbreviation = "CEST", offset = -7200000 },{ from = 941331600000, until = 954032400000, abbreviation = "CET", offset = -3600000 },{ from = 954032400000, until = 972781200000, abbreviation = "CEST", offset = -7200000 },{ from = 972781200000, until = 985482000000, abbreviation = "CET", offset = -3600000 },{ from = 985482000000, until = 1004230800000, abbreviation = "CEST", offset = -7200000 },{ from = 1004230800000, until = 1017536400000, abbreviation = "CET", offset = -3600000 },{ from = 1017536400000, until = 1035680400000, abbreviation = "CEST", offset = -7200000 },{ from = 1035680400000, until = 1048986000000, abbreviation = "CET", offset = -3600000 },{ from = 1048986000000, until = 1067130000000, abbreviation = "CEST", offset = -7200000 },{ from = 1067130000000, until = 1080435600000, abbreviation = "CET", offset = -3600000 },{ from = 1080435600000, until = 1099184400000, abbreviation = "CEST", offset = -7200000 },{ from = 1099184400000, until = 1111885200000, abbreviation = "CET", offset = -3600000 },{ from = 1111885200000, until = 1130634000000, abbreviation = "CEST", offset = -7200000 },{ from = 1130634000000, until = 1143334800000, abbreviation = "CET", offset = -3600000 },{ from = 1143334800000, until = 1162083600000, abbreviation = "CEST", offset = -7200000 },{ from = 1162083600000, until = 1174784400000, abbreviation = "CET", offset = -3600000 },{ from = 1174784400000, until = 1193533200000, abbreviation = "CEST", offset = -7200000 },{ from = 1193533200000, until = 1206838800000, abbreviation = "CET", offset = -3600000 },{ from = 1206838800000, until = 1224982800000, abbreviation = "CEST", offset = -7200000 },{ from = 1224982800000, until = 1238288400000, abbreviation = "CET", offset = -3600000 },{ from = 1238288400000, until = 1256432400000, abbreviation = "CEST", offset = -7200000 },{ from = 1256432400000, until = 1269738000000, abbreviation = "CET", offset = -3600000 },{ from = 1269738000000, until = 1288486800000, abbreviation = "CEST", offset = -7200000 },{ from = 1288486800000, until = 1301187600000, abbreviation = "CET", offset = -3600000 },{ from = 1301187600000, until = 1319936400000, abbreviation = "CEST", offset = -7200000 },{ from = 1319936400000, until = 1332637200000, abbreviation = "CET", offset = -3600000 },{ from = 1332637200000, until = 1351386000000, abbreviation = "CEST", offset = -7200000 },{ from = 1351386000000, until = 1364691600000, abbreviation = "CET", offset = -3600000 },{ from = 1364691600000, until = 1382835600000, abbreviation = "CEST", offset = -7200000 },{ from = 1382835600000, until = 1396141200000, abbreviation = "CET", offset = -3600000 },{ from = 1396141200000, until = 1414285200000, abbreviation = "CEST", offset = -7200000 },{ from = 1414285200000, until = 1427590800000, abbreviation = "CET", offset = -3600000 },{ from = 1427590800000, until = 1445734800000, abbreviation = "CEST", offset = -7200000 },{ from = 1445734800000, until = 1459040400000, abbreviation = "CET", offset = -3600000 },{ from = 1459040400000, until = 1477789200000, abbreviation = "CEST", offset = -7200000 },{ from = 1477789200000, until = 1490490000000, abbreviation = "CET", offset = -3600000 },{ from = 1490490000000, until = 1509238800000, abbreviation = "CEST", offset = -7200000 },{ from = 1509238800000, until = 1521939600000, abbreviation = "CET", offset = -3600000 },{ from = 1521939600000, until = 1540688400000, abbreviation = "CEST", offset = -7200000 },{ from = 1540688400000, until = 1553994000000, abbreviation = "CET", offset = -3600000 },{ from = 1553994000000, until = 1572138000000, abbreviation = "CEST", offset = -7200000 },{ from = 1572138000000, until = 1585443600000, abbreviation = "CET", offset = -3600000 },{ from = 1585443600000, until = 1603587600000, abbreviation = "CEST", offset = -7200000 },{ from = 1603587600000, until = 1616893200000, abbreviation = "CET", offset = -3600000 },{ from = 1616893200000, until = 1635642000000, abbreviation = "CEST", offset = -7200000 },{ from = 1635642000000, until = 1648342800000, abbreviation = "CET", offset = -3600000 },{ from = 1648342800000, until = 1667091600000, abbreviation = "CEST", offset = -7200000 },{ from = 1667091600000, until = 1679792400000, abbreviation = "CET", offset = -3600000 },{ from = 1679792400000, until = 1698541200000, abbreviation = "CEST", offset = -7200000 },{ from = 1698541200000, until = 1711846800000, abbreviation = "CET", offset = -3600000 },{ from = 1711846800000, until = 1729990800000, abbreviation = "CEST", offset = -7200000 },{ from = 1729990800000, until = 1743296400000, abbreviation = "CET", offset = -3600000 },{ from = 1743296400000, until = 1761440400000, abbreviation = "CEST", offset = -7200000 },{ from = 1761440400000, until = 1774746000000, abbreviation = "CET", offset = -3600000 },{ from = 1774746000000, until = 1792890000000, abbreviation = "CEST", offset = -7200000 },{ from = 1792890000000, until = 1806195600000, abbreviation = "CET", offset = -3600000 },{ from = 1806195600000, until = 1824944400000, abbreviation = "CEST", offset = -7200000 },{ from = 1824944400000, until = 1837645200000, abbreviation = "CET", offset = -3600000 },{ from = 1837645200000, until = 1856394000000, abbreviation = "CEST", offset = -7200000 },{ from = 1856394000000, until = 1869094800000, abbreviation = "CET", offset = -3600000 },{ from = 1869094800000, until = 1887843600000, abbreviation = "CEST", offset = -7200000 },{ from = 1887843600000, until = 1901149200000, abbreviation = "CET", offset = -3600000 },{ from = 1901149200000, until = 1919293200000, abbreviation = "CEST", offset = -7200000 },{ from = 1919293200000, until = 1932598800000, abbreviation = "CET", offset = -3600000 },{ from = 1932598800000, until = 1950742800000, abbreviation = "CEST", offset = -7200000 },{ from = 1950742800000, until = 1964048400000, abbreviation = "CET", offset = -3600000 },{ from = 1964048400000, until = 1982797200000, abbreviation = "CEST", offset = -7200000 },{ from = 1982797200000, until = 1995498000000, abbreviation = "CET", offset = -3600000 },{ from = 1995498000000, until = 2014246800000, abbreviation = "CEST", offset = -7200000 },{ from = 2014246800000, until = 2026947600000, abbreviation = "CET", offset = -3600000 },{ from = 2026947600000, until = 2045696400000, abbreviation = "CEST", offset = -7200000 },{ from = 2045696400000, until = 2058397200000, abbreviation = "CET", offset = -3600000 },{ from = 2058397200000, until = 2077146000000, abbreviation = "CEST", offset = -7200000 },{ from = 2077146000000, until = 2090451600000, abbreviation = "CET", offset = -3600000 },{ from = 2090451600000, until = 2108595600000, abbreviation = "CEST", offset = -7200000 },{ from = 2108595600000, until = 2121901200000, abbreviation = "CET", offset = -3600000 },{ from = 2121901200000, until = 2140045200000, abbreviation = "CEST", offset = -7200000 },{ from = 2140045200000, until = Infinity, abbreviation = "CET", offset = -3600000 }] }, dateTime = DateTime { date = Date { year = 2017, month = 2, day = 27 }, offset = 82800000 } }
Is there a reason for not having this function, expecting date string of the form YYYY-MM-DD
.
elm-test
passes locally.
Having been struggling with numerous date libraries in JavaScript, I decided to think of what the best API in Elm for a date library would look like. You can find some ideas here. The main goal is to minimize the amount of mistakes developers make around timezones by separating concepts of a “moment in time” and time with timezone. Being a little bit more explicit can go a long way in solving this problem.
Seeing that your library is very new and has somewhat similar concepts, I decided first to try and see what can be improved here, instead of coming up with my own implementation.
The way I think about it, moment in time refers to a particular absolute point in time — but most of the user-friendly details we can learn about it (such as day and time, as well as manipulating, formatting it and parsing a string into it) only come into play when you put it in a context of a timezone (and potentially a calendar, e.g. non-Gregorian one — but let's leave them out).
One could say that a moment in time does in fact have date and time — it's described by UTC. But this is what I think would be nice to be explicit about: by treating UTC as just another timezone we can make users think of the nature of the date they are working with. Is this a UTC date? Do we need to work with browser's timezone? Or do we need to use timezone defined somewhere in the user's settings we need to go and fetch? Those were the problem I had to solve when I was going through countless dates we were parsing, displaying and manipulating in our application.
Note that TimezoneDate
= (Moment, Timezone)
. The reason they are separate in my gist is that while in most cases you require both moment (which I call there Timestamp
) and timezone as function arguments, the timezone is almost never returned — it's used just as a parameter to transform the moment. One would read add : Timezone -> Interval -> Timestamp -> Timestamp
as “Add this interval to this moment by treating it (just for the purpose of this operation) in this timezone” (argument order is different for piping reasons); the interval (say, 5 days) only makes sense in the context of a timezone, even it it's just UTC.
The presence of no-timezone-to-timezone conversion (e.g. zonedDateTime
function) always makes me think: does this mean we are treating the date passed as if it was in the specified timezone, or we treat it in UTC (or any other original timezone, in case of moment.js) and simply change its timezone field? I was actually confused as I was typing this. I still am. I'm pretty sure I'm not alone.
In the current implementation, you have most operations defined on a timezone-less DateTime
. While operations such as addHours
can be performed on a bare date if it's treated as UTC, it's nevertheless very useful (I'd argue it's more useful) to perform those operations on a date with the potentially non-UTC timezone. Duplicating the API is probably not the best idea, this is where this separation helps as well.
Because ZonedDateTime
internally stores local time rather than UTC time, it's incapable of correctly storing time during the daylight saving switch.
Would my approach fit into this library? Should I try it out in a fork or a separate codebase? Let me know what you think!
Many libraries support an extended form of the ISO 8601 standard which includes time zone information in addition to the offset.
2017-01-02T06:12:38+01:00 [Europe/Berlin]
This fills a hole in the standard, as there is no official way to include time zone information.
I have already implemented a parsing function to read the time zone name. It's just a simple regex. Additionally I would propose to modify the existing parser to ignore time zone names if found.
Depending on your feedback, I'd open a pull request and get started.
EDIT: After reading the parser code and checking back with the documentation, I think there should be a clarification.
fromISO8601 parses an ISO8601-formatted date time string into a DateTime object, adjusting for its offset.
The later actually means "converts the date and time to UTC", which is not clear, at least for me. The type DateTime
also does not talk about time zones. Seeing how the parser works, it is supposed to be used for UTC values only?
It is a common pattern to present a dropdown to a user where they can select their timezone.
In order to do this I need a list of all timezones.
Time.TimeZones
doesn't expose a function for getting them all at once. It would be great to have
all : List TimeZone
I used
chave =
DateTime.epoch |> DateTime.millisecond |> toString
So, I expected return one number like 1505400959516 but the return is 0.
I using wrong or its a error?
Convert to and from Gregorian and Unix. This would be helpful for creating authentication headers, etc
I think I am similarly confused to what has been reported in #46.
Let's assume I have two Date
s (or DateTime
s for that matter). I want to know how many years have past from one point in time to another. Mainly for showing the age in years. It seems impossible to do with the current library.
How would I find out the correct age without resorting to weird hacks like dividing the days passed by 365.25
to filter out the leap years correctly?
> Time.Date.delta (Time.Date.date 2018 4 1) (Time.Date.date 1932 4 2) |> .days |> toFloat |> flip (/) 365.25
85.99589322381931 : Float
> Time.Date.delta (Time.Date.date 2018 4 2) (Time.Date.date 1932 4 2) |> .days |> toFloat |> flip (/) 365.25
85.99863107460644 : Float
> Time.Date.delta (Time.Date.date 2018 4 3) (Time.Date.date 1932 4 2) |> .days |> toFloat |> flip (/) 365.25
86.00136892539356 : Float
>
Hi,
I'm running into an issue with importing Time.TimeZones within any elm module after the upgrade from elm v0.17.1 to v0.18.0. Basically if I import the module and not even use it, the elm project will compile. But if I try to run the project in elm-reactor and access the page from Chrome, I will see the following error:
"Uncaught RangeError: Maximum call stack size exceeded"
I have a minimal repro for this issue:
`
import Html exposing (..)
import Time.TimeZones
type alias Model = {}
type Msg = Msg2
main : Program Never Model Msg
main = beginnerProgram
{ model = {}
, update = \a b -> b
, view = _ -> div [] [h1 [] [text "Hello World"]]
}
`
Package imports are:
This is not an issue in 0.17.1.
Thanks!
Hi,
I think it could be confusing for some users that Date
and DateTime
are not the equivalent of things represented by Date elsewhere, like in JavaScript. Even the elm-lang/core
has a Date which represents a timestamp and Date and DateTime from this lib represent something else.
My proposition would be to rename Date to LocalDate and DateTime to LocalDateTime. Also, we could introduce Timestamp and converters from Timestamp to ZonedDateTime (and vice-versa) and to LocalDate and LocalDateTime (assuming the user would provide a time-zone).
What is your opinion?
My elm-package.json
contains,
"elm-community/elm-time": "1.0.8 <= v < 2.0.0",
dependency.
I needed to run elm-package install
on new machine and after installation is done, elm-make
failed with,
ERROR in ./static/elm/Main.elm
Module build failed: Error: Compiler process exited with error Compilation failed
Problem in dependency elm-community/parser-combinators 1.1.0
The elm-package.json constraints of 'elm-community/parser-combinators' are probably
letting too much stuff through. Definitely open an issue on the relevant github
repo to get this fixed and save other people from this pain.
In the meantime, take a look through the direct dependencies of the broken
package and see if any of them have had releases recently. If you find the new
thing that is causing problems, you can artificially constrain things by adding
some extra constraints to your elm-package.json as a stopgap measure.
Detected errors in 1 module.
After quick investigation I fixed my build by setting dependency as,
"elm-community/elm-time": "1.0.8 <= v < 1.0.11",
so after elm-package install
run 1.0.10
version installed and elm-make
runs OK.
ps. Adding elm-community/parser-combinators: "1.1.0 <= v < 2.0.0"
to dependencies didn't fix my build.
I'm not sure if this is possible currently, seems not.
Most of the time all I have a is a Timezone name coming from the database e.g. Australia/Melbourne
The function unpack
wants a lot more information that I don't have.
Given that you already have functions for creating the timezone e.g. australia_melbourne ()
. I suppose that you can do the reverse and get a timezone by using the name.
It would be great to have a way to get aTimeZone
just by using the name. e.g.
fromName "Australia/Melbourne"
. Is this possible already?
e.g.
fromName name
case name of
'Australia/Melbourne' ->
Just (australia_melbourne ())
...
_ ->
Nothing
Hello,
I've been using your lib (and thank you for doing it by the way) and I think it's missing some helpers to deal with other libs.
For instance, I use rluiten/elm-date-extra to handle some light translations. I also use this lib that we made in my company elm-time-overlap.
Both (and others) use standard elm Date and/or Time types. It would be quite pleasant to have some functions to
and from
with your Date
and DateTime
. Or I am missing something?
These are not particularly complicated and I would gladly make a PR with them if you want. I don't know if they would fit in their modules or inside another Util
module though.
As I see things, I would love for :
Time.Date.fromDate : Date.Date -> Time.Date.Date
Time.Date.toDate : Time.Date.Date -> Date.Date
Time.Date.toTime : Time.Date.Date -> Time.Time
Time.Date.toWeekday : Time.Date.Weekday -> Date.Day
Time.Date.toMonth : Int -> Date.Month
Time.DateTime.fromDate : Date.Date -> Time.DateTime.DateTime
The last one is debatable because you could just use Date.toTime |> Time.DateTime.fromTimestamp
but it could just be that.
What do you think?
I read the API documentation an as result I have a question:
is there any reason to use offset from midnight.
instead the offset of time zones
? and why we should use this offset in dateTime in case we have ZonedDateTime.elm
When I select one of the ETC/UTC + or - timezones, it looks as if they have the sign wrong.
Here's a sample from the elm-repl:
> import Time.DateTime as DateTime exposing (zero)
> import Time.ZonedDateTime as ZonedDateTime
> import Time.TimeZones exposing (etc_gmt_plus_8, etc_gmt_minus_8)
> dt = DateTime.dateTime { zero | year = 2018, month = 01, day = 09, hour = 0 }
DateTime { date = Date { year = 2018, month = 1, day = 9 }, offset = 0 }
: Time.DateTime.DateTime
> dt |> ZonedDateTime.fromDateTime (etc_gmt_plus_8 ()) |> ZonedDateTime.toISO8601
"2018-01-08T16:00:00.000-08:00" : String
> dt |> ZonedDateTime.fromDateTime (etc_gmt_minus_8 ()) |> ZonedDateTime.toISO8601
"2018-01-09T08:00:00.000+08:00" : String
Note the -08:00
in the conversion using etc_gmt_plus_8
and the +08:00
in the conversion using etc_gmt_minus_8
.
Looking at the source:
elm-time/src/Time/TimeZoneData.elm
Line 312 in 2a30f0e
Clarify what npm
has to install and how to run them.
Since the API should be solid in the elm-community, I want to review it to make sure that it makes sense for the long-term before publishing. I invite anyone else who is interested to add their comments/concerns/suggestions as well.
The code works correctly, but the naming might be confusing.
Fixing because putting together a presentation and want the naming to be correct.
ZonedDateTime.fromISO8601
takes a TimeZone
as an argument and returns a ZonedDateTime
representing the parsed date in the specified timezone. However, there is no way to learn the timezone that was written into the ISO 8601 string since ZonedDateTime.fromISO8601
calls DateTime.fromISO8601
and applies a timezone.
My proposal is that ZonedDateTime.fromISO8601
should take only one String
argument and return a ZonedDateTime
representing the encoded date with the encoded timezone. DateTime.fromISO8601
would then then be implemented as ZonedDateTime.fromISO8601 >> ZonedDateTime.toDateTime
.
This is a request for a dayOfWeek
function, similar to http://package.elm-lang.org/packages/elm-lang/core/4.0.5/Date#dayOfWeek.
"2017-07-03T11:27:11.000-0400"
|> Time.DateTime.fromISO8601
|> toString
Err "Errors encountered at position 25: expected "Z" or expected "+" or expected "-" or expected "−""
"2017-07-03T11:27:11.001-0400"
|> Time.DateTime.fromISO8601
|> toString
Ok (DateTime { date = Date { year = 2017, month = 7, day = 3 }, offset = 55631001 })
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.