Applescript, iTunes, and 'date' - perl

I've got an applescript that I call for a song to set the play count and another to set the last played date. These are called from a perl script fetching data from last.fm. Unfortunately, whenever I call the last played date script, I get an error message setItunesLastPlayed.scpt: execution error: iTunes got an error: A descriptor type mismatch occurred. (-10001).
I'm calling it like this:
osascript /Users/gms8994/setItunesLastPlayed.scpt "<ARTIST>" "<TITLE>" "Wednesday, July 05, 2011 07:14:11 AM"
I did notice that if I request the value of the last play from itunes, it comes back without zero-padding days and hours, so I tried removing those, to no avail.
Here's my script.
on run argv
tell application "iTunes"
set theArtist to (item 1 of argv)
set theTitle to (item 2 of argv)
set theLastPlay to (item 3 of argv)
set theLastPlay to date theLastPlay
set results to (every file track of playlist "Library" whose artist contains theArtist and name contains theTitle)
repeat with t in results
tell t
say theLastPlay
set played date of t to theLastPlay
end tell
end repeat
end tell
end run
Can anyone point me to the fix?

The played date property of a track requires a date object, not just the date string. You will need to convert your date into a date object:
set newDate to (current date)
set month of newDate to "July"
set year of newDate to "2011"
(* You can fill in the rest *)
set played date of t to newDate
I don't think there is a way to directly create a date object from a given string, so you'll have to maintain a function to do that for you in case last.fm (or the technology they rely to store and report back dates) decides to change their date format.

Related

How to set up only time in date-fns and still keep the timezone in javascript

I currently have the following use case:
User receives a date in UTC from the backend
This date is transformed into local time for displaying purposes
The date is displayed in different inputs. One input for date and other for time
User can select time independently
The date should be sent back to the backend in UTC format as well
I'm not very experienced with time zones and I'm getting beaten by trying to allow the user to set up only the time (or date) in a datetime field.
My pseudo code is the following:
When receiving the from backend simply convert the date to show it to the user, making the orignal date stay in UTC
When the user picks the hour and minute (all in one action) use setHours and setMinutes from date-fns library
Use native toISOString() to set in models
Code so far [playground]:
import { utcToZonedTime, format } from "date-fns-tz";
import { setHours, setMinutes } from "date-fns";
const UTCStringdate = "2022-04-06T10:00:00.000000Z";
const userTimezone = "Asia/Bangkok";
const localizedTime = utcToZonedTime(UTCStringdate, userTimezone);
// Prints the correct information
// 10:00 in UTC is equal to 17:00 in Bangkok
console.log(format(localizedTime, "HH:mm"));
// Now I expext to set only the `minutes` and `hours`
// to this `localizedTime` so that I can update the backend
const [hours, minutes] = "10:30".split(":");
// Somewhere over here the `setHours` and `setMinutes`
// is turning the Date object into my own timezone
// and not using `Asia/Bangkok` timezone anymore
let newTime = setHours(localizedTime, hours);
newTime = setMinutes(newTime, minutes);
// Now I expect to print 17:30 since we only
// set up 30 minutes forward than the original one
// but it ends up printing 10:30
console.log(format(newTime, 'HH:mm'));
I understand that somewhere along the way (most likely in setHours and setMinutes) the date-fns library turns back the localizedTime back into my own timezone, completely ruining the idea of turning the Asia/Bangkok time into UTC.
Questions
First, is this the best approach to manipulate only the time part of a date when considering timezones? If not, anyone can point me to articles? I wasn't able to find anything on the topic
Second, how can I use setHours and setMinutes and still maintain the timezone?
There are no multiple time zones in JavaScript. There is UTC and there is your local one. What date-fns-tz does, is adjusting the time to the chosen user time zone. In your example, you can see this when printing both the original and the localized time
const utcTime = new Date(UTCStringdate);
console.log(utcTime.toISOString()); // -> 2022-04-06T10:00:00.000Z
console.log(localizedTime.toISOString()); // -> 2022-04-06T14:00:00.000Z
To solve your issue, convert UTC time to users time and let the user to adjust hours and minutes in his local time zone. After that, convert the time object back to UTC using zonedTimeToUtc
newTime = zonedTimeToUtc(newTime, userTimezone);
and then use newTime.toISOString() to send it back to the server.
console.log(newTime.toISOString());

Same Date stamp not equal in swift?

EDIT: thanks to Alexander - Reinstate Monica. See the link in the comments for more info.
I ran into something odd today. I'm using firebase storage for an app and I want to compare the date of the file on the server with the one stored locally which I have manually set the attributes for when creating the file. If the dates are different then the app will re-load the file from the server like so:
if localModDate != serverModDate {
//re-download file
}
most of the time this works correctly, but sometimes the if statement get triggered even though the dates match (checked via print statements) and if I convert the stamps to strings then the dates always match correctly:
if String(describing: localModDate) != String(describing: serverModDate) {
//re-download file
}
my guess is that swift is converting to epoch time (I tested this and the epoch times are indeed off in like the 6th decimal place). Is this correct or is there something else going on here?
Date is just a TimeInterval (which is a typealias for Double) of elapsed seconds since the "reference date" (Jan 1 2001). The == operator just compares those two Doubles, so it's subject to the same floating point precision issues of regular Doubles.
Use Calendar.isDate(_:equalTo:toGranularity:) to check if the dates are "close enough":
if Calendar.current.isDate(localModDate, equalTo: serverModDate, toGranularity: .second) {
...
}

