3 days calculator

Hello guys,

I would like to create a script that it gets as input a specific date and returns a range of ± 3 days.

For example, if the input is “31/01/2020”

I would like to have the output message as : “The expected delivery dates are from 28/01/2020 to 03/02/2020”

and pasting also this output in my clipboard.

Could you please advise me if it is feasible and how to do it?

Until now I created in Script Editor:

set {d1, d2} to {(date (“31/01/2020” as string)) - 3 * days, (date (“31/01/2020” as string)) + 3 * days}
return {d1, d2}

but I get as result:

{date “Tuesday 28 January 2020 at 00:00:00”, date “Monday 3 February 2020 at 00:00:00”}

Thank you in advance

The most complicated part is to format the dates to dd/MM/yyyy regardless of the locale setting

set currentDate to (current date)

set {lowerBound, upperBound} to {currentDate - (3 * days), currentDate + (3 * days)}
set theMessage to "The expected delivery dates are from " & createDateString(lowerBound) & " to " & createDateString(upperBound)

on createDateString(theDate)
	set {year:yr, month:mn, day:dy} to theDate
	return pad(dy) & "/" & pad(mn as integer) & "/" & (yr as text)
end createDateString

on pad(v)
	return text -2 thru -1 of ((v + 100) as text)
end pad

I would use :

set dateString to "31/01/2020"
set {d1, d2} to {short date string of ((date dateString) - 3 * days), short date string of ((date dateString) + 3 * days)}
return {d1, d2} --> {"28/01/2020", "03/02/2020"}

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 31 janvier 2020 19:39:31

On my de_CH locale I get

→ {“28.01.2020”, “03.02.2020”}

I apologizes, I ignored that the system is able to return dots when the original string contain slashes.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 31 janvier 2020 20:27:10

Amazing guys!

Stefan’s approach is most close to what I want to do.

However I have two questions:

i) What about if I want to do the calculations not based on the current date, but on a different one? As the order dates differ, I would like to use the day that is pasted into the clipboard. (i.e. 28/01/2020)

I tried to amend the first line “set currentDate to (current date)” to “the clipboard” but I receive an error.

ii) Our inventory system uses the formatting YYYY-MM-DD. If I copy into the clipboard the date in this specific format, is there a way to do the calculations for this input as well?

Thank you!

You can use any AppleScript date object.

Please note that an AppleScript date is not a string, it’s a specific class. You have to convert the string to date for example

set dateString to "2020-02-01"
set {TID, text item delimiters} to {text item delimiters, "-"}
set {yr, mn, dy} to text items of dateString
set text item delimiters to TID
set theDate to (current date)
tell theDate to set {year, month, day} to {yr as integer, mn as integer, dy as integer}

To convert a date string to another format I recommend to use a date formatter from the Foundation framework.

use AppleScript version "2.5"
use framework "Foundation"
use scripting additions

property |⌘| : a reference to current application

set inputDateString to "2020-02-01"
set dateFormatter to |⌘|'s NSDateFormatter's alloc()'s init()
set dateFormatter's locale to |⌘|'s NSLocale's localeWithLocaleIdentifier:"en_US_POSIX"
set dateFormatter's dateFormat to "yyyy-MM-dd"
set theDate to dateFormatter's dateFromString:inputDateString
set dateFormatter's dateFormat to "dd/MM/yyyy"
set outputDateString to dateFormatter's stringFromDate:theDate

Thank you so much again for the help.

Unfortunately I am still struggling with the yyyy-mm-dd formatting!

