Преобразование CIM_DATETIME в Bash/Python

#python #wmi #datetime-format

Вопрос:

У меня есть CIM_DATETIME время, приобретенное у wmic os get lastbootuptime :

 20190309221835.234400-480
 

CIM_DATETIME форматируется следующим образом:

 yyyymmddHHMMSS.mmmmmmsUUU
 

Как я могу преобразовать это во что-то более удобное для человека в Bash или Python?

Формат, который был бы наиболее желательным, — это:

 Sunday, March 10th, 2019 @ 16:01:30 UTC
 

Это или если бы я мог преобразовать его во что-то нормальное, например, в метку времени Unix. Если вам интересно, что мне нужно для этого на языках, отличных от Windows (в пакете уже есть много решений), потому что я занимаюсь компьютерной экспертизой, но в качестве основной операционной системы я использую Linux, поэтому я хочу иметь возможность легко интерпретировать даты, которые я получаю от WMI, во что-то, что я могу легко интерпретировать. Это настолько нишевое занятие, что я даже не могу найти в Интернете инструмент для этого. :/

Спасибо.

Комментарии:

1. Пожалуйста, добавьте желаемый результат для этого примера ввода в свой вопрос.

2. @Сайрус сделал дело!

3. Было бы неплохо, если бы желаемый результат соответствовал заданному входу.

4. @Armali Хорошая мысль! Часовые пояса и форматы преобразования очень быстро сбивают с толку. Должно же быть что-то, по чему можно было бы проверять ошибки.

Ответ №1:

Вы можете получить метку времени без часового пояса с помощью этого:

 from datetime import datetime
datetime.strptime(CIM_DATETIME.split('-')[0], '%Y%m%d%H%M%S.%f')
 

[Обратите внимание, что для разделения строки предполагается отрицательное смещение часового пояса.]
Загвоздка с часовым поясом в том, что он выражается в минутах, поэтому вам нужно разделить на 60. Но нужно ли вам читать часовой пояс? Если это всегда будет одно и то же, то вы сможете внести это отдельно.

Комментарии:

1. Спасибо, но для компьютерной экспертизы часовой пояс действительно предпочтительнее.

Ответ №2:

но для компьютерной криминалистики часовой пояс действительно предпочтительнее.

ответ комбинаториста уже делает половину работы. Его можно легко расширить, чтобы учесть смещение часового пояса:

 import datetime
CIM_DATETIME ='20190309221835.234400-480'
dt = datetime.datetime.strptime(CIM_DATETIME[:-4], '%Y%m%d%H%M%S.%f')
# dt is now datetime.datetime(2019, 3, 9, 22, 18, 35, 234400)
dt -= datetime.timedelta(minutes=int(CIM_DATETIME[-4:]))
# dt is now datetime.datetime(2019, 3, 10, 6, 18, 35, 234400)
dt.strftime("%A, %B %d., %Y @ %X UTC")
 

Ответ №3:

Вот решение в Bash, которое я придумал. Вывод кажется правильным и совпадает со временем, когда пару дней назад я загрузил окно Windows-незадолго до полуночи. Я также удалил»@», потому что это едва ли сделало время приятнее для просмотра, и поэтому мне пришлось удалить его в следующих сценариях, используя CIM_DATETIME из date -за того, что команда не смогла это разобрать.

 CIM_DATETIME="20190309221835.234400-480"

date="${CIM_DATETIME:0:8}"
date="$(date -d "$date" ' %A, %B%e, %Y')"

time="${CIM_DATETIME:8:6}"
time="$(echo "$time" | sed 's/../amp;:/g;s/:$//')" # Adds : between hours, minutes and seconds of time so it can be parsed correctly

timezone="${CIM_DATETIME:21}"
time="$time $timezone"

time="$(date -d "$time" ' %r %Z')"

echo "$date $time"
 

Пример Вывода: Saturday, March 9, 2019 11:38:35 PM EDT

Спасибо вам за все решения.

Ответ №4:

Вот моя улучшенная версия ответа Армали, которая имеет дело с отрицательными / нулевыми / положительными часовыми поясами и позволяет использовать UTC или локальную нотацию:

[ПРАВИТЬ] Отказ от ответственности: Код в этом посте устарел. Я опубликовал этот код в виде пакета python. Установите с pip install windows_tools.installed_software

Использование:

 from windows_tools.wmi_queries import cim_timestamp_to_datetime_utc

print(cim_timestamp_to_datetime_utc('20201103225935.123456 0'))
 

[/ПРАВИТЬ]

 from datetime import datetime, timedelta
import re

def convert_cim_timestamp(cim_timestamp: str, utc_result: bool = True) -> str:
    """
    Convert WMI timestamp to python datetime object
    """
    cim_time, cim_tz = re.split('[ -]', cim_timestamp)
    dt = datetime.strptime(cim_time, '%Y%m%d%H%M%S.%f')
    if not utc_result:
        dt -= timedelta(minutes=int(cim_tz))
        return dt.strftime('%A, %B %d., %Y @ %X')
    else:
        utc_sign = ' ' if ' ' in cim_timestamp else '-'
        utc_offset = int(int(cim_tz)/60)
        return dt.strftime("%A, %B %d., %Y @ %X UTC{}{}".format(utc_sign, utc_offset))


# Example
cim_tz = '20201103225935.123456-240'
print(convert_cim_timestamp(cim_tz))
cim_tz = '20201103225935.123456 120'
print(convert_cim_timestamp(cim_tz))
 

Комментарии:

1. мне кажется, что было бы проще установить timedelta в качестве часового пояса (заменить tzinfo), а затем (если желаемый вывод-строка) использовать %z в директиве форматирования. кроме utc_result того, значение kwarg вводит в заблуждение; затем на выходе указывается смещение UTC, оно не преобразуется в UTC.

2. Спасибо, как было предложено в правке, это старый код, и он был изменен в репозитории git 😉