How do I "add" time to firebase timestamp in Swift?

This question is best stated in an example:
It is currently 9:00am. User wants to do activity at 4:00pm the following day. They use UIDatePicker to select 4:00pm the next day, and then hit a button. I know firebase does times in milliseconds from 1970, so what I want to do is "add" the number of milliseconds from 9:00am to 4:00pm the following day to the ServerValue.timestamp(), like so:
activitiesRef.child(newActivity.id).setValue([
"id": newActivity.id,
"name": newActivity.name,
"isActive": newActivity.isActive,
"locString": newActivity.locationString,
"locLat": newActivity.locLat,
"locLong": newActivity.locLong,
"privacySetting": newActivity.privacySetting,
"targetTime": ServerValue.timestamp()]) // + some added value of time
//"targetTime": [".sv": "timestamp"]])
The reason for this is because I will be displaying a countdown timer elsewhere in the app until it reaches the targetTime. If I can push to firebase the targetTime, then the countdown timer will be a simple comparison of the current time on the user's phone to the targetTime itself.
The error I keep getting when trying to add a double value to the ServerValue.timestamp() is "Contextual type 'Any' cannot be used with dictionary literal"
If it is not possible to do so, what other options do I have? Thank you.
ServerValue.timestamp() is not a number that you can use to perform date arithmetic. It's a special placeholder value that the server side interprets with its sense of time.
The best you can do is write the timestamp, read it back out as a number, then perform math on it.

How do I reset a variable at the start of each day?

I have a variable that keeps track of user statistic I want to reset at the beginning of each day. How can I do that?
Since the application is not allowed to run in the background, it seems I will have to do the check every time the application is active but I don't know how to reset the variable I have only once. This is the function I wanted to use:
let beginingOfDay = NSCalendar.currentCalendar().startOfDayForDate(NSDate())
func resetCurrentTime(){
// Date comparision to compare current date and begining of the day.
let dateComparisionResult:NSComparisonResult = NSDate().compare(beginingOfDay)
if dateComparisionResult == NSComparisonResult.OrderedDescending || dateComparisionResult == NSComparisonResult.OrderedSame {
// Current date is greater or equal to end date.
currentTime = 0 //reset the time tracker
}
}
I wanted to use this function to check when the application is launched but the problem is that the application could be launched many time a day. How I can reset my variable only once at the beginning of a day if the user is using the application or when the application becomes active or is launched for the first time that day?
Thanks
You can store in the user defaults this value.
So the flow is the following:
When the app is launched or became active you check whether the value of the variable in the user defaults is the same as the current day (e.g. 25/07/2016), then do nothing.
If the value is different, then you update the value in the user defaults with the current day.
If the app is running and the date is changed, you can update the value of your variable by subscribing to this notification:
UIApplicationSignificantTimeChangeNotification

Is there a class in JDK to represent an hour of the day, but not necessarily a specific hour at a specific date?

Is there a class in JDK or Guava to represent an hour of the day, but not necessarily a specific hour at a specific date?
If not, why?
In JDK 1.3-1.7, the answer is no. A specific time within a day is much easier to calculate then date, because you don't have to deal with leap year, leap month, such headache stuff. A simple integer is just enough. When you need to convert the time to a locale string, using SimpleDateFormatter or whatever, you can simply convert the time to a Date, just ignore the date part:
int time = 8 * 60 + 34; // 8:34 am
Date date = new Date(60000L * time);
Reset the time zone to +0, and pass the date to the formatter:
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT+0"));
sdf.format(date);
You could simply wrap a byte into a class and every time that the current hour passes 23 within your increment() (or appropriate name) method, set the value of the byte to 0, and whenever the value passes below 0 in your decrement() (or appropriate name) method, set the value of the byte to 23.
As far as I know, there is not a specific class representing Hour (in the JDK or Guava), but there are easy to use classes to fetch the hours from a specific instance of time (which is what I am assuming you are after with this question).
You could use JODA-Time, as PaĆ­lo Ebermann mentions, but that is an external library. Within the JDK, there is a class called Calendar, which has many useful methods.
To get the hour of a long representing the current time, you could do this:
Calendar c = Calendar.getInstance();
c.setTimeInMillis(System.currentTimeMillis());
int hour = c.get(Calendar.HOUR); //returns 0-11
int hourOfDay = c.get(Calendar.HOUR_OF_DAY); //returns 0-23