UNix date and time conversion

I’m aware of that Stefan.
My problem was that I don’t know which value is relevant for the asker.
We don’t know if he must compare dates from different sources so one ‘format’ may be better than the other one.

It’s really efficient.
I replaced the date value by 1471788852197 and ran the script.
The result became : date “dimanche 21 août 2016 à 16:22:38”
As you may see, this time it is correctly at summer hour.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mardi 20 décembre 2016 12:12:10

I don’t think so – here they differ by 11 hours. The problem is that the reference date is GMT, but using a string like that makes it local time

I think you need to do something like this:

set referenceDate to "1/1/1970"
set startDate to (date referenceDate) + xmlDate / 1000 + (time to GMT)
set endDate to startDate + xmlDuration

Shane,

the dates

  • 2016-12-19 14:22:38 +0000
  • 2016-12-19 15:22:38 +0100

are practically the same (the same moment in time), the appearance is different due to the different time zones.

Both Foundation NSDate and AppleScript date are actually wrapper for a number. They don’t know time zones.

UNIX dates are always in UTC.

Here on MacScripter the dates are displayed in UTC if you are not logged in and in your local time zone if you are. But the source of the date is the same.

Stefan,

If I run your original script, asStartDate is returned as:

date “Tuesday, 20 December 2016 at 1:14:12 am”

Your native version returns startDate as:

date “Monday, 19 December 2016 at 2:14:12 pm”

They differ by my UTC offset.

The question, really, is whether whatever is producing the original XML is using local time or UTC. If it’s local time, the AS result is correct; if it’s UTC, the other is correct.

Only the OP can tell us which it is, by doing a test.

If we asume that here, then you need to add time to GMT as above.

@ Shane & Stefan

Adding the time to GMT value doesn’t completely solve the problem.

At this time, here time to GMT is +1 hour

If I apply it to the first example, I get date "lundi 19 décembre 2016 à 14:22:38" + (time to GMT)
which gives date “lundi 19 décembre 2016 à 15:22:38

If I apply to my late example with 1471788852197 I get :
date “dimanche 21 août 2016 à 14:22:38
but I can’t get time to GMT applying to this date, I just have the current value : 1 hour so
date "dimanche 21 août 2016 à 14:22:38" + (date to GMT) → date “dimanche 21 août 2016 à 15:22:38
while ASObjC gives the correct value - date “dimanche 21 août 2016 à 16:22:38” - the one according to the fact that 21 août is in summer hour (with an offset of 2 hours)

My point of view is that choosing the used scheme is crucial.
If the other date values used by the asker are built by ‘old fashioned’ AppleScript, the correct choice would be to use the same ‘old fashionned’ AppleScript to decipher the Xml datas.
If the other dates used by the asker are built by ASObjC code, the correct choice would be to use ASObjC code to decipher the Xml datas.
It’s only if the dates extracted from Xml datas aren’t used with other dates that the user may freely choose the scheme.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mardi 20 décembre 2016 14:44:28

date to GMT returns always the current difference to GMT/UTC, while Cocoa uses the powerful (NS)Calendar class under the hood considering daylight saving status of the affected date.

I just tried setting my time zone to Paris time, and the ASObjC versions give 15:22:38.

Thanks you all for your help: some explanation
I am trying to decode a rather long XML file from an utility for mac which records the phone calls with an android (Samsung7) phone
My phone is set to my current time which is GMT+1
The result for the
1482156852197
gives me
Monday 19 December 2016 14:22:38
While the phone log screen tells me
Monday 19 December 2016 15:14 (no seconds)
I think the
1482156852197
tells the ending time and gives a duration of 8mins and 26 secs

As for the script I only put one
1481955455195
as an example but the file is quite long and I hope to be able to import everything in FIlemaker.
the XML format is

<?xml version="1.0" encoding="utf-8" ?> +212386801 1482156852197 506 1 and it ends with and include all the data for the calls Thanks again for the help Danwan

The script calculate two dates.
I added an instruction which displays both.

After this change I got :

[format]{date “lundi 19 décembre 2016 à 15:14:12”, date “lundi 19 décembre 2016 à 15:22:38”}[/format]

The phone doesn’t take care of the duration value and drops the seconds.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 21 décembre 2016 19:00:03

Thank you Yvan
However I have a small problem still and I don’t know how to solve
the file complete XML is quite long and I hope to be able to import everything in FIlemaker.
so each file separated by a Carrige return can be imported as a FILREMAKER record
the XML format is

<?xml version="1.0" encoding="utf-8" ?> +212386801 1482156852197 506 1 and it ends with and include all the data for the calls Thanks again for the help Danwan Online

You need a repeat loop


set xmlPath to (choose file) as text
tell application "System Events"
	set theXMLFile to XML file xmlPath
	set callHistoryRecords to XML element "CallHistoryRecords" of theXMLFile
	repeat with anElement in XML elements of callHistoryRecords
		tell anElement
			set xmlDate to value of XML element "date"
			set xmlDuration to value of XML element "duration"
			
			-- do something with the values
			
		end tell
	end repeat
end tell

Thanks Stephan
however I receveithis error
error “The variable xmlPath is not defined.” number -2753 from “xmlPath”

THanks Yvan
If I removed in Textwrangler the opening “<” and replaced the

with something like
endofcall
would that help at all?

In this case the XML file would become a plain text file … but of course is only a silly guess

Thanks again

Of course the choose file line is missing. I updated my post

Here is a complete script.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use framework "Foundation"


set xmlPath to (choose file) as text

