Fix display of dates on non english windows

This commit is contained in:
Kovid Goyal 2008-08-30 21:37:37 -07:00
parent 5c399a268e
commit 5e494d0f80
14 changed files with 188 additions and 33 deletions

View File

@ -22,6 +22,9 @@ LIBZ = '/lib/libz.so.1'
LIBBZ2 = '/lib/libbz2.so.1'
LIBUSB = '/usr/lib/libusb.so'
LIBPOPPLER = '/usr/lib/libpoppler.so.3'
LIBXML2 = '/usr/lib/libxml2.so.2'
LIBXSLT = '/usr/lib/libxslt.so.1'
LIBEXSLT = '/usr/lib/libexslt.so.0'
CALIBRESRC = os.path.join(CALIBREPREFIX, 'src')
@ -121,7 +124,7 @@ binaries += [('pdftohtml', PDFTOHTML, 'BINARY'),
print 'Adding external libraries...'
binaries += [ (os.path.basename(x), x, 'BINARY') for x in (SQLITE, DBUS,
LIBMNG, LIBZ, LIBBZ2, LIBUSB, LIBPOPPLER)]
LIBMNG, LIBZ, LIBBZ2, LIBUSB, LIBPOPPLER, LIBXML2, LIBXSLT, LIBEXSLT)]
qt = []

View File

@ -320,11 +320,10 @@ class LoggingInterface:
def strftime(fmt, t=time.localtime()):
'''
A version of strtime that returns unicode strings.
'''
result = time.strftime(fmt, t)
return unicode(result, preferred_encoding, 'replace')
''' A version of strtime that returns unicode strings. '''
if iswindows:
return plugins['winutil'].strftime(unicode(fmt, preferred_encoding), t)
return time.strftime(fmt, t).decode(preferred_encoding, 'replace')
def entity_to_unicode(match, exceptions=[], encoding='cp1252'):
'''

View File

@ -2,7 +2,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
__appname__ = 'calibre'
__version__ = '0.4.84b1'
__version__ = '0.4.84b2'
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
'''
Various run time constants.

View File

@ -9,11 +9,9 @@ from calibre.ebooks.lrf.html.convert_from import process_file
from calibre.web.feeds.main import option_parser as feeds_option_parser
from calibre.web.feeds.main import run_recipe
from calibre.ptempfile import PersistentTemporaryDirectory
from calibre import sanitize_file_name
from calibre import sanitize_file_name, strftime
import sys, os, time
import parser
import sys, os
def option_parser():
parser = feeds_option_parser()
@ -51,7 +49,7 @@ def main(args=sys.argv, notification=None, handler=None):
if not opts.output:
ext = '.lrs' if opts.lrs else '.lrf'
fname = recipe.title + time.strftime(recipe.timefmt)+ext
fname = recipe.title + strftime(recipe.timefmt)+ext
opts.output = os.path.join(os.getcwd(), sanitize_file_name(fname))
print 'Generating LRF...'
process_file(htmlfile, opts)

View File

@ -2,10 +2,10 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
'''Convert websites into LRF files.'''
import sys, time, tempfile, shutil, os, logging, imp, inspect, re
import sys, tempfile, shutil, os, logging, imp, inspect, re
from urlparse import urlsplit
from calibre import __appname__, setup_cli_handlers, CommandLineError
from calibre import __appname__, setup_cli_handlers, CommandLineError, strftime
from calibre.ebooks.lrf import option_parser as lrf_option_parser
from calibre.ebooks.lrf.html.convert_from import process_file
@ -128,7 +128,7 @@ def process_profile(args, options, logger=None):
title = profile.title
if not title:
title = urlsplit(options.url).netloc
options.title = title + time.strftime(profile.timefmt, time.localtime())
options.title = title + strftime(profile.timefmt)
options.match_regexps += profile.match_regexps
options.preprocess_regexps = profile.preprocess_regexps

View File

