Skip to content

Commit 49aeca8

Browse files
committed
Update time, release 0.4.0
1 parent 301302b commit 49aeca8

File tree

11 files changed

+241
-239
lines changed

11 files changed

+241
-239
lines changed

afw.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@
22

33
import importlib
44
import json
5+
import logging
56
import subprocess
67
import sys
7-
from logging import Logger
88
from pathlib import Path
99
from uuid import uuid4
1010
from zipfile import ZipFile
1111

1212
import click
1313
from ualfred import Workflow3
1414

15-
logger = Logger(__file__)
16-
1715
AFW_RUNTIME_FILES = ["afw.py", "afw_runtime.py"]
1816
AFW_REQUIREMENTS = ["click", "ualfred"]
1917

@@ -149,7 +147,8 @@ def test(workflow_path: str, query: str):
149147

150148
wf = Workflow3()
151149

152-
feedback = module.main(args=wf.args[2:], logger=logger)
150+
logging.basicConfig(level=logging.DEBUG)
151+
feedback = module.main(args=wf.args[2:], logger=logging)
153152
print(json.dumps(feedback, indent=4))
154153

155154

afw_runtime.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import dataclasses
2+
from logging import Logger
23

34
from ualfred import (
45
ICON_ACCOUNT,
@@ -99,9 +100,11 @@ class AFWFuncAbc:
99100
icon_note = ICON_NOTE
100101
icon_error = ICON_ERROR
101102

103+
args: list[str]
104+
logger: Logger
102105
responses: list[AFWResponse]
103106

104-
def __init__(self, args: list[str], logger) -> None:
107+
def __init__(self, args: list[str], logger: Logger) -> None:
105108
self.args = args
106109
self.logger = logger
107110
self.responses = list()
File renamed without changes.

afw_time/icon.png

30.8 KB
Loading

afw_time_converter/info.plist renamed to afw_time/info.plist

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
<plist version="1.0">
44
<dict>
55
<key>bundleid</key>
6-
<string>com.rexzhang.alfred-workflow-time-converter</string>
7-
<key>category</key>
8-
<string>Tools</string>
6+
<string>com.rexzhang.alfred-workflows.time</string>
97
<key>connections</key>
108
<dict>
119
<key>A0BEA961-6062-42BD-9606-2257AA07F7AD</key>
@@ -23,13 +21,13 @@
2321
</array>
2422
</dict>
2523
<key>createdby</key>
26-
<string>Rex Zhang &lt;[email protected]&gt;</string>
24+
<string>Rex Zhang</string>
2725
<key>description</key>
2826
<string>Time Format Convert Tool</string>
2927
<key>disabled</key>
3028
<false/>
3129
<key>name</key>
32-
<string>Time Converter</string>
30+
<string>Time</string>
3331
<key>objects</key>
3432
<array>
3533
<dict>
@@ -44,7 +42,7 @@
4442
<key>argumenttrimmode</key>
4543
<integer>0</integer>
4644
<key>argumenttype</key>
47-
<integer>0</integer>
45+
<integer>1</integer>
4846
<key>escaping</key>
4947
<integer>102</integer>
5048
<key>keyword</key>
@@ -60,17 +58,17 @@
6058
<key>runningsubtext</key>
6159
<string></string>
6260
<key>script</key>
63-
<string>python3 afw.py call "{query}"</string>
61+
<string>python3 afw.py call $1</string>
6462
<key>scriptargtype</key>
65-
<integer>0</integer>
63+
<integer>1</integer>
6664
<key>scriptfile</key>
67-
<string>ls</string>
65+
<string></string>
6866
<key>subtext</key>
69-
<string>Examples: 1607609661, 2020-12-10 22:14:33, now</string>
67+
<string></string>
7068
<key>title</key>
71-
<string>Please enter timestamp, datetime string, "now", or space</string>
69+
<string></string>
7270
<key>type</key>
73-
<integer>0</integer>
71+
<integer>5</integer>
7472
<key>withspace</key>
7573
<true/>
7674
</dict>
@@ -108,19 +106,21 @@
108106
<key>A0BEA961-6062-42BD-9606-2257AA07F7AD</key>
109107
<dict>
110108
<key>xpos</key>
111-
<integer>275</integer>
109+
<real>275</real>
112110
<key>ypos</key>
113-
<integer>145</integer>
111+
<real>145</real>
114112
</dict>
115113
<key>E35A1CC1-CA0E-44E7-A39D-DB1C877AC4FC</key>
116114
<dict>
117115
<key>xpos</key>
118-
<integer>425</integer>
116+
<real>425</real>
119117
<key>ypos</key>
120-
<integer>145</integer>
118+
<real>145</real>
121119
</dict>
122120
</dict>
121+
<key>userconfigurationconfig</key>
122+
<array/>
123123
<key>webaddress</key>
124-
<string>https://github.com/rexzhang/alfred-workflow-time-converter</string>
124+
<string>https://github.com/rexzhang/alfred-workflows</string>
125125
</dict>
126126
</plist>

afw_time/main.py

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
import re
2+
from collections import deque
3+
from logging import Logger
4+
5+
import arrow
6+
7+
from afw_runtime import ICON_CLOCK, AFWException, AFWFuncAbc, AFWResponse
8+
9+
SHIFT_UNIT_MAP = {
10+
"ms": "microseconds",
11+
"s": "seconds",
12+
"m": "minutes",
13+
"h": "hours",
14+
"d": "days",
15+
"w": "weeks",
16+
"M": "months",
17+
"q": "quarters",
18+
"y": "years",
19+
}
20+
21+
22+
RE_TIMEZONE = "^[+-][0-9]{2}$"
23+
RE_SHIFT = "^[+-][0-9]+[smhdwMy]$"
24+
25+
26+
class TimeData:
27+
query: str
28+
logger: Logger
29+
30+
time: arrow.Arrow | None = None
31+
zone: str = "local"
32+
shifts: list = list()
33+
34+
def __init__(self, query: str, logger: Logger) -> None:
35+
self.query = query
36+
self.logger = logger
37+
38+
def _is_ext(self, data_str: str) -> bool:
39+
# time shift
40+
r = re.match(RE_SHIFT, data_str)
41+
if r:
42+
self.logger.debug(f"found shift info:{data_str}")
43+
44+
index = len(data_str) - 1
45+
unit = data_str[index]
46+
number = int(data_str[:index])
47+
kwargs = {
48+
SHIFT_UNIT_MAP[unit]: number,
49+
}
50+
self.shifts.append(kwargs)
51+
52+
# self.time = self.time.shift(**kwargs)
53+
return True
54+
55+
# time zone
56+
r = re.match(RE_TIMEZONE, data_str)
57+
if r:
58+
self.logger.debug(f"found zone info:{data_str}")
59+
self.zone = data_str
60+
61+
# self.time = self.time.to(self.zone)
62+
return True
63+
64+
return False
65+
66+
def __call__(self) -> "TimeData":
67+
query_deque = deque(self.query.split(" "))
68+
self.logger.debug(f"query_deque:{query_deque}")
69+
70+
for _ in range(len(query_deque)):
71+
data = query_deque.pop()
72+
if not self._is_ext(data):
73+
query_deque.append(data)
74+
break
75+
76+
time_base_str = " ".join(query_deque)
77+
self.logger.debug(f"query_deque:{query_deque}")
78+
self.logger.debug(f"time_base_str:{time_base_str}")
79+
80+
try:
81+
if time_base_str == "" or time_base_str.lower() == "now":
82+
self.time = arrow.now()
83+
84+
elif time_base_str.isdigit():
85+
self.time = arrow.get(int(time_base_str))
86+
87+
elif time_base_str.replace(".", "", 1).isdigit():
88+
self.time = arrow.get(float(time_base_str))
89+
90+
else:
91+
self.time = arrow.get(time_base_str)
92+
93+
if self.time is None:
94+
raise ValueError()
95+
96+
except (arrow.ParserError, ValueError) as e:
97+
self.logger.warning(
98+
f"Time paser failed, query={self.query}, time_base_str={time_base_str}, {e}"
99+
)
100+
raise AFWException(f"Bad format: {time_base_str}")
101+
102+
self.time = self.time.to(self.zone)
103+
for kwargs in self.shifts:
104+
self.time = self.time.shift(**kwargs)
105+
106+
return self
107+
108+
109+
class AFWFunc(AFWFuncAbc):
110+
icon_info = ICON_CLOCK
111+
112+
_time: arrow.Arrow | None = None
113+
_tips = False
114+
115+
def make_responses_from_time(self) -> list[AFWResponse]:
116+
return [
117+
AFWResponse(
118+
title=self._time.time.to("UTC").format("X"),
119+
subtitle="The time[UTC] as a Timestamp(s).",
120+
icon=self.icon_info,
121+
),
122+
AFWResponse(
123+
title=self._time.time.to("UTC").format("x"),
124+
subtitle="The time[UTC] as a Timestamp(us).",
125+
icon=self.icon_info,
126+
),
127+
AFWResponse(
128+
title=self._time.time.format("W, DDDD[th day]"),
129+
subtitle=f"The time[{self._time.zone}] as ISO Week date and Day for year.",
130+
icon=self.icon_info,
131+
arg=self._time.time.format("W"),
132+
),
133+
AFWResponse(
134+
title=self._time.time.format("YYYY-MM-DD HH:mm:ss"),
135+
subtitle=f"The time[{self._time.zone}] as Date and Time.",
136+
icon=self.icon_info,
137+
),
138+
AFWResponse(
139+
title=self._time.time.format(arrow.FORMAT_RFC3339),
140+
subtitle=f"The time[{self._time.zone}] as RFC3339 Formaself._time.",
141+
icon=self.icon_info,
142+
),
143+
AFWResponse(
144+
# https://www.w3.org/TR/NOTE-datetime
145+
title=self._time.time.format("YYYY-MM-DDTHH:mm:ssZZ"),
146+
subtitle=f"The time[{self._time.zone}] as ISO 8601/W3C Formaself._time.",
147+
icon=self.icon_info,
148+
),
149+
AFWResponse(
150+
title=self._time.time.format(arrow.FORMAT_RFC850),
151+
subtitle="The time[{self.zone}] as RFC850 Formaself._time.",
152+
icon=self.icon_info,
153+
),
154+
]
155+
156+
def append_tips(self):
157+
self.responses += [
158+
AFWResponse(
159+
title="Please enter timestamp, datetime string, 'now', or space",
160+
# subtitle=example1,
161+
subtitle="Examples: 1607609661, 2020-12-10 22:14:33, now",
162+
icon=self.icon_note,
163+
arg="1607609661",
164+
),
165+
AFWResponse(
166+
title="Change time zone or/and time shift",
167+
subtitle="Examples: now +08, now +1d, now +08 +1d",
168+
icon=self.icon_note,
169+
arg="now +08 +1d",
170+
),
171+
]
172+
173+
def append_error_message(self, message: str):
174+
self.responses.append(
175+
AFWResponse(title=message, icon=self.icon_error, valid=False)
176+
)
177+
178+
def _guess_input(self) -> arrow.Arrow | None:
179+
if len(self.args) == 0:
180+
self._tips = True
181+
query = "now"
182+
else:
183+
query = self.args[0]
184+
185+
try:
186+
t = TimeData(query=query, logger=self.logger)()
187+
except AFWException as e:
188+
self.append_error_message(f"Bad query: {e}")
189+
self._tips = True
190+
return None
191+
192+
return t
193+
194+
def _createa_responses(self):
195+
if self._time:
196+
self.append_responses(self.make_responses_from_time())
197+
198+
if self._tips:
199+
self.append_tips()
200+
201+
def _process(self) -> None:
202+
self._time = self._guess_input()
203+
if self._time is None:
204+
self._tips = True
205+
206+
self.logger.debug(f"self._time:{self._time}")
207+
self._createa_responses()
208+
return
209+
210+
211+
def main(args: list[str], logger: Logger) -> list[dict]:
212+
return AFWFunc(args, logger)()

afw_time/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "time",
3+
"version": "0.4.0",
4+
"icon": "icon.png"
5+
}
File renamed without changes.

afw_time_converter/icon.png

-6.4 KB
Binary file not shown.

0 commit comments

Comments
 (0)