-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathepoch.py
131 lines (103 loc) · 5.59 KB
/
epoch.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# encoding: utf-8
import datetime
import re
import subprocess
import sys
import time as timeutil
from importlib import reload
from workflow import Workflow, ICON_CLOCK, ICON_NOTE
reload(sys)
LOGGER = None # Set in the main...
MAX_SECONDS_TIMESTAMP = 10000000000
MAX_SUBSECONDS_ITERATION = 4
def get_divisor(timestamp):
for power in range(MAX_SUBSECONDS_ITERATION):
divisor = pow(1e3, power)
if timestamp < MAX_SECONDS_TIMESTAMP * divisor:
return int(divisor)
return 0
def convert(timestamp, converter):
divisor = get_divisor(timestamp)
LOGGER.debug('Found divisor [{divisor}] for timestamp [{timestamp}]'.format(**locals()))
if divisor > 0:
seconds, subseconds = divmod(timestamp, divisor)
subseconds_str = '{:.9f}'.format(subseconds / float(divisor))
return converter(seconds).isoformat() + subseconds_str[1:].rstrip('0').rstrip('.')
def add_epoch_to_time_conversion(workflow, timestamp, descriptor, converter):
converted = convert(timestamp, converter)
description = descriptor + ' time for ' + str(timestamp)
if converted is None:
raise Exception('Timestamp [{timestamp}] is not supported'.format(**locals()))
else:
LOGGER.debug('Returning [{converted}] as [{description}] for [{timestamp}]'.format(**locals()))
workflow.add_item(title=converted, subtitle=description, arg=converted, valid=True, icon=ICON_CLOCK)
def add_time_to_epoch_conversion(workflow, dt, descriptor, converter, multiplier, tzinfo=None):
epoch_dt = converter(0, tzinfo) if tzinfo is not None else converter(0)
converted = str(int((dt.replace(tzinfo=tzinfo) - epoch_dt).total_seconds() * multiplier))
description = descriptor + ' epoch for ' + str(dt)
workflow.add_item(title=converted, subtitle=description, arg=converted, valid=True, icon=ICON_CLOCK)
def attempt_conversions(workflow, input, prefix=''):
try:
timestamp = int(input)
add_epoch_to_time_conversion(workflow, timestamp, '{prefix}Local'.format(**locals()),
datetime.datetime.fromtimestamp)
add_epoch_to_time_conversion(workflow, timestamp, '{prefix}UTC'.format(**locals()),
datetime.datetime.utcfromtimestamp)
except:
LOGGER.debug('Unable to read [{input}] as an epoch timestamp'.format(**locals()))
try:
match = re.match('(\d{4}-\d{2}-\d{2})?[ T]?((\d{2}:\d{2})(:\d{2})?(.\d+)?)?', str(input))
date, time, hour_minutes, seconds, subseconds = match.groups()
if date or time:
dt = datetime.datetime.strptime(
(date or datetime.datetime.now().strftime('%Y-%m-%d')) + ' ' +
(hour_minutes or '00:00') + (seconds or ':00') +
('.000000' if subseconds is None else subseconds[:7]),
'%Y-%m-%d %H:%M:%S.%f'
)
add_time_to_epoch_conversion(workflow, dt, '{prefix}Local s.'.format(**locals()),
datetime.datetime.fromtimestamp,1, dt.astimezone().tzinfo)
add_time_to_epoch_conversion(workflow, dt, '{prefix}Local ms.'.format(**locals()),
datetime.datetime.fromtimestamp,1e3, dt.astimezone().tzinfo)
add_time_to_epoch_conversion(workflow, dt, u'{prefix}Local µs.'.format(**locals()),
datetime.datetime.fromtimestamp,1e6, dt.astimezone().tzinfo)
add_time_to_epoch_conversion(workflow, dt, '{prefix}Local ns.'.format(**locals()),
datetime.datetime.fromtimestamp,1e9, dt.astimezone().tzinfo)
add_time_to_epoch_conversion(workflow, dt, '{prefix}UTC s.'.format(**locals()),
datetime.datetime.utcfromtimestamp, 1)
add_time_to_epoch_conversion(workflow, dt, '{prefix}UTC ms.'.format(**locals()),
datetime.datetime.utcfromtimestamp, 1e3)
add_time_to_epoch_conversion(workflow, dt, u'{prefix}UTC µs.'.format(**locals()),
datetime.datetime.utcfromtimestamp, 1e6)
add_time_to_epoch_conversion(workflow, dt, '{prefix}UTC ns.'.format(**locals()),
datetime.datetime.utcfromtimestamp, 1e9)
except Exception as e:
LOGGER.debug('Unable to read [{input}] as a human-readable datetime'.format(**locals()), e)
def add_current(workflow, unit, multiplier):
converted = str(int(timeutil.time() * multiplier))
description = 'Current timestamp ({unit})'.format(**locals())
LOGGER.debug('Returning [{converted}] as [{description}]'.format(**locals()))
workflow.add_item(title=converted, subtitle=description, arg=converted, valid=True, icon=ICON_NOTE)
def get_clipboard_data():
p = subprocess.Popen(['pbpaste'], stdout=subprocess.PIPE)
p.wait()
return p.stdout.read()
def main(_workflow_):
if len(_workflow_.args) > 0:
query = _workflow_.args[0]
if query:
LOGGER.debug('Got query [{query}]'.format(**locals()))
attempt_conversions(_workflow_, query)
clipboard = get_clipboard_data()
if clipboard:
LOGGER.debug('Got clipboard [{clipboard}]'.format(**locals()))
attempt_conversions(_workflow_, clipboard, prefix='(clipboard) ')
add_current(_workflow_, 's', 1)
add_current(_workflow_, 'ms', 1e3)
add_current(_workflow_, u'µs', 1e6)
add_current(_workflow_, 'ns', 1e9)
_workflow_.send_feedback()
if __name__ == u"__main__":
wf = Workflow()
LOGGER = wf.logger
sys.exit(wf.run(main))