mirror of
https://github.com/gryf/ebook-converter.git
synced 2026-03-17 15:23:43 +01:00
Move strftime to util.date module
In this patch strftime function is moved out of main __init__.py module to util.date, where it belongs.
This commit is contained in:
@@ -3,7 +3,6 @@ import os
|
|||||||
import pkg_resources
|
import pkg_resources
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import time
|
|
||||||
import mimetypes
|
import mimetypes
|
||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
@@ -13,10 +12,11 @@ try:
|
|||||||
except EnvironmentError:
|
except EnvironmentError:
|
||||||
os.chdir(os.path.expanduser('~'))
|
os.chdir(os.path.expanduser('~'))
|
||||||
|
|
||||||
from ebook_converter.constants_old import iswindows, islinux, isfrozen, \
|
from ebook_converter import constants_old
|
||||||
isbsd, preferred_encoding, __appname__, __version__, __author__, \
|
from ebook_converter.constants_old import islinux, isfrozen, \
|
||||||
|
isbsd, __appname__, __version__, __author__, \
|
||||||
win32event, win32api, winerror, fcntl, \
|
win32event, win32api, winerror, fcntl, \
|
||||||
filesystem_encoding, plugins, config_dir
|
config_dir
|
||||||
from ebook_converter.startup import winutil, winutilerror
|
from ebook_converter.startup import winutil, winutilerror
|
||||||
from ebook_converter.utils.icu import safe_chr
|
from ebook_converter.utils.icu import safe_chr
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ def guess_extension(*args, **kwargs):
|
|||||||
|
|
||||||
def unicode_path(path, abs=False):
|
def unicode_path(path, abs=False):
|
||||||
if isinstance(path, bytes):
|
if isinstance(path, bytes):
|
||||||
path = path.decode(filesystem_encoding)
|
path = path.decode(constants_old.filesystem_encoding)
|
||||||
if abs:
|
if abs:
|
||||||
path = os.path.abspath(path)
|
path = os.path.abspath(path)
|
||||||
return path
|
return path
|
||||||
@@ -68,9 +68,10 @@ def sanitize_file_name(name, substitute='_'):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if isinstance(name, bytes):
|
if isinstance(name, bytes):
|
||||||
name = name.decode(filesystem_encoding, 'replace')
|
name = name.decode(constants_old.filesystem_encoding, 'replace')
|
||||||
if isinstance(substitute, bytes):
|
if isinstance(substitute, bytes):
|
||||||
substitute = substitute.decode(filesystem_encoding, 'replace')
|
substitute = substitute.decode(constants_old.filesystem_encoding,
|
||||||
|
'replace')
|
||||||
chars = (substitute
|
chars = (substitute
|
||||||
if c in _filename_sanitize_unicode else c for c in name)
|
if c in _filename_sanitize_unicode else c for c in name)
|
||||||
one = ''.join(chars)
|
one = ''.join(chars)
|
||||||
@@ -99,7 +100,8 @@ def prints(*args, **kwargs):
|
|||||||
"""
|
"""
|
||||||
file = kwargs.get('file', sys.stdout)
|
file = kwargs.get('file', sys.stdout)
|
||||||
file = getattr(file, 'buffer', file)
|
file = getattr(file, 'buffer', file)
|
||||||
enc = 'utf-8' if os.getenv('CALIBRE_WORKER') else preferred_encoding
|
enc = ('utf-8' if os.getenv('CALIBRE_WORKER')
|
||||||
|
else constants_old.preferred_encoding)
|
||||||
sep = kwargs.get('sep', ' ')
|
sep = kwargs.get('sep', ' ')
|
||||||
if not isinstance(sep, bytes):
|
if not isinstance(sep, bytes):
|
||||||
sep = sep.encode(enc)
|
sep = sep.encode(enc)
|
||||||
@@ -110,7 +112,7 @@ def prints(*args, **kwargs):
|
|||||||
count = 0
|
count = 0
|
||||||
for i, arg in enumerate(args):
|
for i, arg in enumerate(args):
|
||||||
if isinstance(arg, str):
|
if isinstance(arg, str):
|
||||||
if iswindows:
|
if constants_old.iswindows:
|
||||||
from ebook_converter.utils.terminal import Detect
|
from ebook_converter.utils.terminal import Detect
|
||||||
cs = Detect(file)
|
cs = Detect(file)
|
||||||
if cs.is_console:
|
if cs.is_console:
|
||||||
@@ -257,40 +259,6 @@ def walk(dir):
|
|||||||
yield os.path.join(record[0], f)
|
yield os.path.join(record[0], f)
|
||||||
|
|
||||||
|
|
||||||
def strftime(fmt, t=None):
|
|
||||||
"""
|
|
||||||
A version of strftime that returns unicode strings and tries to handle
|
|
||||||
dates before 1900
|
|
||||||
"""
|
|
||||||
if not fmt:
|
|
||||||
return ''
|
|
||||||
if t is None:
|
|
||||||
t = time.localtime()
|
|
||||||
if hasattr(t, 'timetuple'):
|
|
||||||
t = t.timetuple()
|
|
||||||
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] = replacement
|
|
||||||
t = time.struct_time(t)
|
|
||||||
ans = None
|
|
||||||
if iswindows:
|
|
||||||
if isinstance(fmt, bytes):
|
|
||||||
fmt = fmt.decode('mbcs', 'replace')
|
|
||||||
fmt = fmt.replace('%e', '%#d')
|
|
||||||
ans = plugins['winutil'][0].strftime(fmt, t)
|
|
||||||
else:
|
|
||||||
ans = time.strftime(fmt, t)
|
|
||||||
if isinstance(ans, bytes):
|
|
||||||
ans = ans.decode(preferred_encoding, 'replace')
|
|
||||||
if early_year:
|
|
||||||
ans = ans.replace('_early year hack##', str(orig_year))
|
|
||||||
return ans
|
|
||||||
|
|
||||||
|
|
||||||
def my_unichr(num):
|
def my_unichr(num):
|
||||||
try:
|
try:
|
||||||
return safe_chr(num)
|
return safe_chr(num)
|
||||||
@@ -380,14 +348,15 @@ def prepare_string_for_xml(raw, attribute=False):
|
|||||||
return raw
|
return raw
|
||||||
|
|
||||||
|
|
||||||
def force_unicode(obj, enc=preferred_encoding):
|
def force_unicode(obj, enc=constants_old.preferred_encoding):
|
||||||
if isinstance(obj, bytes):
|
if isinstance(obj, bytes):
|
||||||
try:
|
try:
|
||||||
obj = obj.decode(enc)
|
obj = obj.decode(enc)
|
||||||
except Exception:
|
except Exception:
|
||||||
try:
|
try:
|
||||||
obj = obj.decode(filesystem_encoding if enc ==
|
obj = obj.decode(constants_old.filesystem_encoding
|
||||||
preferred_encoding else preferred_encoding)
|
if enc == constants_old.preferred_encoding
|
||||||
|
else constants_old.preferred_encoding)
|
||||||
except Exception:
|
except Exception:
|
||||||
try:
|
try:
|
||||||
obj = obj.decode('utf-8')
|
obj = obj.decode('utf-8')
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ from ebook_converter.ebooks.conversion.preprocess import HTMLPreProcessor
|
|||||||
from ebook_converter.ptempfile import PersistentTemporaryDirectory
|
from ebook_converter.ptempfile import PersistentTemporaryDirectory
|
||||||
from ebook_converter.utils.date import parse_date
|
from ebook_converter.utils.date import parse_date
|
||||||
from ebook_converter.utils.zipfile import ZipFile
|
from ebook_converter.utils.zipfile import ZipFile
|
||||||
from ebook_converter import extract, walk, filesystem_encoding
|
from ebook_converter import extract, walk
|
||||||
from ebook_converter.constants_old import __version__
|
from ebook_converter.constants_old import __version__, filesystem_encoding
|
||||||
|
|
||||||
|
|
||||||
DEBUG_README=b'''
|
DEBUG_README=b'''
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ from math import ceil, floor
|
|||||||
|
|
||||||
import bs4
|
import bs4
|
||||||
|
|
||||||
from ebook_converter import (
|
from ebook_converter import __appname__, entity_to_unicode, fit_image, \
|
||||||
__appname__, entity_to_unicode, fit_image, force_unicode, preferred_encoding
|
force_unicode
|
||||||
)
|
from ebook_converter.constants_old import filesystem_encoding, \
|
||||||
from ebook_converter.constants_old import filesystem_encoding
|
preferred_encoding
|
||||||
from ebook_converter.devices.interface import DevicePlugin as Device
|
from ebook_converter.devices.interface import DevicePlugin as Device
|
||||||
from ebook_converter.ebooks import ConversionError
|
from ebook_converter.ebooks import ConversionError
|
||||||
from ebook_converter.ebooks.BeautifulSoup import html5_parser
|
from ebook_converter.ebooks.BeautifulSoup import html5_parser
|
||||||
|
|||||||
@@ -8,12 +8,11 @@ import urllib.parse
|
|||||||
from xml.sax import saxutils
|
from xml.sax import saxutils
|
||||||
|
|
||||||
from ebook_converter import constants as const
|
from ebook_converter import constants as const
|
||||||
from ebook_converter import strftime
|
from ebook_converter.utils import date
|
||||||
from ebook_converter.constants_old import iswindows
|
from ebook_converter.constants_old import iswindows
|
||||||
from ebook_converter.ebooks.oeb import base
|
from ebook_converter.ebooks.oeb import base
|
||||||
from ebook_converter.ebooks.oeb.base import XPath, xml2text, urlnormalize
|
from ebook_converter.ebooks.oeb.base import XPath, xml2text, urlnormalize
|
||||||
from ebook_converter.library.comments import comments_to_html, markdown
|
from ebook_converter.library.comments import comments_to_html, markdown
|
||||||
from ebook_converter.utils.date import is_date_undefined, as_local_time
|
|
||||||
from ebook_converter.ebooks.chardet import strip_encoding_declarations
|
from ebook_converter.ebooks.chardet import strip_encoding_declarations
|
||||||
from ebook_converter.ebooks.metadata import fmt_sidx, rating_to_stars
|
from ebook_converter.ebooks.metadata import fmt_sidx, rating_to_stars
|
||||||
|
|
||||||
@@ -272,11 +271,11 @@ def render_jacket(mi, output_profile, alt_title='Unknown', alt_tags=[],
|
|||||||
publisher = saxutils.escape(publisher)
|
publisher = saxutils.escape(publisher)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if is_date_undefined(mi.pubdate):
|
if date.is_date_undefined(mi.pubdate):
|
||||||
pubdate = ''
|
pubdate = ''
|
||||||
else:
|
else:
|
||||||
dt = as_local_time(mi.pubdate)
|
dt = date.as_local_time(mi.pubdate)
|
||||||
pubdate = strftime('%Y', dt.timetuple())
|
pubdate = date.strftime('%Y', dt.timetuple())
|
||||||
except Exception:
|
except Exception:
|
||||||
pubdate = ''
|
pubdate = ''
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import re, codecs, os, numbers
|
import re, codecs, os, numbers
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
from ebook_converter import strftime
|
from ebook_converter.utils import date
|
||||||
from ebook_converter.customize import CatalogPlugin
|
from ebook_converter.customize import CatalogPlugin
|
||||||
from ebook_converter.library.catalogs import FIELDS, TEMPLATE_ALLOWED_FIELDS
|
from ebook_converter.library.catalogs import FIELDS, TEMPLATE_ALLOWED_FIELDS
|
||||||
from ebook_converter.customize.conversion import DummyReporter
|
from ebook_converter.customize.conversion import DummyReporter
|
||||||
@@ -206,7 +206,7 @@ class BIBTEX(CatalogPlugin):
|
|||||||
|
|
||||||
elif field == 'pubdate' :
|
elif field == 'pubdate' :
|
||||||
bibtex_entry.append('year = "%s"' % item.year)
|
bibtex_entry.append('year = "%s"' % item.year)
|
||||||
bibtex_entry.append('month = "%s"' % bibtexdict.utf8ToBibtex(strftime("%b", item)))
|
bibtex_entry.append('month = "%s"' % bibtexdict.utf8ToBibtex(date.strftime("%b", item)))
|
||||||
|
|
||||||
elif field.startswith('#') and isinstance(item, (str, bytes)):
|
elif field.startswith('#') and isinstance(item, (str, bytes)):
|
||||||
bibtex_entry.append('custom_%s = "%s"' % (field[1:],
|
bibtex_entry.append('custom_%s = "%s"' % (field[1:],
|
||||||
@@ -392,7 +392,7 @@ class BIBTEX(CatalogPlugin):
|
|||||||
|
|
||||||
outfile.write('%%%Calibre catalog\n%%%{0} entries in catalog\n\n'.format(nb_entries))
|
outfile.write('%%%Calibre catalog\n%%%{0} entries in catalog\n\n'.format(nb_entries))
|
||||||
outfile.write('@preamble{"This catalog of %d entries was generated by calibre on %s"}\n\n'
|
outfile.write('@preamble{"This catalog of %d entries was generated by calibre on %s"}\n\n'
|
||||||
% (nb_entries, strftime("%A, %d. %B %Y %H:%M")))
|
% (nb_entries, date.strftime("%A, %d. %B %Y %H:%M")))
|
||||||
|
|
||||||
for entry in data:
|
for entry in data:
|
||||||
outfile.write(create_bibtex_entry(entry, fields, bib_entry, template_citation,
|
outfile.write(create_bibtex_entry(entry, fields, bib_entry, template_citation,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import datetime, os, time
|
import datetime, os, time
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
from ebook_converter import strftime
|
from ebook_converter.utils import date
|
||||||
from ebook_converter.customize import CatalogPlugin
|
from ebook_converter.customize import CatalogPlugin
|
||||||
from ebook_converter.customize.conversion import OptionRecommendation, DummyReporter
|
from ebook_converter.customize.conversion import OptionRecommendation, DummyReporter
|
||||||
from ebook_converter.library import current_library_name
|
from ebook_converter.library import current_library_name
|
||||||
@@ -254,8 +254,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
opts.fmt = self.fmt = path_to_output.rpartition('.')[2]
|
opts.fmt = self.fmt = path_to_output.rpartition('.')[2]
|
||||||
|
|
||||||
# Add local options
|
# Add local options
|
||||||
opts.creator = '%s, %s %s, %s' % (strftime('%A'), strftime('%B'), strftime('%d').lstrip('0'), strftime('%Y'))
|
opts.creator = '%s, %s %s, %s' % (date.strftime('%A'), date.strftime('%B'), date.strftime('%d').lstrip('0'), date.strftime('%Y'))
|
||||||
opts.creator_sort_as = '%s %s' % ('calibre', strftime('%Y-%m-%d'))
|
opts.creator_sort_as = '%s %s' % ('calibre', date.strftime('%Y-%m-%d'))
|
||||||
opts.connected_kindle = False
|
opts.connected_kindle = False
|
||||||
|
|
||||||
# Finalize output_profile
|
# Finalize output_profile
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import re
|
import re
|
||||||
from datetime import datetime, time as dtime, timedelta, MINYEAR, MAXYEAR
|
import datetime
|
||||||
from functools import partial
|
import time
|
||||||
|
import functools
|
||||||
|
|
||||||
from ebook_converter import strftime
|
|
||||||
from ebook_converter.constants_old import iswindows, isosx, plugins, preferred_encoding
|
from ebook_converter.constants_old import iswindows, isosx, plugins, preferred_encoding
|
||||||
from ebook_converter.utils.iso8601 import utc_tz, local_tz, UNDEFINED_DATE
|
from ebook_converter.utils.iso8601 import utc_tz, local_tz, UNDEFINED_DATE
|
||||||
from ebook_converter.utils.localization import lcdata
|
from ebook_converter.utils.localization import lcdata
|
||||||
@@ -46,8 +46,8 @@ else:
|
|||||||
except:
|
except:
|
||||||
parse_date_day_first = False
|
parse_date_day_first = False
|
||||||
|
|
||||||
DEFAULT_DATE = datetime(2000,1,1, tzinfo=utc_tz)
|
DEFAULT_DATE = datetime.datetime(2000,1,1, tzinfo=utc_tz)
|
||||||
EPOCH = datetime(1970, 1, 1, tzinfo=_utc_tz)
|
EPOCH = datetime.datetime(1970, 1, 1, tzinfo=_utc_tz)
|
||||||
|
|
||||||
|
|
||||||
def is_date_undefined(qt_or_dt):
|
def is_date_undefined(qt_or_dt):
|
||||||
@@ -58,7 +58,7 @@ def is_date_undefined(qt_or_dt):
|
|||||||
if hasattr(d, 'date'):
|
if hasattr(d, 'date'):
|
||||||
d = d.date()
|
d = d.date()
|
||||||
try:
|
try:
|
||||||
d = datetime(d.year(), d.month(), d.day(), tzinfo=utc_tz)
|
d = datetime.datetime(d.year(), d.month(), d.day(), tzinfo=utc_tz)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return True # Undefined QDate
|
return True # Undefined QDate
|
||||||
return d.year < UNDEFINED_DATE.year or (
|
return d.year < UNDEFINED_DATE.year or (
|
||||||
@@ -96,7 +96,8 @@ def parse_date(date_string, assume_utc=False, as_utc=True, default=None):
|
|||||||
if isinstance(date_string, bytes):
|
if isinstance(date_string, bytes):
|
||||||
date_string = date_string.decode(preferred_encoding, 'replace')
|
date_string = date_string.decode(preferred_encoding, 'replace')
|
||||||
if default is None:
|
if default is None:
|
||||||
func = datetime.utcnow if assume_utc else datetime.now
|
func = (datetime.datetime.utcnow if assume_utc
|
||||||
|
else datetime.datetime.now)
|
||||||
default = func().replace(day=15, hour=0, minute=0, second=0, microsecond=0,
|
default = func().replace(day=15, hour=0, minute=0, second=0, microsecond=0,
|
||||||
tzinfo=_utc_tz if assume_utc else _local_tz)
|
tzinfo=_utc_tz if assume_utc else _local_tz)
|
||||||
if iso_pat().match(date_string) is not None:
|
if iso_pat().match(date_string) is not None:
|
||||||
@@ -109,7 +110,7 @@ def parse_date(date_string, assume_utc=False, as_utc=True, default=None):
|
|||||||
|
|
||||||
|
|
||||||
def fix_only_date(val):
|
def fix_only_date(val):
|
||||||
n = val + timedelta(days=1)
|
n = val + datetime.timedelta(days=1)
|
||||||
if n.month > val.month:
|
if n.month > val.month:
|
||||||
val = val.replace(day=val.day-1)
|
val = val.replace(day=val.day-1)
|
||||||
if val.day == 1:
|
if val.day == 1:
|
||||||
@@ -130,20 +131,20 @@ def parse_only_date(raw, assume_utc=True, as_utc=True):
|
|||||||
|
|
||||||
|
|
||||||
def strptime(val, fmt, assume_utc=False, as_utc=True):
|
def strptime(val, fmt, assume_utc=False, as_utc=True):
|
||||||
dt = datetime.strptime(val, fmt)
|
dt = datetime.datetime.strptime(val, fmt)
|
||||||
if dt.tzinfo is None:
|
if dt.tzinfo is None:
|
||||||
dt = dt.replace(tzinfo=_utc_tz if assume_utc else _local_tz)
|
dt = dt.replace(tzinfo=_utc_tz if assume_utc else _local_tz)
|
||||||
return dt.astimezone(_utc_tz if as_utc else _local_tz)
|
return dt.astimezone(_utc_tz if as_utc else _local_tz)
|
||||||
|
|
||||||
|
|
||||||
def dt_factory(time_t, assume_utc=False, as_utc=True):
|
def dt_factory(time_t, assume_utc=False, as_utc=True):
|
||||||
dt = datetime(*(time_t[0:6]))
|
dt = datetime.datetime(*(time_t[0:6]))
|
||||||
if dt.tzinfo is None:
|
if dt.tzinfo is None:
|
||||||
dt = dt.replace(tzinfo=_utc_tz if assume_utc else _local_tz)
|
dt = dt.replace(tzinfo=_utc_tz if assume_utc else _local_tz)
|
||||||
return dt.astimezone(_utc_tz if as_utc else _local_tz)
|
return dt.astimezone(_utc_tz if as_utc else _local_tz)
|
||||||
|
|
||||||
|
|
||||||
safeyear = lambda x: min(max(x, MINYEAR), MAXYEAR)
|
safeyear = lambda x: min(max(x, datetime.MINYEAR), datetime.MAXYEAR)
|
||||||
|
|
||||||
|
|
||||||
def qt_to_dt(qdate_or_qdatetime, as_utc=True):
|
def qt_to_dt(qdate_or_qdatetime, as_utc=True):
|
||||||
@@ -153,29 +154,29 @@ def qt_to_dt(qdate_or_qdatetime, as_utc=True):
|
|||||||
o = o.toUTC()
|
o = o.toUTC()
|
||||||
d, t = o.date(), o.time()
|
d, t = o.date(), o.time()
|
||||||
try:
|
try:
|
||||||
ans = datetime(safeyear(d.year()), d.month(), d.day(), t.hour(), t.minute(), t.second(), t.msec()*1000, utc_tz)
|
ans = datetime.datetime(safeyear(d.year()), d.month(), d.day(), t.hour(), t.minute(), t.second(), t.msec()*1000, utc_tz)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
ans = datetime(safeyear(d.year()), d.month(), 1, t.hour(), t.minute(), t.second(), t.msec()*1000, utc_tz)
|
ans = datetime.datetime(safeyear(d.year()), d.month(), 1, t.hour(), t.minute(), t.second(), t.msec()*1000, utc_tz)
|
||||||
if not as_utc:
|
if not as_utc:
|
||||||
ans = ans.astimezone(local_tz)
|
ans = ans.astimezone(local_tz)
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dt = datetime(safeyear(o.year()), o.month(), o.day()).replace(tzinfo=_local_tz)
|
dt = datetime.datetime(safeyear(o.year()), o.month(), o.day()).replace(tzinfo=_local_tz)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
dt = datetime(safeyear(o.year()), o.month(), 1).replace(tzinfo=_local_tz)
|
dt = datetime.datetime(safeyear(o.year()), o.month(), 1).replace(tzinfo=_local_tz)
|
||||||
return dt.astimezone(_utc_tz if as_utc else _local_tz)
|
return dt.astimezone(_utc_tz if as_utc else _local_tz)
|
||||||
|
|
||||||
|
|
||||||
def fromtimestamp(ctime, as_utc=True):
|
def fromtimestamp(ctime, as_utc=True):
|
||||||
dt = datetime.utcfromtimestamp(ctime).replace(tzinfo=_utc_tz)
|
dt = datetime.datetime.utcfromtimestamp(ctime).replace(tzinfo=_utc_tz)
|
||||||
if not as_utc:
|
if not as_utc:
|
||||||
dt = dt.astimezone(_local_tz)
|
dt = dt.astimezone(_local_tz)
|
||||||
return dt
|
return dt
|
||||||
|
|
||||||
|
|
||||||
def fromordinal(day, as_utc=True):
|
def fromordinal(day, as_utc=True):
|
||||||
return datetime.fromordinal(day).replace(
|
return datetime.datetime.fromordinal(day).replace(
|
||||||
tzinfo=_utc_tz if as_utc else _local_tz)
|
tzinfo=_utc_tz if as_utc else _local_tz)
|
||||||
|
|
||||||
|
|
||||||
@@ -193,6 +194,40 @@ def internal_iso_format_string():
|
|||||||
return 'yyyy-MM-ddThh:mm:ss'
|
return 'yyyy-MM-ddThh:mm:ss'
|
||||||
|
|
||||||
|
|
||||||
|
def strftime(fmt, t=None):
|
||||||
|
"""
|
||||||
|
A version of strftime that returns unicode strings and tries to handle
|
||||||
|
dates before 1900
|
||||||
|
"""
|
||||||
|
if not fmt:
|
||||||
|
return ''
|
||||||
|
if t is None:
|
||||||
|
t = time.localtime()
|
||||||
|
if hasattr(t, 'timetuple'):
|
||||||
|
t = t.timetuple()
|
||||||
|
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] = replacement
|
||||||
|
t = time.struct_time(t)
|
||||||
|
ans = None
|
||||||
|
if iswindows:
|
||||||
|
if isinstance(fmt, bytes):
|
||||||
|
fmt = fmt.decode('mbcs', 'replace')
|
||||||
|
fmt = fmt.replace('%e', '%#d')
|
||||||
|
ans = plugins['winutil'][0].strftime(fmt, t)
|
||||||
|
else:
|
||||||
|
ans = time.strftime(fmt, t)
|
||||||
|
if isinstance(ans, bytes):
|
||||||
|
ans = ans.decode(preferred_encoding, 'replace')
|
||||||
|
if early_year:
|
||||||
|
ans = ans.replace('_early year hack##', str(orig_year))
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
def w3cdtf(date_time, assume_utc=False):
|
def w3cdtf(date_time, assume_utc=False):
|
||||||
if hasattr(date_time, 'tzinfo'):
|
if hasattr(date_time, 'tzinfo'):
|
||||||
if date_time.tzinfo is None:
|
if date_time.tzinfo is None:
|
||||||
@@ -227,21 +262,21 @@ def as_utc(date_time, assume_utc=True):
|
|||||||
|
|
||||||
|
|
||||||
def now():
|
def now():
|
||||||
return datetime.now().replace(tzinfo=_local_tz)
|
return datetime.datetime.now().replace(tzinfo=_local_tz)
|
||||||
|
|
||||||
|
|
||||||
def utcnow():
|
def utcnow():
|
||||||
return datetime.utcnow().replace(tzinfo=_utc_tz)
|
return datetime.datetime.utcnow().replace(tzinfo=_utc_tz)
|
||||||
|
|
||||||
|
|
||||||
def utcfromtimestamp(stamp):
|
def utcfromtimestamp(stamp):
|
||||||
try:
|
try:
|
||||||
return datetime.utcfromtimestamp(stamp).replace(tzinfo=_utc_tz)
|
return datetime.datetime.utcfromtimestamp(stamp).replace(tzinfo=_utc_tz)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# Raised if stamp is out of range for the platforms gmtime function
|
# Raised if stamp is out of range for the platforms gmtime function
|
||||||
# For example, this happens with negative values on windows
|
# For example, this happens with negative values on windows
|
||||||
try:
|
try:
|
||||||
return EPOCH + timedelta(seconds=stamp)
|
return EPOCH + datetime.timedelta(seconds=stamp)
|
||||||
except (ValueError, OverflowError):
|
except (ValueError, OverflowError):
|
||||||
# datetime can only represent years between 1 and 9999
|
# datetime can only represent years between 1 and 9999
|
||||||
import traceback
|
import traceback
|
||||||
@@ -334,8 +369,8 @@ def format_date(dt, format, assume_utc=False, as_utc=False):
|
|||||||
if not format:
|
if not format:
|
||||||
format = 'dd MMM yyyy'
|
format = 'dd MMM yyyy'
|
||||||
|
|
||||||
if not isinstance(dt, datetime):
|
if not isinstance(dt, datetime.datetime):
|
||||||
dt = datetime.combine(dt, dtime())
|
dt = datetime.datetime.combine(dt, datetime.time())
|
||||||
|
|
||||||
if hasattr(dt, 'tzinfo'):
|
if hasattr(dt, 'tzinfo'):
|
||||||
if dt.tzinfo is None:
|
if dt.tzinfo is None:
|
||||||
@@ -349,7 +384,7 @@ def format_date(dt, format, assume_utc=False, as_utc=False):
|
|||||||
if dt == UNDEFINED_DATE:
|
if dt == UNDEFINED_DATE:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
repl_func = partial(fd_repl_func, dt, 'ap' in format.lower())
|
repl_func = functools.partial(fd_repl_func, dt, 'ap' in format.lower())
|
||||||
return re.sub(
|
return re.sub(
|
||||||
'(s{1,2})|(m{1,2})|(h{1,2})|(ap)|(AP)|(d{1,4}|M{1,4}|(?:yyyy|yy))',
|
'(s{1,2})|(m{1,2})|(h{1,2})|(ap)|(AP)|(d{1,4}|M{1,4}|(?:yyyy|yy))',
|
||||||
repl_func, format)
|
repl_func, format)
|
||||||
@@ -411,8 +446,8 @@ def clean_date_for_sort(dt, fmt=None):
|
|||||||
if not fmt:
|
if not fmt:
|
||||||
fmt = 'yyMd'
|
fmt = 'yyMd'
|
||||||
|
|
||||||
if not isinstance(dt, datetime):
|
if not isinstance(dt, datetime.datetime):
|
||||||
dt = datetime.combine(dt, dtime())
|
dt = datetime.datetime.combine(dt, datetime.time())
|
||||||
|
|
||||||
if hasattr(dt, 'tzinfo'):
|
if hasattr(dt, 'tzinfo'):
|
||||||
if dt.tzinfo is None:
|
if dt.tzinfo is None:
|
||||||
@@ -426,7 +461,7 @@ def clean_date_for_sort(dt, fmt=None):
|
|||||||
'day':UNDEFINED_DATE.day, 'hour':UNDEFINED_DATE.hour,
|
'day':UNDEFINED_DATE.day, 'hour':UNDEFINED_DATE.hour,
|
||||||
'min':UNDEFINED_DATE.minute, 'sec':UNDEFINED_DATE.second}
|
'min':UNDEFINED_DATE.minute, 'sec':UNDEFINED_DATE.second}
|
||||||
|
|
||||||
repl_func = partial(cd_repl_func, tt, dt)
|
repl_func = functools.partial(cd_repl_func, tt, dt)
|
||||||
re.sub('(s{1,2})|(m{1,2})|(h{1,2})|(d{1,4}|M{1,4}|(?:yyyy|yy))', repl_func, fmt)
|
re.sub('(s{1,2})|(m{1,2})|(h{1,2})|(d{1,4}|M{1,4}|(?:yyyy|yy))', repl_func, fmt)
|
||||||
return dt.replace(year=tt['year'], month=tt['mon'], day=tt['day'], hour=tt['hour'],
|
return dt.replace(year=tt['year'], month=tt['mon'], day=tt['day'], hour=tt['hour'],
|
||||||
minute=tt['min'], second=tt['sec'], microsecond=0)
|
minute=tt['min'], second=tt['sec'], microsecond=0)
|
||||||
|
|||||||
Reference in New Issue
Block a user