@ -306,7 +306,7 @@ class FileDialog(QObject):
QObject.connect(self.fd, SIGNAL('accepted()'), self.save_dir)
self.accepted = self.fd.exec_() == QFileDialog.Accepted
else:
dir = dynamic.get(self.dialog_name, default=os.path.expanduser('~'))
dir = dynamic.get(self.dialog_name, os.path.expanduser('~'))
self.selected_files = []
if mode == QFileDialog.AnyFile:
f = qstring_to_unicode(

View File

@ -13,7 +13,7 @@ from PyQt4.QtGui import QTableView, QProgressDialog, QAbstractItemView, QColor,
from PyQt4.QtCore import QAbstractTableModel, QVariant, Qt, QString, \
QCoreApplication, SIGNAL, QObject, QSize, QModelIndex
from calibre import preferred_encoding
from calibre import strftime
from calibre.ptempfile import PersistentTemporaryFile
from calibre.library.database import LibraryDatabase, text_to_tokens
from calibre.gui2 import NONE, TableView, qstring_to_unicode, config
@ -370,7 +370,7 @@ class BooksModel(QAbstractTableModel):
dt = self.db.timestamp(row)
if dt:
dt = dt - timedelta(seconds=time.timezone) + timedelta(hours=time.daylight)
return QVariant(dt.strftime(BooksView.TIME_FMT).decode(preferred_encoding, 'replace'))
return QVariant(strftime(BooksView.TIME_FMT, dt.timetuple()))
elif col == 4:
r = self.db.rating(row)
r = r/2 if r else 0
@ -690,7 +690,7 @@ class DeviceBooksModel(BooksModel):
dt = item.datetime
dt = datetime(*dt[0:6])
dt = dt - timedelta(seconds=time.timezone) + timedelta(hours=time.daylight)
data[_('Timestamp')] = dt.strftime('%a %b %d %H:%M:%S %Y')
data[_('Timestamp')] = strftime('%a %b %d %H:%M:%S %Y', dt.timetuple())
data[_('Tags')] = ', '.join(item.tags)
self.emit(SIGNAL('new_bookdisplay_data(PyQt_PyObject)'), data)
@ -731,7 +731,7 @@ class DeviceBooksModel(BooksModel):
dt = self.db[self.map[row]].datetime
dt = datetime(*dt[0:6])
dt = dt - timedelta(seconds=time.timezone) + timedelta(hours=time.daylight)
return QVariant(dt.strftime(BooksView.TIME_FMT))
return QVariant(strftime(BooksView.TIME_FMT, dt.timetuple()))
elif col == 4:
tags = self.db[self.map[row]].tags
if tags:

View File

@ -2,7 +2,8 @@
# Invoke with nmake /f Makefile.winutil
test : winutil.pyd
python.exe -c "import winutil; winutil.set_debug(True); print winutil.get_usb_devices(); print winutil.get_mounted_volumes_for_usb_device(0x054c, 0x031e)"
python.exe -c "import winutil; winutil.set_debug(True); print repr(winutil.strftime(u'%b %a %A')); "
#python.exe -c "import winutil; winutil.set_debug(True); print winutil.get_usb_devices(); print winutil.get_mounted_volumes_for_usb_device(0x054c, 0x031e)"
winutil.pyd : winutil.obj
link.exe /DLL /nologo /INCREMENTAL:NO /LIBPATH:c:\Python25\libs \

View File

@ -57,12 +57,19 @@ wherever possible in this module.
#define UNICODE
#include <Windows.h>
#include <Python.h>
#include <structseq.h>
#include <timefuncs.h>
#include <shlobj.h>
#include <stdio.h>
#include <setupapi.h>
#include <devguid.h>
#include <cfgmgr32.h>
#include <stdarg.h>
#include <time.h>
#define PyStructSequence_GET_ITEM(op, i) \
(((PyStructSequence *)(op))->ob_item[i])
#define BUFSIZE 512
#define MAX_DRIVES 26
@ -515,6 +522,143 @@ winutil_is_usb_device_connected(PyObject *self, PyObject *args) {
return ans;
}
static int
gettmarg(PyObject *args, struct tm *p)
{
int y;
memset((void *) p, '\0', sizeof(struct tm));
if (!PyArg_Parse(args, "(iiiiiiiii)",
&y,
&p->tm_mon,
&p->tm_mday,
&p->tm_hour,
&p->tm_min,
&p->tm_sec,
&p->tm_wday,
&p->tm_yday,
&p->tm_isdst))
return 0;
if (y < 1900) {
if (69 <= y && y <= 99)
y += 1900;
else if (0 <= y && y <= 68)
y += 2000;
else {
PyErr_SetString(PyExc_ValueError,
"year out of range");
return 0;
}
}
p->tm_year = y - 1900;
p->tm_mon--;
p->tm_wday = (p->tm_wday + 1) % 7;
p->tm_yday--;
return 1;
}
static PyObject *
winutil_strftime(PyObject *self, PyObject *args)
{
PyObject *tup = NULL;
struct tm buf;
PyObject *format;
const wchar_t *fmt;
size_t fmtlen, buflen;
wchar_t *outbuf = 0;
size_t i;
memset((void *) &buf, '\0', sizeof(buf));
if (!PyArg_ParseTuple(args, "U|O:strftime", &format, &tup))
return NULL;
if (tup == NULL) {
time_t tt = time(NULL);
buf = *localtime(&tt);
} else if (!gettmarg(tup, &buf))
return NULL;
if (buf.tm_mon == -1)
buf.tm_mon = 0;
else if (buf.tm_mon < 0 || buf.tm_mon > 11) {
PyErr_SetString(PyExc_ValueError, "month out of range");
return NULL;
}
if (buf.tm_mday == 0)
buf.tm_mday = 1;
else if (buf.tm_mday < 0 || buf.tm_mday > 31) {
PyErr_SetString(PyExc_ValueError, "day of month out of range");
return NULL;
}
if (buf.tm_hour < 0 || buf.tm_hour > 23) {
PyErr_SetString(PyExc_ValueError, "hour out of range");
return NULL;
}
if (buf.tm_min < 0 || buf.tm_min > 59) {
PyErr_SetString(PyExc_ValueError, "minute out of range");
return NULL;
}
if (buf.tm_sec < 0 || buf.tm_sec > 61) {
PyErr_SetString(PyExc_ValueError, "seconds out of range");
return NULL;
}
/* tm_wday does not need checking of its upper-bound since taking
``% 7`` in gettmarg() automatically restricts the range. */
if (buf.tm_wday < 0) {
PyErr_SetString(PyExc_ValueError, "day of week out of range");
return NULL;
}
if (buf.tm_yday == -1)
buf.tm_yday = 0;
else if (buf.tm_yday < 0 || buf.tm_yday > 365) {
PyErr_SetString(PyExc_ValueError, "day of year out of range");
return NULL;
}
if (buf.tm_isdst < -1 || buf.tm_isdst > 1) {
PyErr_SetString(PyExc_ValueError,
"daylight savings flag out of range");
return NULL;
}
/* Convert the unicode string to a wchar one */
fmtlen = PyUnicode_GET_SIZE(format);
fmt = (wchar_t *)PyMem_Malloc((fmtlen+1)*sizeof(wchar_t));
if (fmt == NULL) return PyErr_NoMemory();
i = PyUnicode_AsWideChar((PyUnicodeObject *)format, fmt, fmtlen);
if (i < fmtlen) {
PyErr_SetString(PyExc_RuntimeError, "Failed to convert format string");
PyMem_Free(fmt);
return NULL;
}
for (i = 1024; ; i += i) {
outbuf = (wchar_t *)PyMem_Malloc(i*sizeof(wchar_t));
if (outbuf == NULL) {
return PyErr_NoMemory();
}
buflen = wcsftime(outbuf, i, fmt, &buf);
if (buflen > 0 || i >= 256 * fmtlen) {
/* If the buffer is 256 times as long as the format,
it's probably not failing for lack of room!
More likely, the format yields an empty result,
e.g. an empty format, or %Z when the timezone
is unknown. */
PyObject *ret;
ret = PyUnicode_FromWideChar(outbuf, buflen);
PyMem_Free(outbuf); PyMem_Free(fmt);
return ret;
}
PyMem_Free(outbuf); PyMem_Free(fmt);
#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
/* VisualStudio .NET 2005 does this properly */
if (buflen == 0 && errno == EINVAL) {
PyErr_SetString(PyExc_ValueError, "Invalid format string");
return NULL;
}
#endif
}
}
static PyMethodDef WinutilMethods[] = {
{"special_folder_path", winutil_folder_path, METH_VARARGS,
@ -553,6 +697,15 @@ static PyMethodDef WinutilMethods[] = {
"set_debug(bool)\n\nSet debugging mode."
},
{"strftime", winutil_strftime, METH_VARARGS,
"strftime(format[, tuple]) -> string\n\
\n\
Convert a time tuple to a string according to a format specification.\n\
See the library reference manual for formatting codes. When the time tuple\n\
is not present, current time as returned by localtime() is used. format must\n\
be a unicode string. Returns unicode strings."
},
{NULL, NULL, 0, NULL}
};

View File

@ -4,6 +4,7 @@ __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
import re, time
from calibre import strftime
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import NavigableString
@ -65,7 +66,7 @@ class NewYorker(BasicNewsRecipe):
'title': title,
'desc': desc, 'content':'',
'url': href,
'date': time.strftime('%a, %d %b', time.localtime()),
'date': strftime('%a, %d %b'),
}
articles.append(art)

View File

@ -3,6 +3,7 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
import re, string, time
from calibre import strftime
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import BeautifulSoup
@ -68,7 +69,7 @@ class Newsweek(BasicNewsRecipe):
small = img['src']
match = re.search(r'(\d+)_', small.rpartition('/')[-1])
if match is not None:
self.timefmt = time.strftime(' [%d %b, %Y]', time.strptime(match.group(1), '%y%m%d'))
self.timefmt = strftime(' [%d %b, %Y]', time.strptime(match.group(1), '%y%m%d'))
self.cover_url = small.replace('coversmall', 'coverlarge')
sections = self.get_sections(soup)
@ -84,7 +85,7 @@ class Newsweek(BasicNewsRecipe):
'title' : title,
'url' : a['href'],
'description':'', 'content':'',
'date': time.strftime('%a, %d %b', time.localtime())
'date': strftime('%a, %d %b')
}
if art['title'] and art['url']:
sections[0][1].append(art)