For the input 2016-02-15 with the initial version I was getting incorrect dates (from 10/05/2020 to 06/11/20200.

And with the last suggestion I receive a weird error:

-[__NSTaggedDate length]: unrecognized selector sent to instance 0x39ed987440c7c893”

So I just thought of a different approach/workaround!

As the yyyy-mm-dd formatting is only in one specific app that I use and all the rest apps show the date in the normal dd/mm/yyyy formatting, I would like to ask of how to add a check in the beginning of the code.

So if the copied text in the clipboard has 4 digits dash at the beginning, to revert the date, elsewhere to use the normal ± 3 days calculations.

You are mixing up strings and dates which are not directly interchangeable.

In AppleScript the date keyword in front of a string creates an AppleScript date if the string matches a supported date format.

All my code snippets work. Both date strings must be pure strings.

The error [__NSTaggedDate length] indicates that the caller is a date.

Unfortunately it doesn’t work for me and there is the “date” keyword in front of the variable.

That’s why I suggested my workaround.

The copied text in the clipboard is a pure date.

So how can I check if the copied text in the clipboard has “4 digits” and a dash at the beginning, and to assign those values (YYYY, MM, DD) to 3 new variables, and then use the normal ± 3 days calculations, elsewhere to do nothing?

As I said, the date strings must be pure strings, remove the date keyword

It is pure now, but a new error message:

“Can’t make «class ocid» id «data optr00000000F06FDE57F47F0000» into type number.”

By the way, as I want to have one script only for both date formats, don’t you think my workaround is good?

To check if the text from the clipboard has the pattern “first 4 characters are numbers and then there is a dash” to assign the first four digits to variable yyyy, the sixth and seventh digits to variable mm and the last two digits to variable dd. Elsewhere nothing.

You have to coerce the result of the date formatter to text to get an AppleScript string

set outputDateString to (dateFormatter's stringFromDate:theDate) as text

I recommend to use the NSDateFormatter solution. Try to convert the string with one format. If the result is missing value use the other format.

Thanks, well you were right!

With a few trials, it now works for the dates in “yyyy/mm/dd” but not anymore for the “dd/mm/yyyy” ones.

For the latter, I receive now the error:
“Can’t get item 2 of “dd/mm/yyyy”

So here is the whole code:

set dateString to the clipboard
set {TID, text item delimiters} to {text item delimiters, "-"}
set {yr, mn, dy} to text items of dateString
set text item delimiters to TID
set theDate to (current date)
tell theDate to set {year, month, day} to {yr as integer, mn as integer, dy as integer}

try
	set inputDate to theDate
on error
	display dialog "The content is not a date." buttons "OK"
	error number -128
end try

set {lowerBound, upperBound} to {inputDate - (3 * days), inputDate + (3 * days)}
set theMessage to "The expected dates are from " & createDateString(lowerBound) & " to " & createDateString(upperBound) & "."
set the clipboard to theMessage
display dialog theMessage buttons "OK" giving up after 10

on createDateString(theDate)
	set {year:yr, month:mn, day:dy} to theDate
	return pad(dy) & "/" & pad(mn as integer) & "/" & (yr as text)
end createDateString

on pad(v)
	return text -2 thru -1 of ((v + 100) as text)
end pad

and here are all the different date formats we have in our inventory / logistics tools and that I would like to have them as inputs (by copying the whole string and not only specific part)

2020-02-02 12:02:27
3 Jan 2020, 15:29:40
2020-02-01 8:34 AM
2019-12-21
05/01/2020

Furthermore, I just noticed that only for the dates 2020-02-02 and 2020-02-01 the returned expected dates are correct.

For other dates, like 2020-01-31 , 2019-11-20 , 2019-09-12 , all the returned ±3 days range is incorrect.

This is a solution with NSDateFormatter which considers all given date formats

use AppleScript version "2.5"
use framework "Foundation"
use scripting additions

property |⌘| : a reference to current application
property dateFormatter : missing value

set formatter to |⌘|'s NSDateFormatter's alloc()'s init()
set formatter's locale to (|⌘|'s NSLocale's localeWithLocaleIdentifier:"en_US_POSIX")
set dateFormatter to formatter

set inputDateString to the clipboard
set dateFormat to checkDateFormat(inputDateString)
set dateFormatter's dateFormat to dateFormat
set inputDate to (dateFormatter's dateFromString:inputDateString)
if inputDate is missing value then
	display dialog "The content is not a valid date." buttons "Cancel" default button 1
	return
end if

set inputDate to inputDate as date
set {lowerBound, upperBound} to {inputDate - (3 * days), inputDate + (3 * days)}
set theMessage to "The expected dates are from " & dateToString(lowerBound) & " to " & dateToString(upperBound) & "."
set the clipboard to theMessage
display dialog theMessage buttons "OK" giving up after 10 default button 1

on checkDateFormat(dateString)
	if dateString contains "-" then
		if dateString ends with "M" then
			return "yyyy-MM-dd h:mm a"
		else if length of dateString is 10 then
			return "yyyy-MM-dd"
		else
			return "yyyy-MM-dd HH:mm:ss"
		end if
	else if dateString contains "/" then
		return "dd/MM/yyyy"
	else
		return "d MMM yyyy, HH:mm:ss"
	end if
end checkDateFormat

on dateToString(theDate)
	set dateFormatter's dateFormat to "dd/MM/yyyy"
	return (dateFormatter's stringFromDate:theDate) as text
end dateToString

Stefan you are awesome!!!

Thank you so much for all!