Mojave Date Extraction Issues

Hi folks!

I need to blow the dust off a classic. I used the wonderful Dates & Times in AppleScripts posts to build a workflow that enters the Tuesday and Thursday on a product based on a given date regardless of which day of the week it falls on.

I’m having trouble running this in Mojave. It has run for years in other OS’s without issue. Mojave works thru Thursday. Friday & Saturday are moving to the next week. Sunday 12/30/18 thru Thursday 1/3/19 return Week 0. Friday 1/4/19 & Saturday 1/5/19 return Week 1.

I would really appreciate your help.


--Mojave Works Thru Thursday. Friday & Saturday Move To The Next Week.
--Sunday 12/30/18 thru Thursday 1/3/19 return Week 0.
--Friday 1/4/19 & Saturday 1/5/19 return Week 1.

--ACTIVATE ONE OF THESE 3 TEST STRINGS.
--set fmData to "123456|SJL123085|Product|12/31/18" --Text String Example: OK
--set fmData to "123456|SJL123085|Product|01/03/19" --Text String Example: OK
--set fmData to "123456|SJL123085|Product|01/04/19" --Error. Moves to next week.

set TempTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to "|"
set TIDnum to count text items of fmData
set GPON to first text item of fmData
set VerCode to second text item of fmData
set ProType to third text item of fmData
set IHD to fourth text item of fmData
set AppleScript's text item delimiters to TempTID

--Parse IHD.
set TempTID2 to AppleScript's text item delimiters
set AppleScript's text item delimiters to "/"
set TIDnum2 to count text items of IHD
set ihdMonth to first text item of IHD
set ihdDay to second text item of IHD
set ihdYear to third text item of IHD
set AppleScript's text item delimiters to TempTID2

--Get week number.
date (IHD) as text
set currentWeekNumber to ((getDatesWeekNum((date (IHD)))) - (getDatesWeekNum(date ("1/1/" & ((ihdYear)) as string))))
display dialog currentWeekNumber

--Get Tuesday & Thursday. 
getdatesforweeknum((ihdYear), (currentWeekNumber))
set inhomeweek to (getdatesforweeknum((ihdYear), (currentWeekNumber)))
count the items in inhomeweek
get item 1 of inhomeweek
set Tu to (item 1 of inhomeweek)
get item 3 of inhomeweek
set Thu to (item 3 of inhomeweek)

set Tue to Tu as text
date_wo_year(Tue) as text
set Thur to Thu as text
date_with_year(Thur) as text

set PMdate to (date_wo_year(Tue)) & "-" & (date_with_year(Thur)) as text

display dialog PMdate



--Week number calculation.
on getDatesWeekNum(theDate)
	set {dDate, dDateNum} to {"1/1/1000", 364878}
	return ((theDate - (date dDate)) div days + dDateNum) div 7 + 1
end getDatesWeekNum

--MOJAVE: Choose Sunday instead of Monday.
on getdatesforweeknum(yearNum, weekNum)
	set Jan4 to date "Tuesday, January 4, 2000 at 3:30:00 AM"
	set Jan4's year to yearNum
	set baseSunday to date "Sunday, January 2, 2000 at 3:30:00 AM" --Or any Sunday in the past - MOJAVE MOD.
	set week1Start to Jan4 - (Jan4 - baseSunday) mod weeks
	set weekNStart to week1Start + (weekNum - 1) * weeks
	set datesInWeek to {}
	repeat with i from 0 to 6 * days by days
		set end of datesInWeek to weekNStart + i as list
	end repeat
	return datesInWeek
end getdatesforweeknum

--Format text date to number date without year.
to date_wo_year(textDate)
	set {year:y, month:m, day:d} to date textDate
	tell (y * 10000 + m * 100 + d) as string to text 5 thru 6 & "/" & text 7 thru 8
end date_wo_year

--Format text date to number date with year.
to date_with_year(textDate)
	set {year:y, month:m, day:d} to date textDate
	tell (y * 10000 + m * 100 + d) as string to text 5 thru 6 & "/" & text 7 thru 8 & "/" & text 1 thru 4
end date_with_year



At one point we were looking to move everything to JXA so I built this one. Sadly, the rest of script is not supported by one developer or another so we had to abandon it.

The first test string contains an error: 1/1-2/3/2019. (Note Jan 1-Feb 3, 2019.) The others work without issue.

Is it still not possible to run JXA inside of AS?

var app = Application.currentApplication();
app.includeStandardAdditions = true;

