   (let ((trim (replace-regexp-in-string "[\n\t]+" " " (or name ""))))
     (replace-regexp-in-string "^ +\\| +$" "" trim)))
 
+(defun elfeed-generate-id (&optional content)
+  "Generate an ID based on CONTENT or from the current time."
+  (concat "urn:sha1:" (sha1 (format "%s" (or content (float-time))))))
+
 (defun elfeed-entries-from-atom (url xml)
   "Turn parsed Atom content into a list of elfeed-entry structs."
   (let* ((feed-id url)

                 (anylink (xml-query '(link :href) entry))
                 (altlink (xml-query '(link [rel "alternate"] :href) entry))
                 (link (or altlink anylink))
                 (id (or (xml-query '(id *) entry) link))
                 (date (or (xml-query '(published *) entry)
                           (xml-query '(updated *) entry)
                           (xml-query '(date *) entry)))
                 (content (or (xml-query '(content *) entry)
                              (xml-query '(summary *) entry)))
                 (type (or (xml-query '(content :type) entry)
                           (xml-query '(summary :type) entry)
                           ""))

          (let* ((title (or (xml-query '(title *) item) ""))
                 (link (xml-query '(link *) item))
                 (guid (xml-query '(guid *) item))
                 (date (or (xml-query '(pubDate *) item)
                           (xml-query '(date *) item)))
                 (description (xml-query '(description *) item))
                 (id (or guid link (elfeed-generate-id description)))
                 (etags (xml-query-all '(enclosure) item))
                 (enclosures (loop for enclosure in etags
                                   for wrap = (list enclosure)