set theDates to {}
tell application "System Events"
	set theXMLFile to XML file xmlPath
	set callHistoryRecords to XML element "CallHistoryRecords" of theXMLFile
	repeat with anElement in XML elements of callHistoryRecords
		tell anElement
			set xmlDate to value of XML element "date"
			set xmlDuration to value of XML element "duration"
			set end of theDates to my decipherDatas(xmlDate, xmlDuration)
		end tell
	end repeat
end tell
set theDates to my concatList:theDates usingString:linefeed

set destFile to ((path to desktop as text) & "theDates_setaDeht.txt")
my writeto(destFile, theDates, «class utf8», false)

#=====

on decipherDatas(xmlDate, xmlDuration)
	set OSversion to (current application's NSProcessInfo's processInfo()'s operatingSystemVersion())
	--> {majorVersion:10, minorVersion:12, patchVersion:1}
	tell OSversion to set OSversion to its minorversion as number
	
	-- create the dates from the timestamp
	set startDate to (current application's NSDate's dateWithTimeIntervalSince1970:(xmlDate / 1000))
	set endDate to startDate's dateByAddingTimeInterval:xmlDuration
	
	-- coerce the dates to AppleScript dates
	if OSversion > 10 then
		set asStartDate to startDate as date
		set asEndDate to endDate as date
	else
		set asStartDate to my makeASDateFrom:startDate
		set asEndDate to my makeASDateFrom:endDate
	end if
	return date string of asStartDate & tab & date string of asEndDate
end decipherDatas

on makeASDateFrom:theNSDate
	set theCalendar to current application's NSCalendar's currentCalendar()
	set comps to theCalendar's componentsInTimeZone:(missing value) fromDate:theNSDate
	tell (current date) to set {theASDate, year, day, its month, day, time} to ¬
		{it, comps's |year|(), 1, comps's |month|(), comps's |day|(), (comps's hour()) * hours + (comps's minute()) * minutes + (comps's |second|())}
	return theASDate
end makeASDateFrom:

#=====

on concatList:theList usingString:d1
	set anArray to current application's NSArray's arrayWithArray:theList
	return (anArray's componentsJoinedByString:d1) as text
end concatList:usingString:

#=====
(*
Handler borrowed to Regulus6633 - http://macscripter.net/viewtopic.php?id=36861
*)
on writeto(targetFile, theData, dataType, apendData)
	-- targetFile is the path to the file you want to write
	-- theData is the data you want in the file.
	-- dataType is the data type of theData and it can be text, list, record etc.
	-- apendData is true to append theData to the end of the current contents of the file or false to overwrite it
	try
		set targetFile to POSIX file (POSIX path of targetFile as text)
		set openFile to open for access targetFile with write permission
		if not apendData then set eof of openFile to 0
		write theData to openFile starting at eof as dataType
		close access openFile
		return true
	on error
		try
			close access targetFile
		end try
		return false
	end try
end writeto

#=====

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 21 décembre 2016 21:26:04

You are right. What really needs to be added is the time to GMT at the date in question, whereas the change I proposed is adding the time to GMT at the time the script is run. In many cases they will probably be the same, but not all.

I don’t think there’s a straight forward way of calculating that, so an ASObjC version should be used.

How may we do the reverse : given an AppleScript date : calculate it’s count of milliseconds since 01/01/1970 ?
I found CFGregorianDateGetAbsoluteTime but it’s described as deprecated.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) jeudi 22 décembre 2016 14:51:32

You can subtract two AppleScript dates and get the difference in seconds, then multiply it with 1000

set referenceDateString to "1/1/1970"
set referenceDate to date referenceDateString

set givenDateInMilliseconds to ((current date) - referenceDate) * 1000

Thanks Stefan
It seems that substracting time to GMT is better.



use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

use framework "Foundation"

set referenceDate to date ("1/1/1")
set year of referenceDate to 1970
set theDate to (current date)
set theDateMinus to theDate - (time to GMT)

set givenDateInMilliseconds to (theDate - referenceDate) * 1000
set givenDateInMillisecondsMinus to (theDateMinus - referenceDate) * 1000

# Now use ASObjC to rebuild the ASdates
-- create the dates from the timestamp
set theNSDate to (current application's NSDate's dateWithTimeIntervalSince1970:(givenDateInMilliseconds / 1000))
set theNSDateMinus to (current application's NSDate's dateWithTimeIntervalSince1970:(givenDateInMillisecondsMinus / 1000))

-- coerce the dates to AppleScript dates
set OSversion to (system attribute "sys2") # system attribute belongs to Standard Additions
if OSversion > 10 then
	set ASDate to theNSDateMinus as date
	set ASDateTooMuch to theNSDate as date
else
	set ASDate to my makeASDateFrom:theNSDateMinus
	set ASDateTooMuch to my makeASDateFrom:theNSDate
end if

{theDate:theDate, ASDate:ASDate, ASDateTooMuch:ASDateTooMuch}
--> {theDate:date "jeudi 22 décembre 2016 à 16:05:04", ASDate:date "jeudi 22 décembre 2016 à 16:05:04", ASDateTooMuch:date "jeudi 22 décembre 2016 à 17:05:04"}

on makeASDateFrom:theNSDate
	set theCalendar to current application's NSCalendar's currentCalendar()
	set comps to theCalendar's componentsInTimeZone:(missing value) fromDate:theNSDate
	tell (current date) to set {theASDate, year, day, its month, day, time} to ¬
		{it, comps's |year|(), 1, comps's |month|(), comps's |day|(), (comps's hour()) * hours + (comps's minute()) * minutes + (comps's |second|())}
	return theASDate
end makeASDateFrom:

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) jeudi 22 décembre 2016 16:06:11

But you still face the same problem: you need to subtract time to GMT for the date in question, which may not be the same as time to GMT when the script is run.