Вы можете получить достаточное расстояние с помощью простой замены для преобразования строк формата.
_format_changes = (
('MMMM', '%B'),
('MMM', '%b'), # note: the order in this list is critical
('MM', '%m'),
('M', '%m'), # note: no exact equivalent
# etc etc
)
def conv_format(s):
for c, p in _format_changes:
# s.replace(c, p) #### typo/braino
s = s.replace(c, p)
return s
Я предполагаю, что ваши "обручи" означают нечто подобное. Обратите внимание, что есть осложнения:
(1) формат C # может содержать буквальный текст, заключенный в одинарные кавычки (примеры в цитируемой вами ссылке)
(2) он, вероятно, позволяет сделать один символ буквальным, если экранировать его с (например) \
(3) Для 12- или 24-часовых часов может потребоваться дополнительная работа (я не углублялся в спецификацию C #; этот комментарий основан на другом подобном упражнении, в котором я участвовал).
Вы можете написать компилятор и интерпретатор байт-кода, чтобы обойти все ошибки (такие как M, F, FF, FFF, ...).
Альтернативой для рассмотрения является использование ctypes
или что-то похожее для прямого вызова C#
RTL.
Обновление Исходный код был чрезмерно упрощенным и имел опечатку / брейно. В следующем новом коде показано, как решить некоторые проблемы (например, литеральный текст и обеспечить, чтобы литерал %
во входных данных не делал strftime несчастным). Он не пытается дать точные ответы там, где нет прямого преобразования (M, F и т. Д.). Отмечаются места, где может быть возбуждено исключение, но код действует на основе принципа невмешательства.
_format_changes = (
('yyyy', '%Y'), ('yyy', '%Y'), ('yy', '%y'),('y', '%y'),
('MMMM', '%B'), ('MMM', '%b'), ('MM', '%m'),('M', '%m'),
('dddd', '%A'), ('ddd', '%a'), ('dd', '%d'),('d', '%d'),
('HH', '%H'), ('H', '%H'), ('hh', '%I'), ('h', '%I'),
('mm', '%M'), ('m', '%M'),
('ss', '%S'), ('s', '%S'),
('tt', '%p'), ('t', '%p'),
('zzz', '%z'), ('zz', '%z'), ('z', '%z'),
)
def cnv_csharp_date_fmt(in_fmt):
ofmt = ""
fmt = in_fmt
while fmt:
if fmt[0] == "'":
# literal text enclosed in ''
apos = fmt.find("'", 1)
if apos == -1:
# Input format is broken.
apos = len(fmt)
ofmt += fmt[1:apos].replace("%", "%%")
fmt = fmt[apos+1:]
elif fmt[0] == "\\":
# One escaped literal character.
# Note graceful behaviour when \ is the last character.
ofmt += fmt[1:2].replace("%", "%%")
fmt = fmt[2:]
else:
# This loop could be done with a regex "(yyyy)|(yyy)|etc".
for intok, outtok in _format_changes:
if fmt.startswith(intok):
ofmt += outtok
fmt = fmt[len(intok):]
break
else:
# Hmmmm, what does C# do here?
# What do *you* want to do here?
# I'll just emit one character as literal text
# and carry on. Alternative: raise an exception.
ofmt += fmt[0].replace("%", "%%")
fmt = fmt[1:]
return ofmt
Проверено в следующей степени:
>>> from cnv_csharp_date_fmt import cnv_csharp_date_fmt as cv
>>> cv("yyyy-MM-dd hh:mm:ss")
'%Y-%m-%d %I:%M:%S'
>>> cv("3pcts %%% yyyy-MM-dd hh:mm:ss")
'3pc%p%S %%%%%% %Y-%m-%d %I:%M:%S'
>>> cv("'3pcts' %%% yyyy-MM-dd hh:mm:ss")
'3pcts %%%%%% %Y-%m-%d %I:%M:%S'
>>> cv(r"3pc\t\s %%% yyyy-MM-dd hh:mm:ss")
'3pcts %%%%%% %Y-%m-%d %I:%M:%S'
>>>