var sysEvents = Application('System Events');
var finder = Application('Finder');
var indd = 'com.adobe.InDesign';
var inddA = Application('com.Adobe.InDesign');
// File = ([String.path])
var workFldr = Path('/Users/Shared/Work/')
var workFldrIndd = "/Users/Shared/Work/"
var inddDoc = indd.activeDocument;


// ACTIVATE ONE OF THESE 3 TEST STRINGS.
// The first test string contains an error: 1/1-2/3/2019. The others work OK.
// var fmData = "123456|SJL123085|Product|12/31/18"; // ERROR. Note 2nd month.
// var fmData = "123456|SJL123085|Product|01/03/19";
// var fmData = "123456|SJL123085|Product|01/04/19";
var array = fmData.split('|');
var arrayLength = array.length;
for (var i = 0; i < arrayLength; i++) {
    var currentArrayItem = array[i];
}
var gpon = array[0];
var verCode = array[1];
var proType = array[2];
var ihd = array[3];

// Parse IHD.
var array = ihd.split('/');
var arrayLength = array.length;
for (var i = 0; i < arrayLength; i++) {
    var currentArrayItem = array[i];
}
var ihdMonth = array[0];
var ihdDay = array[1];
var ihdYear = array[2];

// Remove '/' from IHD for job save.
var docIHD = ihd;
docIHD = docIHD.split('/').join('');

var verCodeIHD = ((verCode) + `-` + (docIHD));
// app.displayDialog(`The new InDesign document will be named \r` + `\'` + (verCodeIHD) + `.\'`);

// Get Tuesday & Thursday of IHW.
var myIHD = new Date(ihd);
var first = myIHD.getDate() - myIHD.getDay();
var third = first + 2; // Get Tuesday.
var fifth = first + 4; // Get Thursday.
var thirdDay = new Date(myIHD.setDate(third)).toLocaleDateString();
var fifthDay = new Date(myIHD.setDate(fifth)).toLocaleDateString();
// Tuesday.
var array = thirdDay.split('/');
var arrayLength = array.length;
for (var i = 0; i < arrayLength; i++) {
    var currentArrayItem = array[i];
}
var tuesMonth = array[0];
var tuesDay = array[1];
// Thursday.
var array = fifthDay.split('/');
var arrayLength = array.length;
for (var i = 0; i < arrayLength; i++) {
    var currentArrayItem = array[i];
}
var thurMonth = array[0];
var thurDay = array[1];
var thurYear = array[2];

var pmDates = ((tuesMonth) + `/` + (tuesDay) + `-`+ (thurMonth) + `/` + (thurDay) + `/` + (thurYear));
app.displayDialog(pmDates);


Hi.

AppleScript dates have had a bug for the past few system versions whereby their string representations are out with their actual properties if they represent a date before some time in the 1800s. The threshold date and the amount of difference depend on what time zone you’re in. Your getDatesWeekNum handler (which looks as if it may be based on an old one of mine), relies on sticking the keyword ‘date’ before the string “1/1/1000”, which is unlikely these days to produce a date with a day value of 1, the month January, the year 1000, AND the time 0. It’ll be anything from a few minutes to a few hours out on either side. So the handler itself will produce the wrong result. But I don’t understand what the handler’s supposed to do. It returns 105289 for today’s date on my machine, which is pretty high for a week number!

I don’t understand the script as a whole either. Are you seeking to take date strings in US short-date form and get the week number of the weeks in which the dates occur and the Tuesday and Friday of those weeks? As appleScript dates? Are you counting a week as starting on Sunday or Monday?

Further to the above, these are more reliable versions of the week-number and dates-that-week handlers. They now take a weekday parameter too to indicate the day of the week on which weeks should be understood to start:

