UNix date and time conversion

Hi
I have a file collecting my callhistory as XML it read as follows

<?xml version="1.0" encoding="utf-8" ?> +212386801 1482156852197 506 1 </CallHistoryRecord

Is there a way to select the xml file with prompt as the inpuit file
then convert
1482156852197
to whatever it means as Day/Month/Year or some other format
and
30
to Time

and save the result to a destination file

Thanks

I was not sure of the starting date. According to StefanK’s message here I use 1970/01/01 which is the one used internally by Numbers but I guess that you may get the conversion with something like :

set fakeDateString to "12/12/12"
set theDate to date fakeDateString
set day of theDate to 1
set month of theDate to 1
set year of theDate to 1970
# Now we have the starting date in the format in use on the machine
set numericDate to "1482156852197" as number # it's the count of (seconds/100) since the starting date
set theDate to theDate + (numericDate / 1000)

set theDuration to "506" as integer
set theDate to theDate + theDuration
--> date "lundi 19 décembre 2016 à 14:22:38"

For those trying to run the fine StefanK’s answer, take care that two characters are missing at the end of the sample dataset posted by danwan. We must add “s>”

With the corrected data set, StefanK’s code returns : date “lundi 19 décembre 2016 à 15:22:38”

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) lundi 19 décembre 2016 21:54:46

Hi,

the date value is a UNIX timestamp, the interval since 1970 in milliseconds, to get seconds you have to divide the value by 1000.

To parse the XML use System Events, the easiest way to create the dates is AppleScriptObjC

use AppleScript version "2.5" -- El Capitan (10.11) or later
use scripting additions

use framework "Foundation"

set xmlPath to (choose file) as text
tell application "System Events"
	set theXMLFile to XML file xmlPath
	tell XML element "callhistory" of XML element "CallHistoryRecords" of theXMLFile
		set xmlDate to value of XML element "date"
		set xmlDuration to value of XML element "duration"
	end tell
end tell

-- 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
set asStartDate to startDate as date
set asEndDate to endDate as date

Edit:

I was wrong to suggest AppleScriptObjC as the easiest way to create the dates. AppleScript can do it as well

set xmlPath to (choose file) as text
tell application "System Events"
	set theXMLFile to XML file xmlPath
	tell XML element "callhistory" of XML element "CallHistoryRecords" of theXMLFile
		set xmlDate to value of XML element "date"
		set xmlDuration to value of XML element "duration"
	end tell
end tell

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

Those coercions require at least macOS 10.11. Otherwise you need something like:

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:

There is even a pure AppleScript solution.
I updated my post.

Thanks both of you.

Here, the ASObjC path returns date “lundi 19 décembre 2016 à 15:22:38”

The old fashioned AppleScript path returns date “lundi 19 décembre 2016 à 14:22:38”

I really don’t know which is the best one.

Thanks to StefanK and Shane STANLEY, below is an ASObjC version able to apply since 10.10

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

use framework "Foundation"

set xmlPath to (choose file) as text
set OSversion to (system attribute "sys2") # system attribute belongs to Standard Additions
tell application "System Events"
	set theXMLFile to XML file xmlPath
	tell XML element "callhistory" of XML element "CallHistoryRecords" of theXMLFile
		set xmlDate to value of XML element "date"
		set xmlDuration to value of XML element "duration"
	end tell
end tell

-- 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

{asStartDate, asEndDate} # ADDED on 2016/12/21

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:

Edited the way to get OSversion

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mardi 20 décembre 2016 08:37:23

Yvan, both dates are actually the same.

“ AppleScript returns UTC
“ The ASOC-AS coercion seems to pass a date formatter which considers your local time zone (UTC+1 in Central Europe).

Alas, this is a bit of a Catch-22 – the conversion of NSOperatingSystemVersion from a struct to a record also requires 10.11 or later.

Don’t worry Shane
I will edit the script to use use (system attribute “sys2”)

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

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