lau / tzdata Goto Github PK
View Code? Open in Web Editor NEWtzdata for Elixir. Born from the Calendar library.
License: MIT License
tzdata for Elixir. Born from the Calendar library.
License: MIT License
Location, where data saved is hardcoded to priv
.
Problem is, that: https://github.com/lau/tzdata/blob/master/lib/tzdata/data_loader.ex#L13 based on CWD it creates a priv. For example on releases, it seems, like: release_name/priv/...
not in tzdata/priv, but somewhere starting from cwd
. That means, on releases, where CWD is changed, it is not really known, where the priv folder should be created.
Possible solutions: explicitly define the download directory in configuration (download_dir: "/tmp/..."
), or use :code.priv_dir
for it. I'm against to use priv
dir so explicitly for mutable data. Problem is, that it makes impossible to install release on immutable location(at least for a application themself), and configure the whole application to have it mutable data on another storage.
This might be more theoretical than practical, but as I understand it there could be negative leap seconds (that is, a second less than normal) and not just extra leap seconds. It's never happened so far, but the UTC standard seems to be built upon than possibility.
How would tzdata handle a negative leap second? leap_seconds/0
only states when a leap second occurs, assuming (explicitly in the function documentation) that it's extra (positive) leap seconds.
15:57:28.719 [debug] Tzdata downloading new data from https://www.iana.org/time-zones/repository/tzdata-latest.tar.gz
15:57:29.399 [debug] Tzdata data downloaded. Release version 2017c.
{:error,
{:tzdata,
{:bad_return,
{{Tzdata.App, :start, [:normal, []]},
{:EXIT,
{{:badmatch,
{:error,
{:shutdown,
{:failed_to_start_child, Tzdata.EtsHolder,
{:badarg,
[{:ets, :lookup, [:tzdata_current_release, :release_version], []},
{Tzdata.ReleaseReader, :current_release_from_table, 0,
[file: 'lib/tzdata/release_reader.ex', line: 47]},
{Tzdata.ReleaseReader, :simple_lookup, 1,
[file: 'lib/tzdata/release_reader.ex', line: 14]},
{Tzdata.ReleaseReader, :release_version, 0,
[file: 'lib/tzdata/release_reader.ex', line: 9]},
{Tzdata.DataBuilder, :load_and_save_table, 0,
[file: 'lib/tzdata/data_builder.ex', line: 11]},
{Tzdata.EtsHolder, :init, 1,
[file: 'lib/tzdata/ets_holder.ex', line: 11]},
{:gen_server, :init_it, 2, [file: 'gen_server.erl', line: 365]},
{:gen_server, :init_it, 6,
[file: 'gen_server.erl', line: 333]}]}}}}},
[{Tzdata.App, :start, 2, [file: 'lib/tzdata/tzdata_app.ex', line: 15]},
{:application_master, :start_it_old, 4,
[file: 'application_master.erl', line: 273]}]}}}}}}
iex(3)> 15:57:29.414 [info] Application tzdata exited: exited in: Tzdata.App.start(:normal, [])
** (EXIT) an exception was raised:
** (MatchError) no match of right hand side value: {:error, {:shutdown, {:failed_to_start_child, Tzdata.EtsHolder, {:badarg, [{:ets, :lookup, [:tzdata_current_release, :release_version], []}, {Tzdata.ReleaseReader, :current_release_from_table, 0, [file: 'lib/tzdata/release_reader.ex', line: 47]}, {Tzdata.ReleaseReader, :simple_lookup, 1, [file: 'lib/tzdata/release_reader.ex', line: 14]}, {Tzdata.ReleaseReader, :release_version, 0, [file: 'lib/tzdata/release_reader.ex', line: 9]}, {Tzdata.DataBuilder, :load_and_save_table, 0, [file: 'lib/tzdata/data_builder.ex', line: 11]}, {Tzdata.EtsHolder, :init, 1, [file: 'lib/tzdata/ets_holder.ex', line: 11]}, {:gen_server, :init_it, 2, [file: 'gen_server.erl', line: 365]}, {:gen_server, :init_it, 6, [file: 'gen_server.erl', line: 333]}]}}}}
(tzdata) lib/tzdata/tzdata_app.ex:15: Tzdata.App.start/2
(kernel) application_master.erl:273: :application_master.start_it_old/4
Not sure what the issues is exactly. I confirmed that I'm using the latest 0.5.13 with latest Timex.
Hi, is a release with 2016.b planned? :)
I'm running a custom logging backend to mock the logger in test. Instead of log output on stdout, I send messages to the originating process (typically the test process) where I can then assert_received
for a particular log message. I've found this mechanism cleaner/easier than capture_log
.
But I've hit a problem with tzdata's EtsHolder genserver:
[error] Tzdata.EtsHolder Tzdata.EtsHolder received unexpected message in handle_info/2: {…}
It executes Logger
calls, but fails if a message it sent to it.
I'd like to implement a no-op handle_info
in EtsHolder. I'm happy to PR it up, but shout out if you hate the idea.
Similar issues, but not quite: #28
Using tz_data 0.5.15.
This night I got a couple of error log messages from two different applications deployed on the same host. There was around three hours between the errors and I haven't noticed any other issues with the apps or host.
One of the messages:
[ERROR] <0.2341.0>: GenServer :tzdata_release_updater terminating
** (File.Error) could not stream "/path/to/app/lib/tzdata-0.5.15/priv/tmp_downloads/339626_44358462//pacificnew": no such file or directory
(elixir) lib/file/stream.ex:79: anonymous fn/2 in Enumerable.File.Stream.reduce/3
(elixir) lib/stream.ex:1270: anonymous fn/5 in Stream.resource/3
(elixir) lib/stream.ex:1433: Enumerable.Stream.do_each/4 (elixir) lib/enum.ex:1841: Enum.reverse/1
(elixir) lib/enum.ex:2599: Enum.to_list/1 (tzdata) lib/tzdata/parser.ex:16: Tzdata.Parser.process_file/1
(tzdata) lib/tzdata/basic_data_map.ex:8: anonymous fn/2 in Tzdata.BasicDataMap.from_files_in_dir/1
(elixir) lib/enum.ex:1273: Enum."-map/2-lists^map/1-0-"/2 (elixir) lib/enum.ex:1273: Enum."-map/2-lists^map/1-0-"/2
(tzdata) lib/tzdata/basic_data_map.ex:8: Tzdata.BasicDataMap.from_files_in_dir/1
(tzdata) lib/tzdata/data_builder.ex:32: Tzdata.DataBuilder.do_load_and_save_table/4
(tzdata) lib/tzdata/release_updater.ex:46: Tzdata.ReleaseUpdater.poll_for_update/0 Last message: :check_if_time_to_update
The other is similar and can also not find the pacificnew
file.
The only other tzdata logs I can find is from around 1 second before the error saying
Tzdata.ReleaseUpdater [INFO] <0.2341.0>: tzdata release in place is from a file last modified Mon, 23 Oct 2017 15:19:20 GMT. Release file on server was last modified Tue, 16 Jan 2018 17:43:58 GMT.
In the latest tzdata from https://www.iana.org/time-zones, the pacificnew
is not included, so perhaps it should just be removed from BasicDataMap?
Hi, I have an error on compilation on CentOS 6.3 with tzdata 0.5.2:
Could you please tell me how to solve it?
Generated ecto app
20:54:13.422 [error] Task #PID<0.1047.0> started from :tzdata_release_updater terminating
** (File.Error) could not stream priv/tmp_downloads/300363//backward: no such file or directory
(elixir) lib/file/stream.ex:77: anonymous fn/2 in Enumerable.File.Stream.reduce/3
(elixir) lib/stream.ex:1077: anonymous fn/5 in Stream.resource/3
(elixir) lib/stream.ex:1240: Enumerable.Stream.do_each/4
(elixir) lib/enum.ex:1391: Enum.reduce/3
(elixir) lib/enum.ex:2130: Enum.to_list/1
(tzdata) lib/tzdata/parser.ex:16: Tzdata.Parser.process_file/1
(tzdata) lib/tzdata/basic_data_map.ex:8: anonymous fn/2 in Tzdata.BasicDataMap.from_files_in_dir/1
(elixir) lib/enum.ex:1043: anonymous fn/3 in Enum.map/2
Function: #Function<1.108323131/0 in Tzdata.ReleaseUpdater.init/1>
Args: []
==> cowlib (compile)
Would it be possible to somehow prefetch the fresh tz release during app release assembly?
Maybe some kind of mix task (mix tzdata.download
) that would override the version bundled with tzdata package?
The main reason for this is to minimise the possibility of new release starting with old tzdata.
iex(6)> {:ok, mvd } = Calendar.DateTime.from_erl {{2014,10,4},{23,44,32}}, "Etc/UTC"
{:ok, #DateTime<2014-10-04 23:44:32Z>}
iex(7)> mvd |> Calendar.DateTime.shift_zone!("Europe/London")
#DateTime<2014-10-05 00:44:32+01:00 BST Europe/London>
iex(8)> mvd |> Calendar.DateTime.shift_zone!("Europe/Dublin")
#DateTime<2014-10-04 23:44:32+00:00 GMT Europe/Dublin>
iex(9)>
There is some issue in changing timezone when its Dublin, there is one hour difference between UTC and Dublin time but conversion is not adding day light saving.
Can you guide?
We've just started getting this crash when tzdata tries to do an update of its data:
crasher:
initial call: Elixir.Tzdata.ReleaseUpdater:init/1
pid: <0.2305.0>
registered_name: tzdata_release_updater
exception exit: {
{badarg,[{erlang,hd,[[]],[]},
{'Elixir.Tzdata.DataLoader',content_length_from_headers,1,[{file,"lib/tzdata/data_loader.ex"},{line,29}]},{'Elixir.Tzdata.DataLoader',do_latest_file_size,1,[{file,"lib/tzdata/data_loader.ex"},{line,51}]},
{'Elixir.Tzdata.ReleaseUpdater','loaded_tzdata_matches_iana_file_size?',0,[{file,"lib/tzdata/release_updater.ex"},{line,48}]},
{'Elixir.Tzdata.ReleaseUpdater',poll_for_update,0,[{file,"lib/tzdata/release_updater.ex"},{line,36}]},
{'Elixir.Tzdata.ReleaseUpdater',handle_info,2,[{file,"lib/tzdata/release_updater.ex"},{line,17}]},
{gen_server,try_dispatch,4,[{file,"gen_server.erl"},{line,601}]},
{gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,667}]}]},
[{gen_server,terminate,7,[{file,"gen_server.erl"},{line,812}]},
{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,247}]}]}
Best as I can tell, the HEAD data it's pulling no longer contains the Content-Length field. Indeed a quick test seems to bear this out:
$ curl --head https://www.iana.org/time-zones/repository/tzdata-latest.tar.gz
HTTP/1.1 200 OK
Date: Tue, 07 Mar 2017 00:30:29 GMT
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: upgrade-insecure-requests
Last-Modified: Tue, 28 Feb 2017 21:18:44 GMT
Vary: Accept-Encoding
content-type: application/x-gzip
content-encoding: identity
Cache-Control: public, max-age=3600
Server: Apache
X-Cache-Host: www-varnish.iana.org
X-Cache-Hits: 1413
Accept-Ranges: bytes
Connection: keep-alive
Strict-Transport-Security: max-age=48211200
But of course I could be misreading the code.
Edit: We're running 0.5.10
First: thanks for maintaining tzdata!
Background story:
I was playing today with SchedEx Empex NYC 2018 Talk + Github and noticed that tzdata pulls quite some transient dependencies.
$ mix app.tree
schedextest
├── elixir
├── logger
│ └── elixir
├── cortex
│ ├── elixir
│ ├── logger
│ └── file_system
│ ├── elixir
│ └── logger
└── sched_ex
├── elixir
├── crontab
│ ├── elixir
│ └── logger
├── logger
└── timex
├── elixir
├── logger
├── tzdata
│ ├── elixir
│ ├── hackney
│ │ ├── crypto
│ │ ├── asn1
│ │ ├── public_key
│ │ │ ├── asn1
│ │ │ └── crypto
│ │ ├── ssl
│ │ │ ├── crypto
│ │ │ └── public_key
│ │ ├── idna
│ │ │ └── unicode_util_compat
│ │ ├── mimerl
│ │ ├── certifi
│ │ ├── ssl_verify_fun
│ │ │ └── ssl
│ │ └── metrics
│ └── logger
├── gettext
│ ├── elixir
│ └── logger
└── combine
└── elixir
The only place where hackney is needed is in this module: https://github.com/lau/tzdata/blob/06da3182cc948902bc42a3cec86552744382c229/lib/tzdata/data_loader.ex doing a get
/ head
requests. Nothings fancy and also not performance-critical because it only has to download 300k file once in a while.
One option would be to use something like https://github.com/alexandrubagu/simplehttp
, the other would be to include (embed / vendor-in) a small module that wraps :httpc.request
. That way tzdata would be independent of any http client implementations by using the always present :httpc
implementation.
I understand that this does not look like high prio issue, yet considering the popularity of timex and other libraries depending on tzdata it might be sensible to shed some of the dependencies longterm to make including tzdata
as painless as possible.
Here are some numbers to make it more visual:
https://hex.pm/packages?search=depends%3Acalendar -> 29 dependencies of calender
, guardian
and quantum
being the most popular.
https://hex.pm/packages?search=depends%3Atimex -> 209 dependencies of timex
with a lot of popular packages...
Hope this will get proper consideration and have a nice day!
Hi,
I noticed on a number of production servers that there are a number of TCP connection to https://www.iana.org that remain in CLOSE_WAIT. The only code that references www.iana.org seems to be tzdata. Do you have any clue?
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
beam.smp 1424 root 11u IPv4 18985 0t0 TCP *:35058 (LISTEN)
beam.smp 1424 root 12u IPv4 18987 0t0 TCP localhost:60553->localhost:epmd (ESTABLISHED)
beam.smp 1424 root 13u IPv4 18137 0t0 TCP gratwifi.lan:81 (LISTEN)
beam.smp 1424 root 16u IPv4 422369 0t0 TCP 192.168.1.7:42237->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 17u IPv4 16152 0t0 UDP *:52241
beam.smp 1424 root 19u IPv4 723308 0t0 TCP 192.168.1.7:37011->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 20u IPv4 581191 0t0 TCP 192.168.1.7:60339->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 21u IPv4 1129389 0t0 TCP 192.168.1.7:54109->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 22u IPv4 864988 0t0 TCP 192.168.1.7:59174->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 23u IPv4 1011660 0t0 TCP 192.168.1.7:56804->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 24u IPv4 1276491 0t0 TCP 192.168.1.7:58875->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 25u IPv4 1435758 0t0 TCP 192.168.1.7:33240->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 26u IPv4 1592295 0t0 TCP 192.168.1.7:37590->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 27u IPv4 1764131 0t0 TCP 192.168.1.7:41133->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 28u IPv4 2365627 0t0 TCP 192.168.1.7:32983->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 29u IPv4 1955942 0t0 TCP 192.168.1.7:59567->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 30u IPv4 2573572 0t0 TCP 192.168.1.7:45931->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 31u IPv4 2168659 0t0 TCP 192.168.1.7:50945->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 32u IPv4 2499120 0t0 UDP *:60100
beam.smp 1424 root 33u IPv4 2979799 0t0 TCP 192.168.1.7:37016->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 34u IPv4 2785116 0t0 TCP 192.168.1.7:33791->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 35u IPv4 3183900 0t0 TCP 192.168.1.7:37685->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 36u IPv4 3352151 0t0 TCP 192.168.1.7:56252->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 37u IPv4 101022 0t0 TCP 192.168.1.7:59720->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 38u IPv4 262679 0t0 TCP 192.168.1.7:46152->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 39u IPv4 3537364 0t0 TCP 192.168.1.7:39599->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 40u IPv4 3882622 0t0 TCP 192.168.1.7:60647->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 41u IPv4 3733899 0t0 TCP 192.168.1.7:35346->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 42u IPv4 4064143 0t0 TCP 192.168.1.7:52116->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 43u IPv4 4372605 0t0 TCP 192.168.1.7:52828->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 44u IPv4 4512808 0t0 TCP 192.168.1.7:38491->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 45u IPv4 4235652 0t0 TCP 192.168.1.7:45662->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 46u IPv4 4630737 0t0 TCP 192.168.1.7:54971->www.iana.org:https (CLOSE_WAIT)
beam.smp 1424 root 47u IPv4 4790369 0t0 TCP 192.168.1.7:49358->www.iana.org:https (CLOSE_WAIT)
Hello,
Erlang/OTP 22 [erts-10.5] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1]
IEx 1.9.4 (compiled with Erlang/OTP 22)
{
"hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085"},
"timex": {:hex, :timex, "3.6.1", "efdf56d0e67a6b956cc57774353b0329c8ab7726766a11547e529357ffdc1d56"},
"tzdata": {:hex, :tzdata, "1.0.2", "6c4242c93332b8590a7979eaf5e11e77d971e579805c44931207e32aa6ad3db1"}
}
I've been getting an error every time my project tries to update the timezone database, for a few weeks now.
** (ArgumentError) argument error
(stdlib) :ets.lookup_element(:hackney_config, :mod_metrics, 2)
/proj/deps/hackney/src/hackney_metrics.erl:26: :hackney_metrics.get_engine/0
/proj/deps/hackney/src/hackney_connect.erl:78: :hackney_connect.create_connection/5
/proj/deps/hackney/src/hackney_connect.erl:47: :hackney_connect.connect/5
/proj/deps/hackney/src/hackney.erl:333: :hackney.request/5
(tzdata) lib/tzdata/http_client/hackney.ex:17: Tzdata.HTTPClient.Hackney.head/3
(tzdata) lib/tzdata/data_loader.ex:46: Tzdata.DataLoader.last_modified_of_latest_available/1
(tzdata) lib/tzdata/release_updater.ex:81: Tzdata.ReleaseUpdater.loaded_tzdata_matches_remote_last_modified?/0
(tzdata) lib/tzdata/release_updater.ex:42: Tzdata.ReleaseUpdater.poll_for_update/0
I've run into a dead end debugging this as the Tzdata.HTTPClient.Hackney module uses the callback system I'm not familiar with.
I also don't see any similar issues created, so I'm thinking this is some sort of configuration error on my part. Do you perhaps have an idea why this is erroring?
Hi,
It looks like the data_loader.ex file does not customize the default user agent. It would be useful to set that to a unique value to politely identify the source of http requests.
Untested code would be something like...
Before:
{:ok, 200, _headers, client_ref}=:hackney.get(url, [], "", [])
After:
tz_ua = [<<"User-Agent: ", "tzdata/", version/binary, " (https://github.com/lau/tzdata)" >>],
{:ok, 200, _headers, client_ref}=:hackney.get(url, tz_ua, "", [])
For the sake of reference easily copy-and-pasted, hackney's default_ua() is created in hackney_request.erl.
Thanks,
Hi,
I'm writing to suggest complementing or replacing the existing Content-Length checks in data_loader.ex with an If-Modified-Since header, commonly used by web browsers to avoid the delay of a download operation.
% nc -C www.iana.org 80
GET /time-zones/repository/tzdata-latest.tar.gz HTTP/1.1
Host: www.iana.org
User-Agent: https://github.com/lau/tzdata
If-Modified-Since: Tue, 28 Feb 2017 21:18:44 GMT
HTTP/1.1 304 Not Modified
Date: Thu, 09 Mar 2017 04:33:21 GMT
Last-Modified: Tue, 28 Feb 2017 21:18:44 GMT
I would like to have attached a patch, but I'm not familiar enough with Erlang/Hackney to quickly create one to use this If-Modified-Since method. However, I'm interested enough in seeing this feature exist I'd hack up a diff after a day's research if that's what I have to do.
I hope this suggestion can perhaps simplify the operation: Instead of a combination of GETs and HEADs the fetch could become just GETs, with the difference between an unmodified GET or modified GET revealed by the empty 304 or normal 200 response.
Thanks,
Library doing some http checks, I think that it is not good in all environments (for example because of security reasons) to make some wild http requests in a library, which doesn't seem to need to do it (it is not an API to extern data).
Would be nice to add some configuration option, like: check_new_releases: true | false
or outsource the supervisor for release updates, that if somebody really want to update it regular, should release_updater in its own supervisor tree. What do you think about it?
There's missing EDT timezone, but it could be found in northamerica and australasia.
Sometimes the automatic update is failing on my machine (and on a coworkers' machine). I can turn automatic updating off, however I think it would be nice if this error is handled correctly.
2015-10-14 10:45:38.080 [debug] Tzdata downloading new data from https://www.iana.org/time-zones/repository/tzdata-latest.tar.gz
2015-10-14 10:45:39.148 [debug] Tzdata data downloaded. Release version 2015f.
2015-10-14 10:45:40.728 [error] GenServer Tzdata.EtsHolder terminating
** (MatchError) no match of right hand side value: {:error, :cannot_create_table}
(tzdata) lib/tzdata/ets_holder.ex:51: Tzdata.EtsHolder.load_ets_table/1
(tzdata) lib/tzdata/ets_holder.ex:44: Tzdata.EtsHolder.load_release/0
(tzdata) lib/tzdata/ets_holder.ex:21: Tzdata.EtsHolder.handle_cast/2
(stdlib) gen_server.erl:615: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:681: :gen_server.handle_msg/5
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", :new_release_has_been_downloaded}
State: "2015g”
I didn't look any further than this point because I'm unable to reproduce this on command. Maybe you have an idea yourself why this happens.
I got a Tzdata.EtsHolder
error when updating tzdata. It seems downloading succeeded, but parsing failed.
Log is a bit long because we use Sentry logger.
Interactive Elixir (1.7.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
03:57:49.652 [debug] Tzdata polling for update.
03:57:50.863 [info] tzdata release in place is from a file last modified Mon, 31 Dec 2018 01:25:12 GMT. Release file on server was last modified Tue, 26 Mar 2019 05:40:14 GMT.
2019-03-27T12:57:50.864 [info] tzdata release in place is from a file last modified Mon, 31 Dec 2018 01:25:12 GMT. Release file on server was last modified Tue, 26 Mar 2019 05:40:14 GMT.
03:57:50.869 [debug] Tzdata downloading new data from https://data.iana.org/time-zones/tzdata-latest.tar.gz
03:57:52.029 [debug] Tzdata data downloaded. Release version 20198.
03:57:53.020 [error] GenServer Tzdata.EtsHolder terminating
** (MatchError) no match of right hand side value: {:error, :cannot_create_table}
(tzdata) lib/tzdata/ets_holder.ex:59: Tzdata.EtsHolder.load_ets_table/1
(tzdata) lib/tzdata/ets_holder.ex:52: Tzdata.EtsHolder.load_release/0
(tzdata) lib/tzdata/ets_holder.ex:23: Tzdata.EtsHolder.handle_cast/2
(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:711: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", :new_release_has_been_downloaded}
State: "2018i"
2019-03-27T12:57:53.118 [error] GenServer Tzdata.EtsHolder terminating
** (MatchError) no match of right hand side value: {:error, :cannot_create_table}
(tzdata) lib/tzdata/ets_holder.ex:59: Tzdata.EtsHolder.load_ets_table/1
(tzdata) lib/tzdata/ets_holder.ex:52: Tzdata.EtsHolder.load_release/0
(tzdata) lib/tzdata/ets_holder.ex:23: Tzdata.EtsHolder.handle_cast/2
(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:711: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", :new_release_has_been_downloaded}
State: "2018i"
03:57:53.117 [error] :gen_event handler Sentry.LoggerBackend installed in Logger terminating
** (FunctionClauseError) no function clause matching in URI.parse/1
(elixir) lib/uri.ex:414: URI.parse(nil)
(sentry) lib/sentry/client.ex:226: Sentry.Client.get_dsn/0
(sentry) lib/sentry/client.ex:329: Sentry.Client.get_headers_and_endpoint/0
(sentry) lib/sentry/client.ex:92: Sentry.Client.do_send_event/3
(sentry) lib/sentry/logger_backend.ex:38: Sentry.LoggerBackend.handle_event/2
(stdlib) gen_event.erl:577: :gen_event.server_update/4
(stdlib) gen_event.erl:559: :gen_event.server_notify/4
(stdlib) gen_event.erl:300: :gen_event.handle_msg/6
Last message: {:error, #PID<0.327.0>, {Logger, [["GenServer ", "Tzdata.EtsHolder", " terminating", [[10 | "** (MatchError) no match of right hand side value: {:error, :cannot_create_table}"], ["\n " | "(tzdata) lib/tzdata/ets_holder.ex:59: Tzdata.EtsHolder.load_ets_table/1"], ["\n " | "(tzdata) lib/tzdata/ets_holder.ex:52: Tzdata.EtsHolder.load_release/0"], ["\n " | "(tzdata) lib/tzdata/ets_holder.ex:23: Tzdata.EtsHolder.handle_cast/2"], ["\n " | "(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4"], ["\n " | "(stdlib) gen_server.erl:711: :gen_server.handle_msg/6"], ["\n " | "(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3"]], "\nLast message", [], ": ", "{:\"$gen_cast\", :new_release_has_been_downloaded}"], "\nState: ", "\"2018i\""], {{2019, 3, 27}, {3, 57, 53, 20}}, [registered_name: Tzdata.EtsHolder, crash_reason: {%MatchError{term: {:error, :cannot_create_table}}, [{Tzdata.EtsHolder, :load_ets_table, 1, [file: 'lib/tzdata/ets_holder.ex', line: 59]}, {Tzdata.EtsHolder, :load_release, 0, [file: 'lib/tzdata/ets_holder.ex', line: 52]}, {Tzdata.EtsHolder, :handle_cast, 2, [file: 'lib/tzdata/ets_holder.ex', line: 23]}, {:gen_server, :try_dispatch, 4, [file: 'gen_server.erl', line: 637]}, {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 711]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}]}, function: "error_info/7", module: :gen_server, line: 888, file: "gen_server.erl", pid: #PID<0.330.0>]}}
State: %Sentry.LoggerBackend{level: nil}
2019-03-27T12:57:53.118 [error] :gen_event handler Sentry.LoggerBackend installed in Logger terminating
** (FunctionClauseError) no function clause matching in URI.parse/1
(elixir) lib/uri.ex:414: URI.parse(nil)
(sentry) lib/sentry/client.ex:226: Sentry.Client.get_dsn/0
(sentry) lib/sentry/client.ex:329: Sentry.Client.get_headers_and_endpoint/0
(sentry) lib/sentry/client.ex:92: Sentry.Client.do_send_event/3
(sentry) lib/sentry/logger_backend.ex:38: Sentry.LoggerBackend.handle_event/2
(stdlib) gen_event.erl:577: :gen_event.server_update/4
(stdlib) gen_event.erl:559: :gen_event.server_notify/4
(stdlib) gen_event.erl:300: :gen_event.handle_msg/6
Last message: {:error, #PID<0.327.0>, {Logger, [["GenServer ", "Tzdata.EtsHolder", " terminating", [[10 | "** (MatchError) no match of right hand side value: {:error, :cannot_create_table}"], ["\n " | "(tzdata) lib/tzdata/ets_holder.ex:59: Tzdata.EtsHolder.load_ets_table/1"], ["\n " | "(tzdata) lib/tzdata/ets_holder.ex:52: Tzdata.EtsHolder.load_release/0"], ["\n " | "(tzdata) lib/tzdata/ets_holder.ex:23: Tzdata.EtsHolder.handle_cast/2"], ["\n " | "(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4"], ["\n " | "(stdlib) gen_server.erl:711: :gen_server.handle_msg/6"], ["\n " | "(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3"]], "\nLast message", [], ": ", "{:\"$gen_cast\", :new_release_has_been_downloaded}"], "\nState: ", "\"2018i\""], {{2019, 3, 27}, {3, 57, 53, 20}}, [registered_name: Tzdata.EtsHolder, crash_reason: {%MatchError{term: {:error, :cannot_create_table}}, [{Tzdata.EtsHolder, :load_ets_table, 1, [file: 'lib/tzdata/ets_holder.ex', line: 59]}, {Tzdata.EtsHolder, :load_release, 0, [file: 'lib/tzdata/ets_holder.ex', line: 52]}, {Tzdata.EtsHolder, :handle_cast, 2, [file: 'lib/tzdata/ets_holder.ex', line: 23]}, {:gen_server, :try_dispatch, 4, [file: 'gen_server.erl', line: 637]}, {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 711]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}]}, function: "error_info/7", module: :gen_server, line: 888, file: "gen_server.erl", pid: #PID<0.330.0>]}}
State: %Sentry.LoggerBackend{level: nil}
03:57:53.120 [error] GenServer #PID<0.538.0> terminating
** (stop) {:EXIT, {:function_clause, [{URI, :parse, [nil], [file: 'lib/uri.ex', line: 414]}, {Sentry.Client, :get_dsn, 0, [file: 'lib/sentry/client.ex', line: 226]}, {Sentry.Client, :get_headers_and_endpoint, 0, [file: 'lib/sentry/client.ex', line: 329]}, {Sentry.Client, :do_send_event, 3, [file: 'lib/sentry/client.ex', line: 92]}, {Sentry.LoggerBackend, :handle_event, 2, [file: 'lib/sentry/logger_backend.ex', line: 38]}, {:gen_event, :server_update, 4, [file: 'gen_event.erl', line: 577]}, {:gen_event, :server_notify, 4, [file: 'gen_event.erl', line: 559]}, {:gen_event, :handle_msg, 6, [file: 'gen_event.erl', line: 300]}]}}
Last message: {:gen_event_EXIT, Sentry.LoggerBackend, {:EXIT, {:function_clause, [{URI, :parse, [nil], [file: 'lib/uri.ex', line: 414]}, {Sentry.Client, :get_dsn, 0, [file: 'lib/sentry/client.ex', line: 226]}, {Sentry.Client, :get_headers_and_endpoint, 0, [file: 'lib/sentry/client.ex', line: 329]}, {Sentry.Client, :do_send_event, 3, [file: 'lib/sentry/client.ex', line: 92]}, {Sentry.LoggerBackend, :handle_event, 2, [file: 'lib/sentry/logger_backend.ex', line: 38]}, {:gen_event, :server_update, 4, [file: 'gen_event.erl', line: 577]}, {:gen_event, :server_notify, 4, [file: 'gen_event.erl', line: 559]}, {:gen_event, :handle_msg, 6, [file: 'gen_event.erl', line: 300]}]}}}
State: {Logger, Sentry.LoggerBackend}
2019-03-27T12:57:53.121 [error] GenServer #PID<0.538.0> terminating
** (stop) {:EXIT, {:function_clause, [{URI, :parse, [nil], [file: 'lib/uri.ex', line: 414]}, {Sentry.Client, :get_dsn, 0, [file: 'lib/sentry/client.ex', line: 226]}, {Sentry.Client, :get_headers_and_endpoint, 0, [file: 'lib/sentry/client.ex', line: 329]}, {Sentry.Client, :do_send_event, 3, [file: 'lib/sentry/client.ex', line: 92]}, {Sentry.LoggerBackend, :handle_event, 2, [file: 'lib/sentry/logger_backend.ex', line: 38]}, {:gen_event, :server_update, 4, [file: 'gen_event.erl', line: 577]}, {:gen_event, :server_notify, 4, [file: 'gen_event.erl', line: 559]}, {:gen_event, :handle_msg, 6, [file: 'gen_event.erl', line: 300]}]}}
Last message: {:gen_event_EXIT, Sentry.LoggerBackend, {:EXIT, {:function_clause, [{URI, :parse, [nil], [file: 'lib/uri.ex', line: 414]}, {Sentry.Client, :get_dsn, 0, [file: 'lib/sentry/client.ex', line: 226]}, {Sentry.Client, :get_headers_and_endpoint, 0, [file: 'lib/sentry/client.ex', line: 329]}, {Sentry.Client, :do_send_event, 3, [file: 'lib/sentry/client.ex', line: 92]}, {Sentry.LoggerBackend, :handle_event, 2, [file: 'lib/sentry/logger_backend.ex', line: 38]}, {:gen_event, :server_update, 4, [file: 'gen_event.erl', line: 577]}, {:gen_event, :server_notify, 4, [file: 'gen_event.erl', line: 559]}, {:gen_event, :handle_msg, 6, [file: 'gen_event.erl', line: 300]}]}}}
State: {Logger, Sentry.LoggerBackend}
I also try 1.0.0-rc.0
(though on Elixir 1.7) but same error:
Interactive Elixir (1.7.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
13:16:46.050 [debug] Tzdata polling for update.
13:16:46.772 [info] tzdata release in place is from a file last modified Mon, 31 Dec 2018 01:25:12 GMT. Release file on server was last modified Tue, 26 Mar 2019 05:40:14 GMT.
13:16:46.772 [debug] Tzdata downloading new data from https://data.iana.org/time-zones/tzdata-latest.tar.gz
13:16:47.461 [debug] Tzdata data downloaded. Release version 20198.
13:16:48.556 [error] GenServer Tzdata.EtsHolder terminating
** (MatchError) no match of right hand side value: {:error, :cannot_create_table}
(tzdata) lib/tzdata/ets_holder.ex:63: Tzdata.EtsHolder.load_ets_table/1
(tzdata) lib/tzdata/ets_holder.ex:56: Tzdata.EtsHolder.load_release/0
(tzdata) lib/tzdata/ets_holder.ex:27: Tzdata.EtsHolder.handle_cast/2
(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:711: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", :new_release_has_been_downloaded}
State: "2018i"
Hi,
recently I discovered a series of crashes related to tzdata, as I am running my release from a read-only filesystem.
=CRASH REPORT==== 21-Dec-2017::09:20:17 ===
crasher:
initial call: Elixir.Tzdata.ReleaseUpdater:init/1
pid: <0.28190.6>
registered_name: tzdata_release_updater
exception error: #{'__exception__' => true,
'__struct__' => 'Elixir.File.Error',
action => <<"write to file">>,
path =>
<<"/opt/app/lib/tzdata-0.5.14/priv/latest_remote_poll.txt">>,
reason => eacces}
in function 'Elixir.File':'write!'/3 (lib/file.ex, line 831)
in call from 'Elixir.Tzdata.DataLoader':last_modified_of_latest_available/1 (lib/tzdata/data_loader.ex, line 53)
in call from 'Elixir.Tzdata.ReleaseUpdater':'loaded_tzdata_matches_remote_last_modified?'/0 (lib/tzdata/release_updater.ex, line 79)
in call from 'Elixir.Tzdata.ReleaseUpdater':poll_for_update/0 (lib/tzdata/release_updater.ex, line 40)
in call from 'Elixir.Tzdata.ReleaseUpdater':handle_info/2 (lib/tzdata/release_updater.ex, line 17)
in call from gen_server:try_dispatch/4 (gen_server.erl, line 616)
in call from gen_server:handle_msg/6 (gen_server.erl, line 686)
ancestors: [<0.1494.0>,<0.1493.0>]
message_queue_len: 0
messages: []
links: [<0.1494.0>]
dictionary: []
trap_exit: false
status: running
heap_size: 987
stack_size: 27
reductions: 1634
Is there another way to make use of tzdata, maybe pointing it to a writable directory?
Kind regards,
Lukas Rieder
The discussion about tzdata's unexpected update behaviour came up on Slack again (https://elixir-lang.slack.com/archives/C0AB4A879/p1546084693076000). I think there's a way to have your cake and eat it, too - split off the update logic.
After the split, there'd be two libraries:
tzdata
which has the pure code, just the time zone access;tzdata_updater
which has the side-effecting code that does the updates.That way, downstream libraries like timex can just depend on the tzdata
library and nothing unexpected will happen (nor will maintainers of downstream libraries be forced to make a decision on whether this behaviour is wanted or not - they can't, only the end user can). If someone wants the update behaviour, that is simple enough to accomplish by adding the tzdata_updater
dependency as well. No messing around with Mix configs needed.
(needless to say, more than happy to chip in some time to make this happen)
This happens on the summer/winter time change boundary:
iex(57)> datetimes = [datetime1, datetime2, datetime3]
[#DateTime<2018-10-28 00:59:59Z>, #DateTime<2018-10-28 01:00:00Z>,
#DateTime<2018-10-28 01:00:01Z>]
iex(58)> Enum.map(datetimes, &DateTime.shift_zone(&1, "Europe/Copenhagen"))
[
ok: #DateTime<2018-10-28 02:59:59+02:00 CEST Europe/Copenhagen>,
error: :time_zone_not_found,
ok: #DateTime<2018-10-28 02:00:01+01:00 CET Europe/Copenhagen>
]
I think I should expect #DateTime<2018-10-28 02:00:00+01:00 CET Europe/Copenhagen>
for the second element.
I'm guessing it's due to this line:
tzdata/lib/tzdata/time_zone_database.ex
Line 17 in b556189
We encountered an error in one of our apps that uses Timex, which uses Tzdata. Here's the stacktrace:
Elixir.FunctionClauseError: no function clause matching in Keyword.delete_key/3
File "lib/tzdata/util.ex", line 73, in Tzdata.Util.first_matching_weekday_in_month/4
File "lib/tzdata/util.ex", line 329, in Tzdata.Util.time_for_rule/2
File "lib/tzdata/period_builder.ex", line 161, in Tzdata.PeriodBuilder.calc_periods_for_year/9
File "lib/tzdata/period_builder.ex", line 180, in Tzdata.PeriodBuilder.calc_periods_for_year/9
File "lib/tzdata/period_builder.ex", line 185, in Tzdata.PeriodBuilder.calc_periods_for_year/9
File "lib/tzdata/period_builder.ex", line 180, in Tzdata.PeriodBuilder.calc_periods_for_year/9
File "lib/tzdata/period_builder.ex", line 185, in Tzdata.PeriodBuilder.calc_periods_for_year/9
File "lib/tzdata/period_builder.ex", line 180, in Tzdata.PeriodBuilder.calc_periods_for_year/9
Module "Elixir.Tzdata.ReleaseUpdater", in Tzdata.ReleaseUpdater.init/1
The four arguments to Tzdata.Util.first_matching_weekday_in_month/4
are 1932
, 4
, 7
, and []
, respectively.
We're using Timex 3.6.1 and Tzdata 1.0.1.
Today, We've got this error when startup and sometimes while running:
Elixir.ArgumentError: argument error
Module "ets", in :ets.new/2
File "lib/tzdata/data_builder.ex", line 11, in Tzdata.DataBuilder.load_and_save_table/0
File "lib/tzdata/release_updater.ex", line 41, in Tzdata.ReleaseUpdater.poll_for_update/0
File "lib/tzdata/release_updater.ex", line 17, in Tzdata.ReleaseUpdater.handle_info/2
File "gen_server.erl", line 616, in :gen_server.try_dispatch/4
File "gen_server.erl", line 686, in :gen_server.handle_msg/6
File "proc_lib.erl", line 247, in :proc_lib.init_p_do_apply/3
Module "Elixir.Tzdata.ReleaseUpdater", in Tzdata.ReleaseUpdater.init/1
Arguments passed to :ets.new/2
arg0 :tzdata_rel_2017c
arg1 [:set, :named_table]
We use Tzdata 0.5.12 and Timex 3.1.24.
"timex": {:hex, :timex, "3.1.24", "d198ae9783ac807721cca0c5535384ebdf99da4976be8cefb9665a9262a1e9e3", [:mix], [{:combine, "~> 0.7", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
"tzdata": {:hex, :tzdata, "0.5.12", "1c17b68692c6ba5b6ab15db3d64cc8baa0f182043d5ae9d4b6d35d70af76f67b", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
Hello, if the date-time hits exactly the start of a gap the following values are returned:
iex(11)> Tzdata.TimeZoneDatabase.time_zone_periods_from_wall_datetime(~N[2019-03-10 02:00:00], "America/Goose_Bay")
{:gap,
{%{
from_wall: ~N[2018-03-11 03:00:00],
std_offset: 3600,
until_wall: ~N[2018-11-04 02:00:00],
utc_offset: -14400,
zone_abbr: "ADT"
}, ~N[2018-11-04 02:00:00]},
{%{
from_wall: ~N[2019-03-10 03:00:00],
std_offset: 3600,
until_wall: ~N[2019-11-03 02:00:00],
utc_offset: -14400,
zone_abbr: "ADT"
}, ~N[2019-03-10 03:00:00]}}
iex(12)> Tzdata.TimeZoneDatabase.time_zone_periods_from_wall_datetime(~N[1884-01-01 00:00:00], "America/Goose_Bay")
** (UndefinedFunctionError) function nil.utc_off/0 is undefined. If you are using the dot syntax, such as map.field or module.function, make sure the left side of the dot is an atom or a map
nil.utc_off()
(tzdata) lib/tzdata/time_zone_database.ex:97: Tzdata.TimeZoneDatabase.old_tz_period_to_new/1
(tzdata) lib/tzdata/time_zone_database.ex:67: Tzdata.TimeZoneDatabase.gap_for_time_zone/2
iex(12)>
One second later everything is ok:
iex(14)> Tzdata.TimeZoneDatabase.time_zone_periods_from_wall_datetime(~N[2019-03-10 02:00:01], "America/Goose_Bay")
{:gap,
{%{
from_wall: ~N[2018-11-04 01:00:00],
std_offset: 0,
until_wall: ~N[2019-03-10 02:00:00],
utc_offset: -14400,
zone_abbr: "AST"
}, ~N[2019-03-10 02:00:00]},
{%{
from_wall: ~N[2019-03-10 03:00:00],
std_offset: 3600,
until_wall: ~N[2019-11-03 02:00:00],
utc_offset: -14400,
zone_abbr: "ADT"
}, ~N[2019-03-10 03:00:00]}}
iex(15)> Tzdata.TimeZoneDatabase.time_zone_periods_from_wall_datetime(~N[1884-01-01 00:00:01], "America/Goose_Bay")
{:gap,
{%{
from_wall: :min,
std_offset: 0,
until_wall: ~N[1884-01-01 00:00:00],
utc_offset: -14500,
zone_abbr: "LMT"
}, ~N[1884-01-01 00:00:00]},
{%{
from_wall: ~N[1884-01-01 00:30:48],
std_offset: 0,
until_wall: ~N[1918-01-01 00:00:00],
utc_offset: -12652,
zone_abbr: "NST"
}, ~N[1884-01-01 00:30:48]}}
iex(16)>
iex(1)> Tzdata.tzdata_version
"2019c"
$> mix hex.outdated tzdata
Current version 1.0.2 of dependency is up to date!
It would be cool, when DataLoader.download_new
would not crash on timeouts/etc.
A Logger.warn
would be nicer, instead of getting a alarm from Sentry :(
https://github.com/lau/tzdata/blob/master/lib/tzdata/data_loader.ex#L10
Anybody willing to work on this?
Seeing this in the console (1.3.3 does not have this issue)
Elixir 1.4.0-rc.1
Interactive Elixir (1.4.0-rc.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> [error] Tzdata.ReleaseUpdater :tzdata_release_updater received unexpected message in handle_info/2: {#Reference<0.0.1.1369>,
%Task{owner: #PID<0.310.0>, pid: #PID<0.375.0>, ref: #Reference<0.0.1.1585>}}
[error] Tzdata.ReleaseUpdater :tzdata_release_updater received unexpected message in handle_info/2: {:DOWN, #Reference<0.0.1.1369>, :process, #PID<0.310.0>, :normal}
Elixir 1.3.3
Interactive Elixir (1.3.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
Both run on the same project, using version 0.5.9
I think it's an utterly bad idea to have libraries auto-update. Frankly, I hate the concept. You change the behavior on production, you are pulling random stuff from the internet into production systems, it may or may not slow down startup by a random amount; it has all sorts of security implications I simply don't want to think about.
Please make the default to disable auto update; I'm fine if people want this (although I can think of exactly zero reasons why), but libraries should have secure defaults.
I observe the below error in my production logs.
[error] GenServer :tzdata_release_updater terminating
** (ArgumentError) argument error
(stdlib) :ets.lookup_element(:hackney_config, :mod_metrics, 2)
/Users/kodepet/Documents/Work/topup/deps/hackney/src/hackney_metrics.erl:26: :hackney_metrics.get_engine/0
/Users/kodepet/Documents/Work/topup/deps/hackney/src/hackney_connect.erl:78: :hackney_connect.create_connection/5
/Users/kodepet/Documents/Work/topup/deps/hackney/src/hackney_connect.erl:47: :hackney_connect.connect/5
/Users/kodepet/Documents/Work/topup/deps/hackney/src/hackney.erl:333: :hackney.request/5
(tzdata) lib/tzdata/http_client/hackney.ex:17: Tzdata.HTTPClient.Hackney.head/3
(tzdata) lib/tzdata/data_loader.ex:46: Tzdata.DataLoader.last_modified_of_latest_available/1
(tzdata) lib/tzdata/release_updater.ex:81: Tzdata.ReleaseUpdater.loaded_tzdata_matches_remote_last_modified?/0
(tzdata) lib/tzdata/release_updater.ex:42: Tzdata.ReleaseUpdater.poll_for_update/0
(tzdata) lib/tzdata/release_updater.ex:19: Tzdata.ReleaseUpdater.handle_info/2
(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:711: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: :check_if_time_to_update
State: []
We're getting this error intermittently and so we're assuming it's part of the autoupdate procedure that's crashing:
** Reason for termination ==
** {badarg,
[{ets,lookup,[tzdata_current_release,release_version],[]},
{'Elixir.Tzdata.ReleaseReader',current_release_from_table,0,
[{file,"lib/tzdata/release_reader.ex"},{line,47}]},
{'Elixir.Tzdata.ReleaseReader',simple_lookup,1,
[{file,"lib/tzdata/release_reader.ex"},{line,14}]},
{'Elixir.Tzdata.ReleaseReader',zone_and_link_list,0,
[{file,"lib/tzdata/release_reader.ex"},{line,7}]},
{'Elixir.Tzdata','zone_exists?',1,[{file,"lib/tzdata.ex"},{line,40}]},
{'Elixir.Timex.Timezone',name_of,1,
[{file,"lib/timezone/timezone.ex"},{line,142}]},
{'Elixir.Timex.Timezone',do_get,3,
[{file,"lib/timezone/timezone.ex"},{line,205}]},
{'Elixir.Timex.Timezone',convert,2,
[{file,"lib/timezone/timezone.ex"},{line,458}]}]}
{"Kernel pid terminated",application_controller,"{application_terminated,rtr,shutdown}"}
We have tzdata 0.5.12 and the tzdata version is currently 2017b on my local machine.
==> tzdata
Compiled lib/tzdata/parser_organizer.ex
Compiled lib/tzdata/release_parser.ex
Compiled lib/tzdata/util.ex
Compiled lib/tzdata/table_parser.ex
Compiled lib/tzdata/parser.ex
Compiled lib/tzdata/table_data.ex
Compiled lib/tzdata/leap_sec_parser.ex
Compiled lib/tzdata/basic_data.ex
Compiled lib/tzdata/period_builder.ex
Compiled lib/tzdata/far_future_dynamic_periods.ex
*** stack smashing detected ***: /usr/local/lib/erlang/erts-6.2/bin/beam terminated
Segmentation fault (core dumped)
In production we use a read only file system which causes problems when trying to update tzdata. We are running into an infinite loop where the system tries to update => write a file => crash => recover from crash => update. I know that there is an option to turn off auto updating (which we have since done) but I was wondering if there was a better way to engineer updates to the tz info.
Here are two proposals that I think would work:
Based on historical data, it looks like there are only around 9-10 changes to the tz database per year[0]. We could just automate the process of downloading the file and commiting a PR which would also bump the patch level of the library. This would allow people who can't auto update to get the most recent info.
Or
Change the auto update process to not rely on files. I think we should be able to hold everything in memory based on my quick overview of the update process. We lose the benefit of being able to read a cache from disk but I don't really think this is a show stopper in terms of perf since this is an async action anyway.
0: ftp://ftp.iana.org/tz/releases
I got this error after cleaning my deps and running mix deps.get
and then iex -S mix
:
18:16:19.924 [error] Task #PID<0.786.0> started from :tzdata_release_updater terminating
** (File.Error) could not stream priv/tmp_downloads/302817//pacificnew: no such file or directory
(elixir) lib/file/stream.ex:77: anonymous fn/2 in Enumerable.File.Stream.reduce/3
(elixir) lib/stream.ex:1084: anonymous fn/5 in Stream.resource/3
(elixir) lib/stream.ex:1247: Enumerable.Stream.do_each/4
(elixir) lib/enum.ex:1477: Enum.reduce/3
(elixir) lib/enum.ex:2248: Enum.to_list/1
(tzdata) lib/tzdata/parser.ex:16: Tzdata.Parser.process_file/1
(tzdata) lib/tzdata/basic_data_map.ex:8: anonymous fn/2 in Tzdata.BasicDataMap.from_files_in_dir/1
(elixir) lib/enum.ex:1088: Enum."-map/2-lists^map/1-0-"/2
Function: #Function<0.19695994/0 in Tzdata.ReleaseUpdater.init/1>
Args: []
This was surprising and I don't think it is appropriate to run the updater during the compilation step. It should only ever run when the main app is running.
This is version 0.5.2 of tzdata.
After updating to Elixir 1.2.1 I get the following error continously once i start my server
I use
{:tzdata, "~> 0.5.6"}
{:timex, "~> 0.19.2"},
[error] Task #PID<0.634.0> started from :tzdata_release_updater terminating
** (UndefinedFunctionError) undefined function Logger.log/3
(logger) Logger.log(:debug, "Tzdata polling for update.", [module: Tzdata.ReleaseUpdater, function: "poll_for_update/0", line: 30])
(tzdata) lib/tzdata/release_updater.ex:30: Tzdata.ReleaseUpdater.poll_for_update/0
(tzdata) lib/tzdata/release_updater.ex:22: Tzdata.ReleaseUpdater.check_if_time_to_update/0
(elixir) lib/task/supervised.ex:89: Task.Supervised.do_apply/2
(elixir) lib/task/supervised.ex:40: Task.Supervised.reply/5
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Function: #Function<0.63628506/0 in Tzdata.ReleaseUpdater.init/1>
Hi, experimenting with various Elixir time libraries - https://github.com/binarytemple/poc_elixir_calendars/tree/escript_broken
Everything works fine in IEX session. But when escripted there is a crash at startup within the Tzdata application.
I build like so:
mix do deps.compile, escript.build && ./poc_elixir_calendars
The error (formatted) is the following:
{:error, {:shutdown,
{:failed_to_start_child, Tzdata.EtsHolder,
{%ArgumentError{message: "unknown application: :tzdata"},
[
{Application, :app_dir, 1, [file: 'lib/application.ex', line: 372]},
{Application, :app_dir, 2, [file: 'lib/application.ex', line: 381]},
{Tzdata.EtsHolder, :release_dir, 0, [file: 'lib/tzdata/ets_holder.ex', line: 86]},
{Tzdata.EtsHolder, :make_sure_a_release_dir_exists, 0,
[file: 'lib/tzdata/ets_holder.ex', line: 70]},
{Tzdata.EtsHolder, :make_sure_a_release_is_on_file, 0,
[file: 'lib/tzdata/ets_holder.ex', line: 64]},
{Tzdata.EtsHolder, :init, 1, [file: 'lib/tzdata/ets_holder.ex', line: 10]},
{:gen_server, :init_it, 6, [file: 'gen_server.erl', line: 328]},
{:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 240]
}
]}}}}
The escript contains all the Tzdata files, including the ETS dump, '2016c.ets':
% zipinfo poc_elixir_calendars | egrep -i '(ets|tz)'
-rw---- 2.0 fat 1079 b- defN 31-Jul-16 21:14 tzdata.app
-rw---- 2.0 fat 11516 b- defN 31-Jul-16 21:14 Elixir.Calendar.DateTime.TzPeriod.beam
-rw---- 2.0 fat 5232 b- defN 31-Jul-16 21:14 Elixir.Tzdata.ReleaseUpdater.beam
-rw---- 2.0 fat 9372 b- defN 31-Jul-16 21:14 Elixir.Tzdata.DataLoader.beam
-rw---- 2.0 fat 3504 b- defN 31-Jul-16 21:14 Elixir.Tzdata.TableParser.beam
-rw---- 2.0 fat 3397782 b- defN 31-Jul-16 21:14 2016c.ets
-rw---- 2.0 fat 9932 b- defN 31-Jul-16 21:14 Elixir.Tzdata.Parser.beam
-rw---- 2.0 fat 12232 b- defN 31-Jul-16 21:14 Elixir.Tzdata.beam
-rw---- 2.0 fat 8292 b- defN 31-Jul-16 21:14 Elixir.Tzdata.DataBuilder.beam
-rw---- 2.0 fat 5060 b- defN 31-Jul-16 21:14 Elixir.Tzdata.ReleaseReader.beam
-rw---- 2.0 fat 3196 b- defN 31-Jul-16 21:14 Elixir.Tzdata.BasicDataMap.beam
-rw---- 2.0 fat 6116 b- defN 31-Jul-16 21:14 Elixir.Tzdata.ParserOrganizer.beam
-rw---- 2.0 fat 7640 b- defN 31-Jul-16 21:14 Elixir.Tzdata.EtsHolder.beam
-rw---- 2.0 fat 19732 b- defN 31-Jul-16 21:14 Elixir.Tzdata.Util.beam
-rw---- 2.0 fat 9368 b- defN 31-Jul-16 21:14 Elixir.Tzdata.FarFutureDynamicPeriods.beam
-rw---- 2.0 fat 5204 b- defN 31-Jul-16 21:14 Elixir.Tzdata.LeapSecParser.beam
-rw---- 2.0 fat 2236 b- defN 31-Jul-16 21:14 Elixir.Tzdata.App.beam
-rw---- 2.0 fat 1088 b- defN 31-Jul-16 21:14 Elixir.Tzdata.TableData.beam
-rw---- 2.0 fat 12828 b- defN 31-Jul-16 21:14 Elixir.Tzdata.PeriodBuilder.beam
Any suggestions?
Most time zone pickers (most oftenly a <select>
field) on the web show an offset with the time zone name; and time zones are ordered by offset (see pickers for Windows, Android, Google Calendar, ...).
Currently, I don't see any easy way to get the possible offsets for a time zone.
E.g. for Belgium it would return a list of two elements, +01:00 and +02:00.
Would it be possible to add such feature?
See also discussion on Elixir Forum:
https://elixirforum.com/t/list-of-time-zones-in-select-element/28532
Making it more operations compliant, and allow to update all tzdata in one run.
Add possibility to read tzdata from OS (which is on every Linux already installed and updated).
Make it sense?
Hey @lau, was updating Timex's tzdata dependency to 0.5.1 and hit the following error when calling Tzdata.canonical_zone_list
:
Erlang/OTP 18 [erts-7.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.0.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Tzdata.canonical_zone_list
** (ArgumentError) argument error
(stdlib) :ets.lookup(:tzdata_current_release, :release_version)
(tzdata) lib/tzdata/release_reader.ex:41: Tzdata.ReleaseReader.current_release_from_table/0
(tzdata) lib/tzdata/release_reader.ex:13: Tzdata.ReleaseReader.simple_lookup/1
(tzdata) lib/tzdata/release_reader.ex:5: Tzdata.ReleaseReader.zone_list/0
iex(1)>
I do millions of date time calculations per minute and ets begins to become a bottle neck after a while.
I just spun up a temporary work around using fast global and the semapahore library from discord, i'd love to see something like this make it's way into the library propery, preferably in a way that reduces the number of atoms required.
If you welcome the change and have directives I can begin going over the codebase more and release a more well designed solution for inclusion in future builds.
I'm on elixir 1.2.2, my deps are:
defp deps do
[
{:amqp, ">= 0.1.4"},
{:ecto, "~> 1.1"},
{:mariaex, "~> 0.6"},
{:ex_statsd, ">= 0.5.1"},
{:exrm, "~> 1.0"},
{:poison, "~> 1.0"},
{:credo, "~> 0.3", only: [:dev, :test]},
{:dialyxir, "~> 0.3", only: [:dev]},
{:timex, "~> 2.0"},
{:timex_ecto, "~> 1.0"},
{:httpoison, "~> 0.8.3"}
]
end
When I run the project (for example with iex -S mix) I get this after some seconds:
12:48:10.781 [error] Task #PID<0.3269.0> started from :tzdata_release_updater terminating
** (ArgumentError) argument error
:erlang.hd([])
(tzdata) lib/tzdata/data_loader.ex:62: Tzdata.DataLoader.do_latest_remote_poll_date/1
(tzdata) lib/tzdata/data_loader.ex:74: Tzdata.DataLoader.days_since_last_remote_poll/0
(tzdata) lib/tzdata/release_updater.ex:18: Tzdata.ReleaseUpdater.check_if_time_to_update/0
(elixir) lib/task/supervised.ex:89: Task.Supervised.do_apply/2
(elixir) lib/task/supervised.ex:40: Task.Supervised.reply/5
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Function: #Function<1.97472105/0 in Tzdata.ReleaseUpdater.init/1>
Args: []
I see following error whenever I do mix phoenix.server
at the start of my day
[error] GenServer :tzdata_release_updater terminating
** (ArgumentError) argument error
:erlang.hd([])
(tzdata) lib/tzdata/data_loader.ex:29: Tzdata.DataLoader.content_length_from_headers/1
(tzdata) lib/tzdata/data_loader.ex:51: Tzdata.DataLoader.do_latest_file_size/1
(tzdata) lib/tzdata/release_updater.ex:48: Tzdata.ReleaseUpdater.loaded_tzdata_matches_iana_file_size?/0
(tzdata) lib/tzdata/release_updater.ex:36: Tzdata.ReleaseUpdater.poll_for_update/0
(tzdata) lib/tzdata/release_updater.ex:17: Tzdata.ReleaseUpdater.handle_info/2
(stdlib) gen_server.erl:616: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:686: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: :check_if_time_to_update
State: []
Looks like some issue fetching time zone data or some other error?
I found some useful functions using the zone1970.tab
data, that allow for example to retrieve the timezone names based on a country code. This seems useful for example for helping a user to pick a timezone based on a country input.
The module providing such functions (TableData
) was found in the 0.1.x versions but has since then been removed.
69081f3
07efc3e
I was just curious to know why this has been removed.
Using v0.5.7
, in a compiled release, I find that tzdata errors out with :nxdomain
when autoupdate is set to :disabled
and the ets file is missing.
The error stacktrace (https://files.slack.com/files-pri/T08E7VBSA-F20JFDHT6/pasted_image_at_2016_08_11_03_28_pm.png
) makes me think it is trying to make a network connection (the test VM is "disconnected", and the error says :nxdomain
).
autoupdate = :disabled
Would you be opposed to a pull request moving the downlad_url value to config.exs?
We use this behind a firewall and can only get database updates with tzdata releases.
20:21:02.252 [error] GenServer :tzdata_release_updater terminating
** (FunctionClauseError) no function clause matching in Tzdata.Util.first_matching_weekday_in_month/4
(tzdata) lib/tzdata/util.ex:73: Tzdata.Util.first_matching_weekday_in_month(1932, 4, 7, [])
(tzdata) lib/tzdata/util.ex:329: Tzdata.Util.time_for_rule/2
(tzdata) lib/tzdata/period_builder.ex:161: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:180: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:185: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:180: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:185: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:180: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:185: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:180: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:185: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:180: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:185: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:180: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:185: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:180: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:185: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:180: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:185: Tzdata.PeriodBuilder.calc_periods_for_year/9
(tzdata) lib/tzdata/period_builder.ex:180: Tzdata.PeriodBuilder.calc_periods_for_year/9
Last message: :check_if_time_to_update
This might just be a weird blip on AWS. Is anyone seeing this on other infrastructure as well?
I'm using Elixir master and tzdata master.
iex> DateTime.now("America/New_Yor", Tzdata.TimeZoneDatabase)
** (MatchError) no match of right hand side value: {:error, :not_found}
(tzdata) lib/tzdata.ex:168: Tzdata.periods_for_time/3
(tzdata) lib/tzdata/time_zone_database.ex:15: Tzdata.TimeZoneDatabase.time_zone_period_from_utc_iso_days/2
(elixir) lib/calendar/datetime.ex:443: DateTime.shift_zone_for_iso_days_utc/5
Per DateTime.now
docs, it should return {:error, :time_zone_not_found}
instead.
Hello,
I'm seeing these regularly in CI:
** (ArgumentError) argument error
stacktrace:
(stdlib) :ets.lookup(:tzdata_rel_2019a, :zone_and_link_list)
(tzdata) lib/tzdata/release_reader.ex:16: Tzdata.ReleaseReader.simple_lookup/1
(tzdata) lib/tzdata/release_reader.ex:9: Tzdata.ReleaseReader.zone_and_link_list/0
(tzdata) lib/tzdata.ex:61: Tzdata.zone_exists?/1
(timex) lib/timezone/timezone.ex:358: Timex.Timezone.resolve/3
(timex) lib/timezone/timezone.ex:526: Timex.Timezone.convert/2
Versions:
Erlang/OTP 21 [erts-10.3.5.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]
Interactive Elixir (1.8.2) - press Ctrl+C to exit (type h() ENTER for help)
tzdata version "1.0.1"
Hello, I have a Phoenix application that I am running inside a Docker container (bitwalker/alpine-erlang:20.0). I'm using mix_docker for releases.
When I run my application locallyI don't receive this error, but when I run it inside my container this error happens every few seconds or so. I can't find anywhere in my application where I'm using tzdata
. I'm having a hard time tracking down what's causing this error. Any help you could provide would be much appreciated.
22:23:52.554 [error] GenServer :tzdata_release_updater terminating
** (File.Error) could not write to file "/opt/app/lib/tzdata-0.5.12/priv/tmp_downloads/335571_44358462/latest.tar.gz": no such file or directory
(elixir) lib/file.ex:831: File.write!/3
(tzdata) lib/tzdata/data_loader.ex:17: Tzdata.DataLoader.download_new/1
(tzdata) lib/tzdata/data_builder.ex:9: Tzdata.DataBuilder.load_and_save_table/0
(tzdata) lib/tzdata/release_updater.ex:41: Tzdata.ReleaseUpdater.poll_for_update/0
(tzdata) lib/tzdata/release_updater.ex:17: Tzdata.ReleaseUpdater.handle_info/2
(stdlib) gen_server.erl:616: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:686: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: :check_if_time_to_update
=CRASH REPORT==== 2-Nov-2017::22:23:52 ===
crasher:
initial call: Elixir.Tzdata.ReleaseUpdater:init/1
pid: <0.2586.0>
registered_name: tzdata_release_updater
exception error: #{'__exception__' => true,
'__struct__' => 'Elixir.File.Error',
action => <<"write to file">>,
path =>
<<"/opt/app/lib/tzdata-0.5.12/priv/tmp_downloads/335571_44358462/latest.tar.gz">>,
reason => enoent}
in function 'Elixir.File':'write!'/3 (lib/file.ex, line 831)
in call from 'Elixir.Tzdata.DataLoader':download_new/1 (lib/tzdata/data_loader.ex, line 17)
in call from 'Elixir.Tzdata.DataBuilder':load_and_save_table/0 (lib/tzdata/data_builder.ex, line 9)
in call from 'Elixir.Tzdata.ReleaseUpdater':poll_for_update/0 (lib/tzdata/release_updater.ex, line 41)
in call from 'Elixir.Tzdata.ReleaseUpdater':handle_info/2 (lib/tzdata/release_updater.ex, line 17)
in call from gen_server:try_dispatch/4 (gen_server.erl, line 616)
in call from gen_server:handle_msg/6 (gen_server.erl, line 686)
ancestors: [<0.1411.0>,<0.1410.0>]
message_queue_len: 0
messages: []
links: [<0.1411.0>]
dictionary: [{random_seed,{27839,21123,25074}}]
trap_exit: false
status: running
heap_size: 4185
stack_size: 27
reductions: 18757
neighbours:
=SUPERVISOR REPORT==== 2-Nov-2017::22:23:52 ===
Supervisor: {<0.1411.0>,'Elixir.Supervisor.Default'}
Context: child_terminated
Reason: {#{'__exception__' => true,
'__struct__' => 'Elixir.File.Error',
action => <<"write to file">>,
path =>
<<"/opt/app/lib/tzdata-0.5.12/priv/tmp_downloads/335571_44358462/latest.tar.gz">>,
reason => enoent},
[{'Elixir.File','write!',3,
[{file,"lib/file.ex"},{line,831}]},
{'Elixir.Tzdata.DataLoader',download_new,1,
[{file,"lib/tzdata/data_loader.ex"},{line,17}]},
{'Elixir.Tzdata.DataBuilder',load_and_save_table,0,
[{file,"lib/tzdata/data_builder.ex"},{line,9}]},
{'Elixir.Tzdata.ReleaseUpdater',poll_for_update,0,
[{file,"lib/tzdata/release_updater.ex"},{line,41}]},
{'Elixir.Tzdata.ReleaseUpdater',handle_info,2,
[{file,"lib/tzdata/release_updater.ex"},{line,17}]},
{gen_server,try_dispatch,4,
[{file,"gen_server.erl"},{line,616}]},
{gen_server,handle_msg,6,
[{file,"gen_server.erl"},{line,686}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,247}]}]}
Offender: [{pid,<0.2586.0>},
{id,'Elixir.Tzdata.ReleaseUpdater'},
{mfargs,{'Elixir.Tzdata.ReleaseUpdater',start_link,[]}},
{restart_type,permanent},
{shutdown,5000},
{child_type,worker}]
mix.exs
defp deps do
[
{:phoenix, "~> 1.3.0"},
{:phoenix_pubsub, "~> 1.0"},
{:phoenix_ecto, "~> 3.2"},
# {:mariaex, ">= 0.0.0"},
{:phoenix_html, "~> 2.10"},
{:gettext, "~> 0.11"},
{:cowboy, "~> 1.0"},
{:httpoison, "~> 0.13"},
{:poison, "~> 3.1"},
{:mix_docker, "~> 0.5.0"},
# Dev or test deps
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:hound, "~> 1.0", only: [:integration, :dev]},
{:bypass, "~> 0.8", only: [:integration, :dev]},
{:mox, "~> 0.2.0", only: [:test, :dev]},
]
end
We'd like to have reproducible builds, so having tzdata
opportunistically download new versions of the database is something I'd like to be able to disable. Ideally I'd also like to make the hackney
dependency optional.
With the "new" ETS-based timezone storage, we have noticed that the performance of the Tzdata.periods_for_time/3
function has dropped quite excessively.
tzdata 0.1.8:
benchmark name iterations average time
Tzdata.periods 100000000 0.07 µs/op
Tzdata.periods_for_time 10000000 0.16 µs/op
tzdata 0.5.10:
benchmark name iterations average time
Tzdata.periods 50000 51.36 µs/op
Tzdata.periods_for_time 20000 78.61 µs/op
Our use case is converting large amounts of dates from the database into DateTime
structs (using Timex), and we're now getting performance issues because of this conversion.
I'm wondering what the best solution is here (except for pinning our own tzdata
to 0.1.8);
Obviously compiling all timezone data into BEAM bytecode has its downsides (memory usage and not being able to update the tz database in runtime).
Benchmark code: https://github.com/arjan/tzdata_bench/blob/master/bench/tz_bench.exs
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.