У меня есть файл с разделителями табуляции, в котором каждая запись имеет поле временной метки в 12-часовом формате:
mm/dd/yyyy hh:mm:ss [AM|PM].
Мне нужно быстро преобразовать эти поля в 24-часовое время:
mm/dd/yyyy HH:mm:ss.
Как лучше всего это сделать? Я работаю на платформе Windows, но у меня есть доступ к sed, awk, perl, python и tcl в дополнение к обычным инструментам Windows.





Поскольку у вас несколько языков, я предлагаю следующий алгоритм.
1 Проверьте метку времени на наличие строки «PM».
2a Если PM не существует, просто преобразуйте метку времени в объект datetime и продолжайте.
2b Если PM существует, преобразуйте метку времени в объект datetime, добавьте 12 часов и продолжайте.
Используйте модуль DateTime в Pythons примерно так:
import datetime
infile = open('input.txt')
outfile = open('output.txt', 'w')
for line in infile.readlines():
d = datetime.strptime(line, "input format string")
outfile.write(d.strftime("output format string")
Непроверенный код без проверки ошибок. Также он считывает весь входной файл в памяти перед запуском. (Я знаю, что есть много возможностей для улучшений, например, с оператором ... Я делаю это вики-записью сообщества, если кому-то нравится что-то добавлять)
Использование Perl и созданных вручную регулярных выражений вместо таких средств, как strptime:
#!/bin/perl -w
while (<>)
{
# for date times that don't use leading zeroes, use this regex instead:
# (?:\d{1,2}/\d{1,2}/\d{4} )(\d{1,2})(?::\d\d:\d\d) (AM|PM)
while (m%(?:\d\d/\d\d/\d{4} )(\d\d)(?::\d\d:\d\d) (AM|PM)%)
{
my $hh = $1;
$hh -= 12 if ($2 eq 'AM' && $hh == 12);
$hh += 12 if ($2 eq 'PM' && $hh != 12);
$hh = sprintf "%02d", $hh;
# for date times that don't use leading zeroes, use this regex instead:
# (\d{1,2}/\d{1,2}/\d{4} )(\d{1,2})(:\d\d:\d\d) (?:AM|PM)
s%(\d\d/\d\d/\d{4} )(\d\d)(:\d\d:\d\d) (?:AM|PM)%$1$hh$3%;
}
print;
}
Это очень сложно, но при этом может конвертировать несколько временных меток в строке.
Обратите внимание, что преобразование AM / PM в 24-часовой нетривиально.
Сейчас протестировано:
perl ampm-24hr.pl <<!
12/24/2005 12:01:00 AM
09/22/1999 12:00:00 PM
12/12/2005 01:15:00 PM
01/01/2009 01:56:45 AM
12/30/2009 10:00:00 PM
12/30/2009 10:00:00 AM
!
12/24/2005 00:01:00
09/22/1999 12:00:00
12/12/2005 13:15:00
01/01/2009 01:56:45
12/30/2009 22:00:00
12/30/2009 10:00:00
Добавлен:
В Каков простой способ преобразования между временем AM / PM и 24-часовым временем в JavaScript предусмотрен альтернативный алгоритм преобразования:
$hh = ($1 % 12) + (($2 eq 'AM') ? 0 : 12);
Всего один тест ... наверное, лучше.
@ Дэйв Шерохман: Вы уверены? Это должно быть условием присутствия AM / PM, как минимум - вам не нужно добавлять 12 часов к времени AM, например 10:00 AM. Также, похоже, не решена проблема того, что 12:59 - это две минуты до 01:01.
Спасибо, Джонатан, сработало как шарм :) Мне пришлось изменить регулярное выражение на (?:\d{1,2}/\d{1,2}/\d{4} )(\d{1,2})(?::\d\d:\d\d) (AM|PM), но в остальном это было правильно.
Это была часть «Это очень суетливо» - я подумал, что вы сможете с этим разобраться, если необходимо. Сложность заключается в добавлении / добавлении 12-часового мусора; Есть удивительное количество ложных ответов от людей, которые не продумали необходимые шаги.
Вы также можете использовать \ d \ d? вместо \ d {1,2}, что короче: D
Еще раз спасибо. Я ни в коем случае не эксперт по регулярным выражениям; Я стараюсь прокладывать себе путь, пока не получу что-нибудь, что работает.
Я считаю, что круглые скобки в "простом" методе неправильные. Должен быть $hh = ($1 % 12) + ($2 eq 'AM' ? 0 : 12);
Решение $hh = ($1 % 12) + (($2 eq 'AM') ? 0 : 12); у меня сработало.
Это может показаться слишком простым мышлением, но почему бы не импортировать его в Excel, выбрать весь столбец и изменить формат даты, а затем повторно экспортировать его как файл с разделителями табуляции? (Я не тестировал это, но мне это как-то логично :)
Мне это кажется умеренно сложным. Не ошибаюсь - просто сложно.
У меня в файле около 450 000+ строк, и у нас работает только Office 2003, поэтому Excel ограничен 65 КБ строк.
Я не был знаком с лимитом Excel, извините. @ Джонатан: Сложный? Действительно? Думаю, наши мнения по этому поводу разные. Мне кажется сложнее писать сценарии Perl и тому подобное :)
Здесь я преобразовал 24-часовую систему в 12-часовую. Попробуйте использовать этот метод для своей проблемы.
DateFormat fmt = new SimpleDateFormat("yyyyMMddHHssmm");
try {
Date date =fmt.parse("20090310232344");
System.out.println(date.toString());
fmt = new SimpleDateFormat("dd-MMMM-yyyy hh:mm:ss a ");
String dateInString = fmt.format(date);
System.out.println(dateInString);
} catch (Exception e) {
System.out.println(e.getMessage());
}
RESULT:
Tue Mar 10 23:44:23 IST 2009
10-March-2009 11:44:23 PM
Чтобы просто преобразовать поле часа в python:
def to12(hour24):
return (hour24 % 12) if (hour24 % 12) > 0 else 12
def IsPM(hour24):
return hour24 > 11
def to24(hour12, isPm):
return (hour12 % 12) + (12 if isPm else 0)
def IsPmString(pm):
return "PM" if pm else "AM"
def TestTo12():
for x in range(24):
print x, to12(x), IsPmString(IsPM(x))
def TestTo24():
for pm in [False, True]:
print 12, IsPmString(pm), to24(12, pm)
for x in range(1, 12):
print x, IsPmString(pm), to24(x, pm)
В Python это однострочная вещь:
time.strftime('%H:%M:%S', time.strptime(x, '%I:%M %p'))
Пример:
>>> time.strftime('%H:%M:%S', time.strptime('08:01 AM', '%I:%M %p'))
'08:01:00'
>>> time.strftime('%H:%M:%S', time.strptime('12:01 AM', '%I:%M %p'))
'00:01:00'
В Python: преобразование 12-часового времени в 24-часовое время
import re
time1=input().strip().split(':')
m=re.search('(..)(..)',time1[2])
sec=m.group(1)
tz=m.group(2)
if (tz='PM'):
time[0]=int(time1[0])+12
if (time1[0]=24):
time1[0]-=12
time[2]=sec
else:
if (int(time1[0])=12):
time1[0]-=12
time[2]=sec
print(time1[0]+':'+time1[1]+':'+time1[2])
Неточно ... описанное вычисление неверно обрабатывает 00:01 и 12:01.