diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py
index e5e284fb5b..0742e60229 100644
--- a/src/calibre/__init__.py
+++ b/src/calibre/__init__.py
@@ -378,10 +378,11 @@ def strftime(fmt, t=None):
t = time.localtime()
early_year = t[0] < 1900
if early_year:
+ replacement = 1900 if t[0]%4 == 0 else 1901
fmt = fmt.replace('%Y', '_early year hack##')
t = list(t)
orig_year = t[0]
- t[0] = 1900
+ t[0] = replacement
ans = None
if iswindows:
if isinstance(fmt, unicode):
diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py
index 857b56216a..c0065c24c9 100644
--- a/src/calibre/library/catalog.py
+++ b/src/calibre/library/catalog.py
@@ -2235,7 +2235,7 @@ class EPUB_MOBI(CatalogPlugin):
cmTag['name'] = "author"
navStr = '%s | %s' % (self.formatNCXText(book['author'], dest='author'),
book['date'].split()[1])
- if 'tags' in book:
+ if 'tags' in book and len(book['tags']):
navStr = self.formatNCXText(navStr + ' | ' + ' · '.join(sorted(book['tags'])), dest='author')
cmTag.insert(0, NavigableString(navStr))
navPointVolumeTag.insert(2, cmTag)
@@ -3298,10 +3298,10 @@ class EPUB_MOBI(CatalogPlugin):
Deprecated HTML returns as HTML via BeautifulSoup()
'''
-
- # Explode lost CRs to \n\n
# Hackish - ignoring sentences ending or beginning in numbers to avoid
# confusion with decimal points.
+
+ # Explode lost CRs to \n\n
for lost_cr in re.finditer('([a-z])([\.\?!])([A-Z])',comments):
comments = comments.replace(lost_cr.group(),
'%s%s\n\n%s' % (lost_cr.group(1),
@@ -3323,6 +3323,8 @@ class EPUB_MOBI(CatalogPlugin):
# Convert solo returns to
comments = re.sub('[\r\n]','
', comments)
+ # Convert two hypens to emdash
+ comments = re.sub('--','—',comments)
soup = BeautifulSoup(comments)
result = BeautifulSoup()
diff --git a/src/calibre/utils/date.py b/src/calibre/utils/date.py
index 8b26ab02bc..9a433e3a6d 100644
--- a/src/calibre/utils/date.py
+++ b/src/calibre/utils/date.py
@@ -11,8 +11,21 @@ from datetime import datetime
from dateutil.parser import parse
from dateutil.tz import tzlocal, tzutc
+class SafeLocalTimeZone(tzlocal):
+ '''
+ Assume DST was not in effect for historical dates, if DST
+ data for the local timezone is not present in the operating system.
+ '''
+
+ def _isdst(self, dt):
+ try:
+ return tzlocal._isdst(self, dt)
+ except ValueError:
+ pass
+ return False
+
utc_tz = _utc_tz = tzutc()
-local_tz = _local_tz = tzlocal()
+local_tz = _local_tz = SafeLocalTimeZone()
def parse_date(date_string, assume_utc=False, as_utc=True, default=None):
'''
diff --git a/src/odf/element.py b/src/odf/element.py
index 9754c251b0..f0938ba53e 100644
--- a/src/odf/element.py
+++ b/src/odf/element.py
@@ -165,6 +165,18 @@ class Node(xml.dom.Node):
oldChild.parentNode = None
return oldChild
+ def __str__(self):
+ val = []
+ for c in self.childNodes:
+ val.append(str(c))
+ return ''.join(val)
+
+ def __unicode__(self):
+ val = []
+ for c in self.childNodes:
+ val.append(unicode(c))
+ return u''.join(val)
+
defproperty(Node, "firstChild", doc="First child node, or None.")
defproperty(Node, "lastChild", doc="Last child node, or None.")
@@ -221,6 +233,9 @@ class Text(Childless, Node):
self.data = data
def __str__(self):
+ return self.data.encode()
+
+ def __unicode__(self):
return self.data
def toXml(self,level,f):
@@ -452,3 +467,9 @@ class Element(Node):
obj = element(check_grammar=False)
return self._getElementsByObj(obj,[])
+ def isInstanceOf(self, element):
+ """ This is a check to see if the object is an instance of a type """
+ obj = element(check_grammar=False)
+ return self.qname == obj.qname
+
+
diff --git a/src/odf/grammar.py b/src/odf/grammar.py
index f71d72cca3..09ec02cbaa 100644
--- a/src/odf/grammar.py
+++ b/src/odf/grammar.py
@@ -4670,6 +4670,7 @@ allowed_attributes = {
(NUMBERNS,u'boolean-style'):(
(NUMBERNS,u'transliteration-language'),
(STYLENS,u'name'),
+ (STYLENS,u'display-name'),
(NUMBERNS,u'language'),
(NUMBERNS,u'title'),
(NUMBERNS,u'country'),
@@ -4681,6 +4682,7 @@ allowed_attributes = {
(NUMBERNS,u'currency-style'):(
(NUMBERNS,u'transliteration-language'),
(STYLENS,u'name'),
+ (STYLENS,u'display-name'),
(NUMBERNS,u'language'),
(NUMBERNS,u'title'),
(NUMBERNS,u'country'),
@@ -4698,6 +4700,7 @@ allowed_attributes = {
(NUMBERNS,u'date-style'):(
(NUMBERNS,u'transliteration-language'),
(STYLENS,u'name'),
+ (STYLENS,u'display-name'),
(NUMBERNS,u'language'),
(NUMBERNS,u'title'),
(NUMBERNS,u'country'),
@@ -4753,6 +4756,7 @@ allowed_attributes = {
(NUMBERNS,u'number-style'):(
(NUMBERNS,u'transliteration-language'),
(STYLENS,u'name'),
+ (STYLENS,u'display-name'),
(NUMBERNS,u'language'),
(NUMBERNS,u'title'),
(NUMBERNS,u'country'),
@@ -4765,6 +4769,7 @@ allowed_attributes = {
(NUMBERNS,u'percentage-style'):(
(NUMBERNS,u'transliteration-language'),
(STYLENS,u'name'),
+ (STYLENS,u'display-name'),
(NUMBERNS,u'language'),
(NUMBERNS,u'title'),
(NUMBERNS,u'country'),
@@ -4794,6 +4799,7 @@ allowed_attributes = {
(NUMBERNS,u'text-style'):(
(NUMBERNS,u'transliteration-language'),
(STYLENS,u'name'),
+ (STYLENS,u'display-name'),
(NUMBERNS,u'language'),
(NUMBERNS,u'title'),
(NUMBERNS,u'country'),
@@ -4806,6 +4812,7 @@ allowed_attributes = {
(NUMBERNS,u'transliteration-language'),
(NUMBERNS,u'transliteration-format'),
(STYLENS,u'name'),
+ (STYLENS,u'display-name'),
(NUMBERNS,u'language'),
(NUMBERNS,u'title'),
(NUMBERNS,u'country'),
diff --git a/src/odf/odf2xhtml.py b/src/odf/odf2xhtml.py
index b5df80f5d6..912e79cf3c 100644
--- a/src/odf/odf2xhtml.py
+++ b/src/odf/odf2xhtml.py
@@ -1,17 +1,17 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (C) 2006-2007 Søren Roug, European Environment Agency
-#
+#
# This library 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 2.1 of the License, or (at your option) any later version.
-#
+#
# This library 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 this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
@@ -47,7 +47,7 @@ from namespaces import ANIMNS, CHARTNS, CONFIGNS, DCNS, DR3DNS, DRAWNS, FONS, \
#
# The real styles are declared in the element. They have a
# family referring to the default-styles, and may have a parent style.
-#
+#
# Styles have scope. The same name can be used for both paragraph and
# character etc. styles Since CSS2 has no scope we use a prefix. (Not elegant)
# In ODF a style can have a parent, these parents can be chained.
@@ -376,6 +376,8 @@ class ODF2XHTML(handler.ContentHandler):
(OFFICENS, "text"):(self.s_office_text, self.e_office_text),
(OFFICENS, "scripts"):(self.s_ignorexml, None),
(PRESENTATIONNS, "notes"):(self.s_ignorexml, None),
+# (STYLENS, "default-page-layout"):(self.s_style_default_page_layout, self.e_style_page_layout),
+ (STYLENS, "default-page-layout"):(self.s_ignorexml, None),
(STYLENS, "default-style"):(self.s_style_default_style, self.e_style_default_style),
(STYLENS, "drawing-page-properties"):(self.s_style_handle_properties, None),
(STYLENS, "font-face"):(self.s_style_font_face, None),
@@ -834,8 +836,17 @@ class ODF2XHTML(handler.ContentHandler):
self.stylestack.append(self.currentstyle)
self.styledict[self.currentstyle] = {}
+ def s_style_default_page_layout(self, tag, attrs):
+ """ Collect the formatting for the default page layout style.
+ """
+ self.currentstyle = "@page"
+ self.stylestack.append(self.currentstyle)
+ self.styledict[self.currentstyle] = {}
+
def s_style_page_layout(self, tag, attrs):
""" Collect the formatting for the page layout style.
+ This won't work in CSS 2.1, as page identifiers are not allowed.
+ It is legal in CSS3, but the rest of the application doesn't specify when to use what page layout
"""
name = attrs[(STYLENS,'name')]
name = name.replace(".","_")