diff --git a/doc/ReferenceOfClasses.md b/doc/ReferenceOfClasses.md index 1b8ea7a9..ae3cb41b 100644 --- a/doc/ReferenceOfClasses.md +++ b/doc/ReferenceOfClasses.md @@ -56,7 +56,7 @@ Attributes * `blog`: string * `collaborators`: integer * `company`: string -* `created_at`: datetime +* `created_at`: datetime.datetime * `disk_usage`: integer * `email`: string * `followers`: integer @@ -190,13 +190,13 @@ Class `Authorization` Attributes ---------- * `app`: `AuthorizationApplication` -* `created_at`: datetime +* `created_at`: datetime.datetime * `id`: integer * `note`: string * `note_url`: string * `scopes`: list of string * `token`: string -* `updated_at`: datetime +* `updated_at`: datetime.datetime * `url`: string Deletion @@ -258,13 +258,13 @@ Attributes ---------- * `body`: string * `commit_id`: string -* `created_at`: datetime +* `created_at`: datetime.datetime * `html_url`: string * `id`: integer * `line`: integer * `path`: string * `position`: integer -* `updated_at`: datetime +* `updated_at`: datetime.datetime * `url`: string * `user`: `NamedUser` @@ -313,10 +313,10 @@ Attributes * `acl`: string * `bucket`: string * `content_type`: string -* `created_at`: datetime +* `created_at`: datetime.datetime * `description`: string * `download_count`: integer -* `expirationdate`: datetime +* `expirationdate`: datetime.datetime * `html_url`: string * `id`: integer * `mime_type`: string @@ -340,7 +340,7 @@ Class `Event` Attributes ---------- * `actor`: `NamedUser` -* `created_at`: datetime +* `created_at`: datetime.datetime * `id`: string * `org`: `Organization` * `payload`: dict @@ -369,7 +369,7 @@ Class `Gist` Attributes ---------- * `comments`: integer -* `created_at`: datetime +* `created_at`: datetime.datetime * `description`: string * `files`: dict of string to `GistFile` * `fork_of`: `Gist` @@ -380,7 +380,7 @@ Attributes * `html_url`: string * `id`: string * `public`: bool -* `updated_at`: datetime +* `updated_at`: datetime.datetime * `url`: string * `user`: `NamedUser` @@ -418,9 +418,9 @@ Class `GistComment` Attributes ---------- * `body`: string -* `created_at`: datetime +* `created_at`: datetime.datetime * `id`: integer -* `updated_at`: datetime +* `updated_at`: datetime.datetime * `url`: string * `user`: `NamedUser` @@ -450,7 +450,7 @@ Class `GistHistoryState` Attributes ---------- * `change_status`: `CommitStats` -* `committed_at`: datetime +* `committed_at`: datetime.datetime * `url`: string * `user`: `NamedUser` * `version`: string @@ -460,8 +460,8 @@ Class `GitAuthor` Attributes ---------- -* `date`: datetime -* `timezone`: integer +* `date`: datetime.datetime +* `timezone`: datetime.timedelta * `email`: string * `name`: string @@ -557,12 +557,12 @@ Attributes ---------- * `active`: bool * `config`: dict -* `created_at`: datetime +* `created_at`: datetime.datetime * `events`: list of string * `id`: integer * `last_response`: `HookResponse` * `name`: string -* `updated_at`: datetime +* `updated_at`: datetime.datetime * `url`: string Deletion @@ -599,10 +599,10 @@ Attributes ---------- * `assignee`: `NamedUser` * `body`: string -* `closed_at`: datetime +* `closed_at`: datetime.datetime * `closed_by`: `NamedUser` * `comments`: integer -* `created_at`: datetime +* `created_at`: datetime.datetime * `html_url`: string * `id`: integer * `labels`: list of `Label` @@ -612,7 +612,7 @@ Attributes * `repository`: `Repository` * `state`: string * `title`: string -* `updated_at`: datetime +* `updated_at`: datetime.datetime * `url`: string * `user`: `NamedUser` @@ -655,9 +655,9 @@ Class `IssueComment` Attributes ---------- * `body`: string -* `created_at`: datetime +* `created_at`: datetime.datetime * `id`: integer -* `updated_at`: datetime +* `updated_at`: datetime.datetime * `url`: string * `user`: `NamedUser` @@ -677,7 +677,7 @@ Attributes ---------- * `actor`: `NamedUser` * `commit_id`: string -* `created_at`: datetime +* `created_at`: datetime.datetime * `event`: string * `id`: integer * `issue`: `Issue` @@ -717,10 +717,10 @@ Class `Milestone` Attributes ---------- * `closed_issues`: integer -* `created_at`: datetime +* `created_at`: datetime.datetime * `creator`: `NamedUser` * `description`: string -* `due_on`: datetime +* `due_on`: datetime.datetime * `id`: integer * `number`: integer * `open_issues`: integer @@ -755,7 +755,7 @@ Attributes * `collaborators`: integer * `company`: string * `contributions`: integer -* `created_at`: datetime +* `created_at`: datetime.datetime * `disk_usage`: integer * `email`: string * `followers`: integer @@ -824,7 +824,7 @@ Attributes * `blog`: string * `collaborators`: integer * `company`: string -* `created_at`: datetime +* `created_at`: datetime.datetime * `disk_usage`: integer * `email`: string * `followers`: integer @@ -935,10 +935,10 @@ Attributes * `base`: `PullRequestPart` * `body`: string * `changed_files`: integer -* `closed_at`: datetime +* `closed_at`: datetime.datetime * `comments`: integer * `commits`: integer -* `created_at`: datetime +* `created_at`: datetime.datetime * `deletions`: integer * `diff_url`: string * `head`: `PullRequestPart` @@ -947,14 +947,14 @@ Attributes * `issue_url`: string * `mergeable`: bool * `merged`: bool -* `merged_at`: datetime +* `merged_at`: datetime.datetime * `merged_by`: `NamedUser` * `number`: integer * `patch_url`: string * `review_comments`: integer * `state`: string * `title`: string -* `updated_at`: datetime +* `updated_at`: datetime.datetime * `url`: string * `user`: `NamedUser` @@ -997,13 +997,13 @@ Attributes ---------- * `body`: string * `commit_id`: string -* `created_at`: datetime +* `created_at`: datetime.datetime * `id`: integer * `original_commit_id`: string * `original_position`: integer * `path`: string * `position`: integer -* `updated_at`: datetime +* `updated_at`: datetime.datetime * `url`: string * `user`: `NamedUser` @@ -1042,7 +1042,7 @@ Class `Repository` Attributes ---------- * `clone_url`: string -* `created_at`: datetime +* `created_at`: datetime.datetime * `description`: string * `fork`: bool * `forks`: integer @@ -1063,12 +1063,12 @@ Attributes * `parent`: `Repository` * `permissions`: `Permissions` * `private`: bool -* `pushed_at`: datetime +* `pushed_at`: datetime.datetime * `size`: integer * `source`: `Repository` * `ssh_url`: string * `svn_url`: string -* `updated_at`: datetime +* `updated_at`: datetime.datetime * `url`: string * `watchers`: integer @@ -1207,7 +1207,7 @@ Issues * `labels`: list of `Label` * `sort`: string * `direction`: string - * `since`: datetime + * `since`: datetime.datetime * `legacy_search_issues( state, keyword )`: iterator of `Issue` * `state`: "open" or "closed" * `keyword`: string diff --git a/github/GithubObject.py b/github/GithubObject.py index ec187800..10d96d5c 100644 --- a/github/GithubObject.py +++ b/github/GithubObject.py @@ -50,7 +50,7 @@ class BasicGithubObject( object ): @staticmethod def _parseTimezone( s ): assert len( s ) == 25 - return int( s[ 19 : 22 ] ) + int( s[ 23 : 25 ] ) / 60. + return ( -1 if s[ 19 ] == '-' else 1 ) * datetime.timedelta( hours = int( s[ 20 : 22 ] ), minutes = int( s[ 23 : 25 ] ) ) class GithubObject( BasicGithubObject ): def __init__( self, requester, attributes, completed ): diff --git a/test/GitCommit.py b/test/GitCommit.py index 220ae0b9..961e9f17 100644 --- a/test/GitCommit.py +++ b/test/GitCommit.py @@ -24,11 +24,11 @@ class GitCommit( Framework.TestCase ): self.assertEqual( self.commit.author.name, "Vincent Jacques" ) self.assertEqual( self.commit.author.email, "vincent@vincent-jacques.net" ) self.assertEqual( self.commit.author.date, datetime.datetime( 2012, 4, 17, 10, 55, 16 ) ) - self.assertEqual( self.commit.author.timezone, -7 ) + self.assertEqual( self.commit.author.timezone, datetime.timedelta( hours = -7 ) ) self.assertEqual( self.commit.committer.name, "Vincent Jacques" ) self.assertEqual( self.commit.committer.email, "vincent@vincent-jacques.net" ) self.assertEqual( self.commit.committer.date, datetime.datetime( 2012, 4, 17, 10, 55, 16 ) ) - self.assertEqual( self.commit.committer.timezone, -7 ) + self.assertEqual( self.commit.committer.timezone, datetime.timedelta( hours = -7 ) ) self.assertEqual( self.commit.message, "Merge branch 'develop'\n" ) self.assertEqual( len( self.commit.parents ), 2 ) self.assertEqual( self.commit.parents[ 0 ].sha, "936f4a97f1a86392637ec002bbf89ff036a5062d" ) diff --git a/test/GitTag.py b/test/GitTag.py index c05809fa..2518ef06 100644 --- a/test/GitTag.py +++ b/test/GitTag.py @@ -28,7 +28,7 @@ class GitTag( Framework.TestCase ): self.assertEqual( self.tag.sha, "f5f37322407b02a80de4526ad88d5f188977bc3c" ) self.assertEqual( self.tag.tag, "v0.6" ) self.assertEqual( self.tag.tagger.date, datetime.datetime( 2012, 5, 10, 11, 14, 15 ) ) - self.assertEqual( self.tag.tagger.timezone, -7 ) + self.assertEqual( self.tag.tagger.timezone, datetime.timedelta( hours = -7 ) ) self.assertEqual( self.tag.tagger.email, "vincent@vincent-jacques.net" ) self.assertEqual( self.tag.tagger.name, "Vincent Jacques" ) self.assertEqual( self.tag.url, "https://api.github.com/repos/jacquev6/PyGithub/git/tags/f5f37322407b02a80de4526ad88d5f188977bc3c" ) diff --git a/test/IntegrationTest.py b/test/IntegrationTest.py index a2d966b6..4279eb38 100755 --- a/test/IntegrationTest.py +++ b/test/IntegrationTest.py @@ -52,6 +52,7 @@ from UserKey import * from PaginatedList import * from Issue33 import * from Issue50 import * +from Issue54 import * from Exceptions import * Framework.main() diff --git a/test/Issue54.py b/test/Issue54.py new file mode 100644 index 00000000..480728c0 --- /dev/null +++ b/test/Issue54.py @@ -0,0 +1,39 @@ +# Copyright 2012 Vincent Jacques +# vincent@vincent-jacques.net + +# This file is part of PyGithub. http://vincent-jacques.net/PyGithub + +# PyGithub is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License along with PyGithub. If not, see . + +import datetime + +import Framework + +class Issue54( Framework.TestCase ): + def setUp( self ): + Framework.TestCase.setUp( self ) + self.repo = self.g.get_user().get_repo( "PyGithub" ) + + def testPositiveIntegerTimezone( self ): + commit = self.repo.get_git_commit( "4303c5b90e2216d927155e9609436ccb8984c495" ) + self.assertEqual( commit.author.timezone, datetime.timedelta( hours = 7 ) ) + + def testNegativeIntegerTimezone( self ): + commit = self.repo.get_git_commit( "4303c5b90e2216d927155e9609436ccb8984c495" ) + self.assertEqual( commit.author.timezone, datetime.timedelta( hours = -7 ) ) + + # I was not able to find a real commit with an half integer timezone, so I *forged* the associated responses from Github. + # I *hope* they are what Github would send in that case + def testPositiveHalfIntegerTimezone( self ): + commit = self.repo.get_git_commit( "4303c5b90e2216d927155e9609436ccb8984c495" ) + self.assertEqual( commit.author.timezone, datetime.timedelta( hours = 7, minutes = 30 ) ) + + def testNegativeHalfIntegerTimezone( self ): + commit = self.repo.get_git_commit( "4303c5b90e2216d927155e9609436ccb8984c495" ) + self.assertEqual( commit.author.timezone, datetime.timedelta( hours = -7, minutes = -30 ) ) diff --git a/test/ReplayData/Issue54.setUp.txt b/test/ReplayData/Issue54.setUp.txt new file mode 100644 index 00000000..24c3651d --- /dev/null +++ b/test/ReplayData/Issue54.setUp.txt @@ -0,0 +1,10 @@ +GET /user {'Authorization': 'Basic login_and_password_removed'} null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4968'), ('content-length', '801'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"55f0187d26f5ca2e7103006d9837865c"'), ('date', 'Thu, 10 May 2012 19:05:23 GMT'), ('content-type', 'application/json; charset=utf-8')] +{"total_private_repos":5,"html_url":"https://github.com/jacquev6","type":"User","url":"https://api.github.com/users/jacquev6","owned_private_repos":5,"disk_usage":16676,"plan":{"private_repos":5,"collaborators":1,"space":614400,"name":"micro"},"public_gists":1,"avatar_url":"https://secure.gravatar.com/avatar/b68de5ae38616c296fa345d2b9df2225?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","blog":"http://vincent-jacques.net","private_gists":5,"login":"jacquev6","public_repos":10,"email":"vincent@vincent-jacques.net","collaborators":0,"created_at":"2010-07-09T06:10:06Z","company":"Criteo","location":"Paris, France","hireable":false,"followers":13,"following":24,"name":"Vincent Jacques","gravatar_id":"b68de5ae38616c296fa345d2b9df2225","bio":"","id":327146} + +GET /repos/jacquev6/PyGithub {'Authorization': 'Basic login_and_password_removed'} null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4967'), ('content-length', '1097'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"72a84ed8ad0d83f6a4c09dcd388c20a1"'), ('date', 'Thu, 10 May 2012 19:05:27 GMT'), ('content-type', 'application/json; charset=utf-8')] +{"homepage":"http://vincent-jacques.net/PyGithub","clone_url":"https://github.com/jacquev6/PyGithub.git","html_url":"https://github.com/jacquev6/PyGithub","url":"https://api.github.com/repos/jacquev6/PyGithub","has_downloads":true,"watchers":13,"permissions":{"admin":true,"pull":true,"push":true},"mirror_url":null,"has_wiki":false,"has_issues":true,"fork":false,"forks":2,"language":"Python","size":196,"description":"Python library implementing the full Github API v3","git_url":"git://github.com/jacquev6/PyGithub.git","private":false,"created_at":"2012-02-25T12:53:47Z","open_issues":15,"svn_url":"https://github.com/jacquev6/PyGithub","owner":{"url":"https://api.github.com/users/jacquev6","avatar_url":"https://secure.gravatar.com/avatar/b68de5ae38616c296fa345d2b9df2225?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","login":"jacquev6","gravatar_id":"b68de5ae38616c296fa345d2b9df2225","id":327146},"name":"PyGithub","pushed_at":"2012-05-10T18:49:21Z","id":3544490,"ssh_url":"git@github.com:jacquev6/PyGithub.git","updated_at":"2012-05-10T18:49:21Z"} + diff --git a/test/ReplayData/Issue54.testNegativeHalfIntegerTimezone.txt b/test/ReplayData/Issue54.testNegativeHalfIntegerTimezone.txt new file mode 100644 index 00000000..0e51b344 --- /dev/null +++ b/test/ReplayData/Issue54.testNegativeHalfIntegerTimezone.txt @@ -0,0 +1,5 @@ +GET /repos/jacquev6/PyGithub/git/commits/4303c5b90e2216d927155e9609436ccb8984c495 {'Authorization': 'Basic login_and_password_removed'} null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4966'), ('content-length', '910'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"eabd190c639b57d447ea6d3463da7aae"'), ('date', 'Thu, 10 May 2012 19:05:28 GMT'), ('content-type', 'application/json; charset=utf-8')] +{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/commits/4303c5b90e2216d927155e9609436ccb8984c495","message":"Merge branch 'develop'\n","committer":{"email":"vincent@vincent-jacques.net","date":"2012-04-17T10:55:16-07:00","name":"Vincent Jacques"},"sha":"4303c5b90e2216d927155e9609436ccb8984c495","parents":[{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/commits/936f4a97f1a86392637ec002bbf89ff036a5062d","sha":"936f4a97f1a86392637ec002bbf89ff036a5062d"},{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/commits/2a7e80e6421c5d4d201d60619068dea6bae612cb","sha":"2a7e80e6421c5d4d201d60619068dea6bae612cb"}],"tree":{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/trees/f492784d8ca837779650d1fb406a1a3587a764ad","sha":"f492784d8ca837779650d1fb406a1a3587a764ad"},"author":{"email":"vincent@vincent-jacques.net","date":"2012-04-17T10:55:16-07:30","name":"Vincent Jacques"}} + diff --git a/test/ReplayData/Issue54.testNegativeIntegerTimezone.txt b/test/ReplayData/Issue54.testNegativeIntegerTimezone.txt new file mode 100644 index 00000000..9a2b9e94 --- /dev/null +++ b/test/ReplayData/Issue54.testNegativeIntegerTimezone.txt @@ -0,0 +1,5 @@ +GET /repos/jacquev6/PyGithub/git/commits/4303c5b90e2216d927155e9609436ccb8984c495 {'Authorization': 'Basic login_and_password_removed'} null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4966'), ('content-length', '910'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"eabd190c639b57d447ea6d3463da7aae"'), ('date', 'Thu, 10 May 2012 19:05:28 GMT'), ('content-type', 'application/json; charset=utf-8')] +{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/commits/4303c5b90e2216d927155e9609436ccb8984c495","message":"Merge branch 'develop'\n","committer":{"email":"vincent@vincent-jacques.net","date":"2012-04-17T10:55:16-07:00","name":"Vincent Jacques"},"sha":"4303c5b90e2216d927155e9609436ccb8984c495","parents":[{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/commits/936f4a97f1a86392637ec002bbf89ff036a5062d","sha":"936f4a97f1a86392637ec002bbf89ff036a5062d"},{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/commits/2a7e80e6421c5d4d201d60619068dea6bae612cb","sha":"2a7e80e6421c5d4d201d60619068dea6bae612cb"}],"tree":{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/trees/f492784d8ca837779650d1fb406a1a3587a764ad","sha":"f492784d8ca837779650d1fb406a1a3587a764ad"},"author":{"email":"vincent@vincent-jacques.net","date":"2012-04-17T10:55:16-07:00","name":"Vincent Jacques"}} + diff --git a/test/ReplayData/Issue54.testPositiveHalfIntegerTimezone.txt b/test/ReplayData/Issue54.testPositiveHalfIntegerTimezone.txt new file mode 100644 index 00000000..d35c8dcd --- /dev/null +++ b/test/ReplayData/Issue54.testPositiveHalfIntegerTimezone.txt @@ -0,0 +1,5 @@ +GET /repos/jacquev6/PyGithub/git/commits/4303c5b90e2216d927155e9609436ccb8984c495 {'Authorization': 'Basic login_and_password_removed'} null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4966'), ('content-length', '910'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"eabd190c639b57d447ea6d3463da7aae"'), ('date', 'Thu, 10 May 2012 19:05:28 GMT'), ('content-type', 'application/json; charset=utf-8')] +{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/commits/4303c5b90e2216d927155e9609436ccb8984c495","message":"Merge branch 'develop'\n","committer":{"email":"vincent@vincent-jacques.net","date":"2012-04-17T10:55:16-07:00","name":"Vincent Jacques"},"sha":"4303c5b90e2216d927155e9609436ccb8984c495","parents":[{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/commits/936f4a97f1a86392637ec002bbf89ff036a5062d","sha":"936f4a97f1a86392637ec002bbf89ff036a5062d"},{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/commits/2a7e80e6421c5d4d201d60619068dea6bae612cb","sha":"2a7e80e6421c5d4d201d60619068dea6bae612cb"}],"tree":{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/trees/f492784d8ca837779650d1fb406a1a3587a764ad","sha":"f492784d8ca837779650d1fb406a1a3587a764ad"},"author":{"email":"vincent@vincent-jacques.net","date":"2012-04-17T10:55:16+07:30","name":"Vincent Jacques"}} + diff --git a/test/ReplayData/Issue54.testPositiveIntegerTimezone.txt b/test/ReplayData/Issue54.testPositiveIntegerTimezone.txt new file mode 100644 index 00000000..d614219b --- /dev/null +++ b/test/ReplayData/Issue54.testPositiveIntegerTimezone.txt @@ -0,0 +1,5 @@ +GET /repos/jacquev6/PyGithub/git/commits/4303c5b90e2216d927155e9609436ccb8984c495 {'Authorization': 'Basic login_and_password_removed'} null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4966'), ('content-length', '910'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"eabd190c639b57d447ea6d3463da7aae"'), ('date', 'Thu, 10 May 2012 19:05:28 GMT'), ('content-type', 'application/json; charset=utf-8')] +{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/commits/4303c5b90e2216d927155e9609436ccb8984c495","message":"Merge branch 'develop'\n","committer":{"email":"vincent@vincent-jacques.net","date":"2012-04-17T10:55:16-07:00","name":"Vincent Jacques"},"sha":"4303c5b90e2216d927155e9609436ccb8984c495","parents":[{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/commits/936f4a97f1a86392637ec002bbf89ff036a5062d","sha":"936f4a97f1a86392637ec002bbf89ff036a5062d"},{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/commits/2a7e80e6421c5d4d201d60619068dea6bae612cb","sha":"2a7e80e6421c5d4d201d60619068dea6bae612cb"}],"tree":{"url":"https://api.github.com/repos/jacquev6/PyGithub/git/trees/f492784d8ca837779650d1fb406a1a3587a764ad","sha":"f492784d8ca837779650d1fb406a1a3587a764ad"},"author":{"email":"vincent@vincent-jacques.net","date":"2012-04-17T10:55:16+07:00","name":"Vincent Jacques"}} +