View File

@ -5,7 +5,8 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
'''
nytimes.com
'''
import time, string
import string
from calibre import strftime
from calibre.web.feeds.recipes import BasicNewsRecipe
class NYTimes(BasicNewsRecipe):
@ -59,7 +60,7 @@ class NYTimes(BasicNewsRecipe):
url = self.print_version(a['href'])
title = self.tag_to_string(a, use_alt=True).strip()
description = ''
pubdate = time.strftime('%a, %d %b', time.localtime())
pubdate = strftime('%a, %d %b')
summary = div.find(True, attrs={'class':'summary'})
if summary:
description = self.tag_to_string(summary, use_alt=False)

View File

@ -6,7 +6,7 @@ __docformat__ = 'restructuredtext en'
'''
smh.com.au
'''
import time
from calibre import strftime
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import BeautifulSoup
@ -44,7 +44,7 @@ class SMH(BasicNewsRecipe):
articles.append({
'title': title,
'url' : url,
'date' : time.strftime('%a, %d %b'),
'date' : strftime('%a, %d %b'),
'description' : '',
'content' : '',
})

View File

@ -2,9 +2,8 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
import datetime
from calibre.utils.genshi.template import MarkupTemplate
from calibre import preferred_encoding
from calibre import preferred_encoding, strftime
class Template(MarkupTemplate):
@ -126,8 +125,7 @@ class IndexTemplate(Template):
def generate(self, title, datefmt, feeds):
if isinstance(datefmt, unicode):
datefmt = datefmt.encode(preferred_encoding)
date = datetime.datetime.now().strftime(datefmt)
date = date.decode(preferred_encoding, 'replace')
date = strftime(datefmt)
return Template.generate(self, title=title, date=date, feeds=feeds)