neiam
/feedpug
feedpub
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
An impossible feed date reads as nil, not a crashed fetch
cb32133 · Gabe Morell · 2026-11-04 21:36
Message
{commit_body(@commit)}
Files changed
modified
lib/feed_pug/feeds/fetcher.ex
+13
−21
@@ -138,27 +138,19 @@ defmodule FeedPug.Feeds.Fetcher do
| 138 | 138 | |
| 139 | 139 | # Minimal RFC-822/1123 parser, e.g. "Wed, 02 Oct 2002 13:00:00 GMT". |
| 140 | 140 | defp parse_rfc822(str) do |
| 141 | − case Regex.run(~r/(\d{1,2})\s+(\w{3})\s+(\d{2,4})\s+(\d{2}):(\d{2})(?::(\d{2}))?/, str) do | |
| 142 | − [_, d, mon, y, h, min | rest] -> | |
| 143 | − case month_number(mon) do | |
| 144 | − {:ok, month} -> | |
| 145 | − year = String.to_integer(y) |> normalize_year() | |
| 146 | − sec = rest |> List.first() |> to_int(0) | |
| 147 | − | |
| 148 | − case DateTime.new( | |
| 149 | − Date.new!(year, month, String.to_integer(d)), | |
| 150 | − Time.new!(String.to_integer(h), String.to_integer(min), sec) | |
| 151 | − ) do | |
| 152 | − {:ok, dt} -> dt | |
| 153 | − _ -> nil | |
| 154 | − end | |
| 155 | − | |
| 156 | − :error -> | |
| 157 | − nil | |
| 158 | − end | |
| 159 | − | |
| 160 | − _ -> | |
| 161 | − nil | |
| 141 | + # An impossible date or time ("31 Feb", hour 25) reads as nil like any | |
| 142 | + # other unparseable string, rather than crashing the whole feed fetch. | |
| 143 | + with [_, d, mon, y, h, min | rest] <- | |
| 144 | + Regex.run(~r/(\d{1,2})\s+(\w{3})\s+(\d{2,4})\s+(\d{2}):(\d{2})(?::(\d{2}))?/, str), | |
| 145 | + {:ok, month} <- month_number(mon), | |
| 146 | + year = String.to_integer(y) |> normalize_year(), | |
| 147 | + sec = rest |> List.first() |> to_int(0), | |
| 148 | + {:ok, date} <- Date.new(year, month, String.to_integer(d)), | |
| 149 | + {:ok, time} <- Time.new(String.to_integer(h), String.to_integer(min), sec), | |
| 150 | + {:ok, dt} <- DateTime.new(date, time) do | |
| 151 | + dt | |
| 152 | + else | |
| 153 | + _ -> nil | |
| 162 | 154 | end |
| 163 | 155 | end |
| 164 | 156 |
modified
test/feed_pug/feeds/fetcher_test.exs
+15
−0
@@ -58,4 +58,19 @@ defmodule FeedPug.Feeds.FetcherTest do
| 58 | 58 | |
| 59 | 59 | assert Fetcher.parse_datetime(nil) == nil |
| 60 | 60 | end |
| 61 | + | |
| 62 | + test "parse_datetime reads an impossible RFC-822 date or time as nil" do | |
| 63 | + assert Fetcher.parse_datetime("Sat, 31 Feb 2024 13:00:00 GMT") == nil | |
| 64 | + assert Fetcher.parse_datetime("Wed, 02 Oct 2002 25:00:00 GMT") == nil | |
| 65 | + assert Fetcher.parse_datetime("Wed, 02 Oct 2002 13:61:00 GMT") == nil | |
| 66 | + assert Fetcher.parse_datetime("Wed, 02 Oct 2002 13:00:99 GMT") == nil | |
| 67 | + end | |
| 68 | + | |
| 69 | + test "an entry with an impossible date is still stored, not a crashed fetch" do | |
| 70 | + {:ok, feed} = Feeds.upsert_feed_by_url("https://ex.com/feed.xml") | |
| 71 | + rss = String.replace(@rss, "Wed, 02 Oct 2002", "Sat, 31 Feb 2024") | |
| 72 | + Req.Test.stub(__MODULE__, fn conn -> Req.Test.text(conn, rss) end) | |
| 73 | + | |
| 74 | + assert {:ok, [_item]} = Fetcher.refresh(feed, stub()) | |
| 75 | + end | |
| 61 | 76 | end |
Parents: fa42332