Skip to content

Commit

Permalink
add: format american style datetime
Browse files Browse the repository at this point in the history
  • Loading branch information
sudame committed Mar 9, 2020
1 parent 849313c commit e0ab2a8
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 46 deletions.
116 changes: 71 additions & 45 deletions lib/domain/dart_rss.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,25 @@ import 'package:dart_rss/domain/atom_feed.dart';
import 'package:dart_rss/domain/rss1_feed.dart';
import 'package:dart_rss/domain/rss_feed.dart';
import 'package:xml/xml.dart' as xml;
import 'package:intl/intl.dart';

extension SafeParseDateTime on DateTime {
static DateTime safeParse(String str) {
const dateFormatPatterns = [
'EEE, d MMM yyyy HH:mm:ss Z',
];

try {
return DateTime.parse(str);
} catch (_) {
return null;
for (final pattern in dateFormatPatterns) {
try {
final format = DateFormat(pattern);
return format.parse(str);
} catch (_) {}
}
}
return null;
}
}

Expand Down Expand Up @@ -40,56 +51,15 @@ class WebFeed {
switch (rssVersion) {
case RssVersion.RSS1:
final rss1Feed = Rss1Feed.parse(xmlString);
return WebFeed(
title: rss1Feed.title,
description: rss1Feed.description,
links: [rss1Feed.link],
items: rss1Feed.items
.map(
(item) => WebFeedItem(
title: item.title,
body: item.description ?? item.dc?.description,
updated: SafeParseDateTime.safeParse(item.dc?.date),
links: [item.link],
),
)
.toList(),
);
return WebFeed.fromRss1(rss1Feed);
break;
case RssVersion.RSS2:
final rss2Feed = RssFeed.parse(xmlString);
return WebFeed(
title: rss2Feed.title,
description: rss2Feed.description,
links: [rss2Feed.link],
items: rss2Feed.items
.map(
(item) => WebFeedItem(
title: item.title,
body: item.description ?? item.dc?.description,
updated: SafeParseDateTime.safeParse(item.dc?.date),
),
)
.toList(),
);
return WebFeed.fromRss2(rss2Feed);
break;
case RssVersion.Atom:
final atomFeed = AtomFeed.parse(xmlString);
return WebFeed(
title: atomFeed.title,
description: atomFeed.subtitle,
links: atomFeed.links.map((atomLink) => atomLink.href).toList(),
items: atomFeed.items
.map(
(item) => WebFeedItem(
title: item.title,
body: item.summary,
updated: SafeParseDateTime.safeParse(item.updated),
links: item.links.map((atomLink) => atomLink.href).toList(),
),
)
.toList(),
);
return WebFeed.fromAtom(atomFeed);
break;
case RssVersion.Unknown:
throw Error.safeToString(
Expand All @@ -100,6 +70,62 @@ class WebFeed {
}
}

static WebFeed fromRss1(Rss1Feed rss1feed) {
return WebFeed(
title: rss1feed.title ?? rss1feed.dc.title ?? '',
description: rss1feed.description ?? rss1feed.dc?.description ?? '',
links: [rss1feed.link],
items: rss1feed.items
.map(
(item) => WebFeedItem(
title: item.title ?? item.dc?.title ?? '',
body: item.description ?? item.dc?.description ?? '',
updated: SafeParseDateTime.safeParse(item.dc?.date),
links: [item.link],
),
)
.toList(),
);
}

static WebFeed fromRss2(RssFeed rssFeed) {
return WebFeed(
title: rssFeed.title ?? rssFeed.dc.title ?? '',
description: rssFeed.description ?? rssFeed.dc.description ?? '',
links: [rssFeed.link],
items: rssFeed.items
.map(
(item) => WebFeedItem(
title: item.title ?? item.dc.title ?? '',
body: item.description ?? item.dc.description ?? '',
updated: SafeParseDateTime.safeParse(item.pubDate) ??
SafeParseDateTime.safeParse(item.dc.date),
links: [item.link],
),
)
.toList(),
);
}

static WebFeed fromAtom(AtomFeed atomFeed) {
return WebFeed(
title: atomFeed.title,
description: atomFeed.subtitle,
links: atomFeed.links.map((atomLink) => atomLink.href).toList(),
items: atomFeed.items
.map(
(item) => WebFeedItem(
title: item.title,
body: item.summary ?? item.content,
updated: SafeParseDateTime.safeParse(item.updated) ??
SafeParseDateTime.safeParse(item.published),
links: item.links.map((atomLink) => atomLink.href).toList(),
),
)
.toList(),
);
}

static Future<WebFeed> fromUrl(String url) async {
final response = await http.get(url);
return fromXmlString(response.body);
Expand Down
2 changes: 2 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ dependencies:
xml: ^3.0.0
http: ^0.11.0
meta: ^1.0.0
intl: any

dev_dependencies:
test: ^1.0.0
27 changes: 27 additions & 0 deletions test/real_rss_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'package:dart_rss/dart_rss.dart';
import 'package:test/test.dart';

void main() {
group('Can this library use for real rss xml?', () {
const testFeeds = {
'pub.dev feed': 'https://pub.dev/feed.atom',
'Flutter Weekly':
'https://us17.campaign-archive.com/feed?u=c8d8d18b6e2c6316ddc1d48a0&id=47548a283b',
'jQuery blog': 'http://blog.jquery.com/feed/', // <- not use ISO8601
'hatena sample': 'https://b.hatena.ne.jp/sample/bookmark.rss', // <- RSS1
};

for (final title in testFeeds.keys) {
final url = testFeeds[title];
test(title, () async {
// given
final feed = await WebFeed.fromUrl(url);

// then
expect(feed.title.isNotEmpty, true);
expect(feed.items.first.updated is DateTime, true);
expect(feed.items.first.links.isNotEmpty, true);
});
}
});
}
23 changes: 23 additions & 0 deletions test/safe_parse_date_time_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import 'package:dart_rss/dart_rss.dart';
import 'package:test/test.dart';

void main() {
group('about SafeParseDateTime, ', () {
test('it can parse ISO-8601', () {
final date = SafeParseDateTime.safeParse('2018-04-06T13:02:47Z');

expect(date.year, 2018);
expect(date.month, 4);
expect(date.day, 6);
});

test('it can parse American-English-Format', () {
final date =
SafeParseDateTime.safeParse('Tue, 02 Jul 2019 16:47:24 +0000');

expect(date.year, 2019);
expect(date.month, 7);
expect(date.day, 2);
});
});
}
3 changes: 2 additions & 1 deletion test/webfeed_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ void main() {
rss2Feed.items.first.body,
'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
);
expect(rss2Feed.items.first.updated, null);
expect(rss2Feed.items.first.updated,
DateTime.parse('2018-03-26 14:00:00.000'));
});
});
}

0 comments on commit e0ab2a8

Please sign in to comment.