MuppetGate Posted June 21, 2014 Posted June 21, 2014 (edited) Date Calculator Hello there! I needed a bit of motivation to learn Python and Alfred workflows, so I thought I’d kill two horses with one bullet, so to speak. Right, so this is a date calculator – kind of. It won’t tell you when you will the lottery, or how long you’ve got to hide your ‘arty videos’ before your wife gets home, but it will answer one or two very simple questions about dates. For example, if you enter dcalc 25.12.14 - 18.01.14 then it will tell you the number of days between those dates. Note that the workflow parses the command as you enter it, so you’ll see invalid command, invalid expression and invalid formaterrors as you type. Once you’ve completed the command then you’ll be given the result. You could also try dcalc 25.12.14 - now for the number of days until Christmas. (Always seems so far away . . .) Maybe you don’t want it in days, but would rather it in weeks: dcalc 25.12.14 - now w or days and weeks dcalc 25.12.14 - now wd or years, months, weeks and days dcalc 25.12.14 - now ymwd or dcalc 25.12.14 - now long will do the same thing. Personally, I always use the long format because it’s more accurate. For those who like to look ahead, you can add days to a date dcalc now + 6d or weeks dcalc 18.12.14 + 9w or combine ‘em dcalc 18.12.12 + 5y 9d 3w - 2d + 1d 1w What does that mess do? Take the date 18.12.12 Add 5 years Add another 9 days Add another 3 weeks Then take off 2 days Add another 1 day And then add another 1 week If you want to know what week number you’re in, then try this: dcalc today wn Or for a specific date: dcalc 25.12.14 wn You can also use the today thing in other places too: dcalc today + 4d And we have another thing called time because the workflow can handle times too: dcalc time + 6h 8M will add 6 hours and 8 minutes to the current time. Note the capital ‘M’ to denote minutes. Odd, I know . . . sorry, but the workflow has to distinguish between this and a small ‘m’ (for months). I figured make this one a capital because it would see much less use. (It has for me.) If you just want the current time, then just enter dcalc time Here’s another time calculation dcalc 14:35 + 6h That’s the time 6 hours from now, and for real nerdiness: dcalc 21.06.14@14:20 - 23.01.12@09:21 long Probably not all that useful, but some of this other stuff might be. You know all about dcalc now For giving you the current time and date. While you can use dcalc tomorrow for tomorrow’s date, and as you would expect dcalc tomorrow + 1d will give you the day after tomorrow. dcalc next tue will give you the date next Tuesday. Or for for Thursday you could enter dcalc next tue + 2d if you’re still a little too inebriated to realise that dcalc next thu will give you the same answer. That about covers it, I think. I haven’t done anything clever with locales, but you can pick a different date format with dcalcset date format And we also support both 12-hour and 24-hour time formats. dcalcset time format I would recommend sticking with the 24-hour format; it's a lot easier to type because the AM/PM symbols have to be in upper case. You can also set the combined date and time format using: dcalcset date and time format If you’re ever puzzled by invalid command or invalid expression errors, then start with the settings; they might be set incorrectly. Oh, almost forgot. dcalc easter Is the date for next Easter Sunday, for no other reason that I can never remember it, and now there’s an easy way to find out how many days until Christmas: dcalc today - christmas And to celebrate finishing my new book, I decided to add: dcalc passover Alternative parser If surround a simple expression in double quotes, then something quite magical happens: dcalc "4 hours 8 minutes after 4pm" or dcalc "6 weeks and 4 days after next wednesday" or dcalc "1 day after tomorrow" Yup! A natural date language parser! You can even combine it with the existing parser: dcalc "next friday" + 1d This is a little bit experimental (I might drop it later if it proves to be problematic), but I thought I'd throw it in for a bit of a fun. Credits A list of things that made my first attempt at Python programming possible: Dean Jackson for his more-than-slightly awesome Alfred Workflow framework(Jetbrains(HumanFriendly(Python-DateUtil(PyPEG(ParseDateTime(Programming Praxis(MIT(http://opensource.org/licenses/MIT) one will do. :-)The MIT License (MIT) Copyright © 2014 MuppetGate Media Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Edited September 3, 2016 by MuppetGate xilopaint, bivalvegruff, 40-02 and 2 others 4 1
deanishe Posted June 22, 2014 Posted June 22, 2014 (edited) Very nice. Have you thought about making a Script Filter, so that you get the result/error message live? Kinda like this: Edited June 22, 2014 by deanishe alfredappuser 1
deanishe Posted June 22, 2014 Posted June 22, 2014 It will only say: Invalid command! Like he said, you probably need to check the settings. For whatever reason, the default date format in the workflow is "dd-mm-yy", not "dd.mm.yy" as in the description…
MuppetGate Posted June 22, 2014 Author Posted June 22, 2014 It will only say: Invalid command! Yes, not only did I forget to set the correct default, I also forgot to credit the HumanFriendly folk for a library. I'll sort it out later today.
MuppetGate Posted June 22, 2014 Author Posted June 22, 2014 It will only say: Invalid command! Okay, that should have taken care of it.
MuppetGate Posted June 22, 2014 Author Posted June 22, 2014 Very nice. Have you thought about making a Script Filter, so that you get the result/error message live? Kinda like this: That's very clever! I'll have a crack at it when I've checked some examples. MuppetGate 1
deanishe Posted June 22, 2014 Posted June 22, 2014 (edited) It's child's play compared to the rest of the workflow. Very impressive stuff! You just need to change the Keyword to a Script Filter and use wf.add_item() and wf.send_feedback() instead of print(). Here's the hacky wrapper I made to turn it into a Script Filter. Lines 26, 28 and 31 are the important bits, the rest is just boilerplate: from __future__ import print_function, unicode_literals import sys from StringIO import StringIO from workflow import Workflow, ICON_ERROR from date_calculator import main as other_main from date_format_mappings import DEFAULT_WORKFLOW_SETTINGS def main(wf): # Replace sys.stdout to capture the script output stdout_orig = sys.stdout sys.stdout = StringIO() # Run the script and grab the output other_main(wf) result = sys.stdout.getvalue() # Put sys.stdout back together again, so wf.send_feedback() sends its # output to the right place sys.stdout.close() sys.stdout = stdout_orig # Add error/output to list of results if result.startswith('Invalid '): wf.add_item(result, valid=False, icon=ICON_ERROR) else: wf.add_item(result, 'Copy to clipboard', valid=True, arg=result) # Send XML output to Alfred wf.send_feedback() if __name__ == '__main__': wf = Workflow(default_settings=DEFAULT_WORKFLOW_SETTINGS) sys.exit(wf.run(main)) Here's how to make a Script Filter with Alfred-Workflow (you should probably skip straight to the section on Actions), and here are the docs on add_item(). You need to set a value for arg and valid=True in add_item() to make a result actionable. I just used one of the system icons supported by Alfred-Workflow for the error message. Edited October 8, 2015 by deanishe Fix URLs
MuppetGate Posted June 23, 2014 Author Posted June 23, 2014 Thanks. The newer version works fine. Great! :-) Thanks for letting me know. I've now implemented the 'parse-as-you-type' feature suggested by Dean, so there's a new version up On Packal.org
raguay.customct Posted June 23, 2014 Posted June 23, 2014 The newer, newer version works good to. I also like the feedback. I mostly use script filters in my workflows just so that I can get feedback easily. Thanks
MuppetGate Posted June 27, 2014 Author Posted June 27, 2014 Me again. I've just dropped a new version of the date calculator onto Packal. Fixes a few bugs and simplifies the error reporting. Also added a few macros shortcuts for today, tomorrow, days of the week and Christmas
deanishe Posted June 27, 2014 Posted June 27, 2014 Pfft! It doesn't know my birthday. USELESS! Nice update I had a look in the workflow directory. There appears to be another copy of the workflow within the workflow. I suspect that wants removing…
MuppetGate Posted June 27, 2014 Author Posted June 27, 2014 Done! I'll get the hang of this one day . . .
dfay Posted June 30, 2014 Posted June 30, 2014 Nice. I've made a couple modifications you might consider: I added one line to the DATE_MAPPINGS array in date_format_mappings.py - very clear code that was easy to customize: 'yyyy-mm-dd':{'name': 'long inverted US date (-)','date-format':'%Y-%m-%d','regex':'\d{4}-\d{2}-\d{2}'}, I added an additional Applescript output from the dcalc script filter with a shift modifier to open Fantastical to the calculated date, with the following very simple script: on alfred_script(q) tell application "Fantastical" parse sentence (q) end tell end alfred_script This makes for a nice quick way to quickly calculate a date and immediately start adding an event or checking what's on my calendar for that date.
deanishe Posted June 30, 2014 Posted June 30, 2014 Good thinking, dfay! Especially sending it to Fantastical. I think Apple Calendar can handle simpler dates, too, but I'm not sure. One minor gripe: yyyy-mm-dd is an international date format, not a US one. Everyone uses it.
MuppetGate Posted June 30, 2014 Author Posted June 30, 2014 Nice. I've made a couple modifications you might consider: I added one line to the DATE_MAPPINGS array in date_format_mappings.py - very clear code that was easy to customize: 'yyyy-mm-dd':{'name': 'long inverted US date (-)','date-format':'%Y-%m-%d','regex':'\d{4}-\d{2}-\d{2}'}, I added an additional Applescript output from the dcalc script filter with a shift modifier to open Fantastical to the calculated date, with the following very simple script: on alfred_script(q) tell application "Fantastical" parse sentence (q) end tell end alfred_script This makes for a nice quick way to quickly calculate a date and immediately start adding an event or checking what's on my calendar for that date. Thanks very much for that. I'll add in the date format (not sure how I managed to miss it to be honest). I figure that any additional outputs should be pretty easy for anyone to add; that's why I decided to keep the extra text down to a minimum, and tried to make it easy to parse. But a great suggestion, and I'm going to try out Fantastical.
MuppetGate Posted July 1, 2014 Author Posted July 1, 2014 (edited) Pfft! It doesn't know my birthday. USELESS! Fixed. Edited July 1, 2014 by MuppetGate
deanishe Posted July 1, 2014 Posted July 1, 2014 It doesn't work for me I followed the instructions above, but "dcalcset list add dean xx-xx-xxxx" give me an "Invalid command" error "dcalcset format" now appears to be an unknown command You also appear to have removed the download link from the OP. It's got links to all the stuff you used to make the workflow (apart from Smirnoff), but there doesn't appear to be one to the actual workflow any more!
deanishe Posted July 1, 2014 Posted July 1, 2014 And another thing: the workflow description on Packal says "A very basic date calculator". Basic? Premium more like.
MuppetGate Posted July 1, 2014 Author Posted July 1, 2014 (edited) It doesn't work for me I followed the instructions above, but "dcalcset list add dean xx-xx-xxxx" give me an "Invalid command" error "dcalcset format" now appears to be an unknown command You also appear to have removed the download link from the OP. It's got links to all the stuff you used to make the workflow (apart from Smirnoff), but there doesn't appear to be one to the actual workflow any more! Okay, I imagine you're entering in the correct date format. The dcalcset format seems to be okay at my end too. I'll try loading it from packal to make sure I haven't missed anything. Are you running with Python 2.7? Edited July 1, 2014 by MuppetGate
deanishe Posted July 1, 2014 Posted July 1, 2014 Yeah, double-checked the format, deleted the settings file and re-installed before posting. I'm on Mavericks, so Python 2.7. FWIW, python will always refer to the system Python in Alfred, as it doesn't use your PATH. Unless someone was dumb enough to overwrite /usr/bin/python…
MuppetGate Posted July 1, 2014 Author Posted July 1, 2014 (edited) Right, I'm going to have to sleep on this one, I think. Can't think why this wouldn't work on your machine. Always tricky when you can't see it running ... Edited July 1, 2014 by MuppetGate
MuppetGate Posted July 1, 2014 Author Posted July 1, 2014 Quick question: What happens if you enter dcalcshow list
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now