on getDatesWeekNum(theDate, startWeekday)
	-- Get the beginning of the week starting on the given weekday which contains 4th January in the year of the middle of the week containing the given date.  :)
	set Jan4 to theDate + ((startWeekday - (theDate's weekday) + 6) mod 7 - 3) * days -- Middle of date week.
	tell Jan4 to set {its day, its month, its time} to {4, January, 0} -- 4th January that year.
	set week1Start to Jan4 - ((Jan4's weekday) - startWeekday + 7) mod 7 * days -- Start of 4th January week.
	
	-- Taking that as week 1, return the week number of the input date and the year to which it relates.
	return {|week number|:(theDate - week1Start) div weeks + 1, |year|:Jan4's year}
end getDatesWeekNum

getDatesWeekNum(current date, Monday)
on getDatesforWeekNum(yearNum, weekNum, startWeekday)
	-- Get the beginning of the week starting on the given weekday which contains 4th January in the given year.
	tell (current date) to set {Jan4, its day, its month, its year, its time} to {it, 4, January, yearNum, 0}
	set week1Start to Jan4 - ((Jan4's weekday) - startWeekday + 7) mod 7 * days
	-- Get the beginning of the week (weeknum -1) weeks after that.
	set weekNStart to week1Start + (weekNum - 1) * weeks
	-- Populate and return a list of the dates in that week.
	set datesInWeek to {}
	repeat with i from 0 to 6 * days by days
		set end of datesInWeek to weekNStart + i
	end repeat
	
	return datesInWeek
end getDatesforWeekNum

getDatesforWeekNum(2018, 48, Monday)

Edit: getDatesWeekNum handler shortened and debugged and now returns a record containing the week number and the year to which it relates, which may be different from the year of the input date.

A couple of alternatives:

use AppleScript version "2.5" -- requires macOS 10.11
use framework "Foundation"
use scripting additions

-- classes, constants, and enums used
property NSWeekOfYearCalendarUnit : a reference to 8192

on getDatesWeekNum(theDate, startWeekday)
	set theCal to current application's NSCalendar's calendarWithIdentifier:(current application's NSCalendarIdentifierGregorian)
	theCal's setFirstWeekday:(startWeekday as integer)
	theCal's setMinimumDaysInFirstWeek:4
	return theCal's component:NSWeekOfYearCalendarUnit fromDate:theDate
end getDatesWeekNum

on getDatesforWeekNum(yearNum, weekNum, startWeekday)
	set startWeekday to startWeekday as integer
	set theCal to current application's NSCalendar's calendarWithIdentifier:(current application's NSCalendarIdentifierGregorian)
	theCal's setFirstWeekday:startWeekday
	theCal's setMinimumDaysInFirstWeek:4
	set startDate to theCal's dateWithEra:1 yearForWeekOfYear:yearNum weekOfYear:weekNum |weekday|:startWeekday hour:0 minute:0 |second|:0 nanosecond:0
	set weekNStart to startDate as date
	set datesInWeek to {}
	repeat with i from 0 to 6 * days by days
		set end of datesInWeek to weekNStart + i
	end repeat
	return datesInWeek
end getDatesforWeekNum

I thought we’d be seeing ASObjC versions from you before long! :wink:

They return the rights result for the end of December too, which mine don’t. :rolleyes: I’m rethinking mine as I write and will either delete or replace them later.

Edit: OK. My getDatesWeekNum handler’s now fixed and shortened. The 4th January date is now derived from the date in the middle of the week containing the input date instead of from the date itself. I think the other handler’s OK, although there’s no ceiling on the week number it can be passed.

I think the first handler should really return the year as well as the week, because it may not match the year of the date:

use AppleScript version "2.5" -- requires macOS 10.11
use framework "Foundation"
use scripting additions

-- classes, constants, and enums used
property NSYearForWeekOfYearCalendarUnit : a reference to 16384
property NSWeekOfYearCalendarUnit : a reference to 8192

on getDatesWeekNum(theDate, startWeekday)
	set theCal to current application's NSCalendar's calendarWithIdentifier:(current application's NSCalendarIdentifierGregorian)
	theCal's setFirstWeekday:(startWeekday as integer)
	theCal's setMinimumDaysInFirstWeek:4
	return {theCal's component:NSWeekOfYearCalendarUnit fromDate:theDate, theCal's component:NSYearForWeekOfYearCalendarUnit fromDate:theDate}
end getDatesWeekNum

Good idea! I’ve now incorporated that into my version too.

Hi Nigel,

Yessir. It is based on your code.

FWIW, this code runs in 3 US time zones: EST, CST, Arizona Time. We have had bugs with the Arizona time zone. (They don’t follow daylight savings time.) I assumed they were OS bugs and/or issues with the last leap year and compensated for them. They worked themselves out and all locations are now using the same calculator.

It is part of the a much larger script. This portion uses the delivery date, which can be any day of the week except Friday and Saturday, to find the week number and extract the Tuesday and Thursday to be printed on the piece.

For example:
Delivery date: 01/03/19
Tuesday: 01/01/19
Thursday: 01/03/19
Populates: Postmaster please mail by 01/03-01/05/2019. Time Sensitive.

I was previously using baseMonday but kept getting errors in Mojave so I used Sunday - not being sure whether the OS was using Mon.-Sun. or Sun.-Sat. as the week, even though Mojave seemed to using Mon.-Sun. and High Sierra was using Mon.-Sat. in the US. Not the most elegant solution for sure. The calculated week numbers seem to run from Thursday to Wednesday. For our current needs, the hack works but I really would like a better solution moving forward.

I’ve modified getDatesForWeekNum again so that it only returns the dates of weekdays specified in the call to it.


--Mojave Works Thru Thursday. Friday & Saturday Move To The Next Week.
--Sunday 12/30/18 thru Thursday 1/3/19 return Week 0.
--Friday 1/4/19 & Saturday 1/5/19 return Week 1.

--ACTIVATE ONE OF THESE 3 TEST STRINGS.
--set fmData to "123456|SJL123085|Product|12/31/18" --Text String Example: OK
--set fmData to "123456|SJL123085|Product|01/03/19" --Text String Example: OK
set fmData to "123456|SJL123085|Product|01/04/19" --Error. Moves to next week.

set TempTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to "|"
set TIDnum to count text items of fmData
set GPON to first text item of fmData
set VerCode to second text item of fmData
set ProType to third text item of fmData
set IHD to fourth text item of fmData
set AppleScript's text item delimiters to TempTID

--Parse IHD.
set TempTID2 to AppleScript's text item delimiters
set AppleScript's text item delimiters to "/"
set TIDnum2 to count text items of IHD
set ihdMonth to first text item of IHD
set ihdDay to second text item of IHD
set ihdYear to 2000 + (third text item of IHD)
set AppleScript's text item delimiters to TempTID2

-- Set the preferred week-start day.
set weekStartDay to Monday

-- Get an AS version of the IHD date.
tell (current date) to set {ihdDate, its day, its year, its month, its day, its time} to {it, 1, ihdYear, ihdMonth, ihdDay, 0}
--Get week number and the year of which it's that number (which may be different from ihdDate's year).
set {|week number|:currentWeekNumber, |year|:weekYear} to getDatesWeekNum(ihdDate, weekStartDay)

display dialog (ihdDate as text) & ":" & linefeed & weekStartDay & "-start week " & currentWeekNumber & " of " & weekYear

--Get the Tuesday & Thursday dates in that week. 
set {Tue, Thu} to (getDatesForWeekNum(weekYear, currentWeekNumber, {Tuesday, Thursday}, weekStartDay))

set PMdate to (date_wo_year(Tue)) & "-" & (date_with_year(Thu)) as text

display dialog PMdate



--Week number calculation.
on getDatesWeekNum(theDate, startWeekday)
	-- Get the beginning of the week starting on the given weekday which contains 4th January in the year of the middle of the week containing the given date.  :)
	set Jan4 to theDate + ((startWeekday - (theDate's weekday) + 6) mod 7 - 3) * days -- Middle of date week.
	tell Jan4 to set {its day, its month, its time} to {4, January, 0} -- 4th January that year.
	set week1Start to Jan4 - ((Jan4's weekday) - startWeekday + 7) mod 7 * days -- Start of 4th January week.
	
	-- Taking that as week 1, return the week number of the input date and the year to which it relates.
	return {|week number|:(theDate - week1Start) div weeks + 1, |year|:Jan4's year}
end getDatesWeekNum

on getDatesForWeekNum(yearNum, weekNum, weekdaysRequired, startWeekday)
	if (weekdaysRequired is {}) then set weekdaysRequired to {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday}
	-- Get the beginning of the week starting on the given weekday which contains 4th January in the given year.
	tell (current date) to set {Jan4, its day, its month, its year, its time} to {it, 4, January, yearNum, 0}
	set week1Start to Jan4 - ((Jan4's weekday) - startWeekday + 7) mod 7 * days
	-- Get the beginning of the week (weeknum -1) weeks after that.
	set weekNStart to week1Start + (weekNum - 1) * weeks
	-- Populate and return a list of the dates in that week.
	set datesInWeek to {}
	repeat with i from 0 to 6 * days by days
		set thisDate to weekNStart + i
		if (thisDate's weekday is in weekdaysRequired) then set end of datesInWeek to weekNStart + i
	end repeat
	
	return datesInWeek
end getDatesForWeekNum

--Format text date to number date without year.
to date_wo_year(theDate)
	set {year:y, month:m, day:d} to theDate
	tell (y * 10000 + m * 100 + d) as text to text 5 thru 6 & "/" & text 7 thru 8
end date_wo_year

--Format text date to number date with year.
to date_with_year(theDate)
	set {year:y, month:m, day:d} to theDate
	tell (y * 10000 + m * 100 + d) as text to text 5 thru 6 & "/" & text 7 thru 8 & "/" & text 1 thru 4
end date_with_year

Thanks Nigel & Shane!!!
Works like a charm!!! :smiley:
Have a great weekend and holiday season! :cool: