(current date) formatting problem

I am trying to extract the hours and minutes from the date string. How can I get the hours and minutes in a fixed 2 character military format with out a lot of conditional parsing?
For example:


set merged_time to characters 1 through 2 of time string of (current date) & characters 4 through 5 of time string of (current date)

This works only from 1000-1259 and is incorrect from 2200-2359 (i.e. uses 1000-1259 again). TIA.

A date’s ‘time string’ is formatted according to your user preferences and may not necessarily be in the form you need for your script. Use the date’s ‘time’ instead, which gives the number of seconds since midnight. From this, it’s very fast and easy to extract the hours and minutes and to deal with any necessary leading zeros.

set t to time of (current date)
set hr to t div hours
set min to t mod hours div minutes
set merged_time to text 2 thru 5 of ((10000 + hr * 100 + min) as string)

Thanks. Its more involved then a single statement but not as bad as I had feared.

You don’t get much done with a single statement in AppleScript. :slight_smile: In this case, I spread the code over four lines to give you some idea of what was going on, but if you wanted it as a single line:

tell time of (current date) to set merged_time to text 2 thru 5 of ((10000 + it div hours * 100 + it mod hours div minutes) as string)

There may be some shell script that involves less writing, but it’ll undoubtedly take longer to execute.

How about :

set mil_time to do shell script “date +%H:%M”

Andy

Thanks, Andy. That’s certainly shorter! :wink: And, as I predicted, it takes about twenty times as long to execute.

set lotsa to 500

set t to GetMilliSec -- requires the GetMilliSec OSAX
repeat lotsa times
  tell time of (current date) to set merged_time to text 2 thru 5 of ((10000 + it div hours * 100 + it mod hours div minutes) as string)
end repeat
set vanillaTime to ((GetMilliSec) - t) / 1000

set t to GetMilliSec
repeat lotsa times
  set mil_time to do shell script "date +%H%M"
end repeat
set shellTime to ((GetMilliSec) - t) / 1000

{vanillaTime, shellTime, shellTime / vanillaTime}
--> {0.46, 9.557, 20.776086956522} -- timed on a G3 PowerBoook

My own conclusion about shell scripts is that they’re appropriate when (in order of preference):

  1. There is no other way to achieve a task.
  2. A task can be carried out much faster than with a scripted application such as the Finder or System Events.
  3. The scripter is in a hurry and is more familiar with Unix or Perl than with AppleScript.

I agree that using vanilla AS is faster than using a “do shell script” but, if you are only really doing this once, the time is negligible and so the easier shell script wins for me. Here are my results from a PB G4 1.25MHz:

Jon


[This script was automatically tagged for color coded syntax by Script to Markup Code]

Thanks for all the replies but you folks are going way beyond my beginner status. Nigel’s first suggestion works and that is good enough for me at this point. My comment about a single line was mostly tongue-in-cheek as I was looking at parsing out the hour and minute and AM/PM then setting the hour number appropriately. That is way more then the few lines Nigel suggested.

As an aside but related, is there an easy way to also convert the month to a number string? Right now I have 12 if/else statements comparing the month strings then setting the appropriate 2 digit number string.

Say it took me 5 minutes to come up with the vanilla solution and 1 minute for the shell script (which is about right), I’d have to run the script with the shell script code nearly 14,000 times before I made up the 4 minutes I lost coding the vanilla script:

Jon


[This script was automatically tagged for color coded syntax by Script to Markup Code]

If you substitute month constants for month strings, that is actually quite a fast way - especially with a January date. Understandably, though, the method’s not popular. :wink: The classic “fast month number” method was invented by Emmanuel Lévy and was later dubbed “French Vanilla”. The latest incarnation of it is by me and is wittily called “English Fudge”:

set theDate to (current date)

-- Get the month number for theDate
copy theDate to b
set b's month to January
set monthNum to (b - 2500000 - theDate) div -2500000

If you’d spent 5 minutes coming up with the vanilla solution, running the shell script code then 14,000 times would seem a rather perverse thing to do. You could run the vanilla code you’d invented roughly 280,000 times during the same period. :wink:

Of course, the slow solution is:

set the_month to do shell script “date +%m”

I am curious, what part of the ‘do shell script’ creates the delay? At the terminal, running ‘date’ is about a billion times faster then calling an applescript via ‘osascript.’

Andy

I’m not sure. ‘do shell script’ is one of the StandardAdditions commands, so invoking it shouldn’t take any longer than invoking ‘current date’, which the vanilla scripts above use. I’d also expect the actual Unix stuff to take virtually no time at all, so I imagine the delay’s somewhere between the OSAX and Unix - perhaps in the passing and parsing of the parameters.

Reading this again, I see that gw1500se was actually after a two-digit string. By the vanilla method, this might be:

set theDate to (current date)

-- Get the month number for theDate as a two-digit string
copy theDate to b
set b's month to January
set monthNum to text 2 thru 3 of (((b - 252500000 - theDate) div -2500000) as string)

In practice, though, you’d probably want similar figures for the day and year at the same time, so you could combine them like this:

set theDate to (current date)

copy theDate to b
set b's month to January

-- Get an eight-digit number string in yyyymmdd format and extract what you need
tell ((theDate's year) * 10000 + (b - 2500000 - theDate) div -2500000 * 100 + (theDate's day)) as string
  set shortDate to text 5 thru 6 & "/" & text 7 thru 8 & "/" & text 3 thru 4 -- US format
end tell

OK. I admit it. I enjoy this stuff. :wink:

For those who aren’t familiar with Nigel’s scripting talents, you should know that he takes GREAT pleasure in the process of optimizing code. I am of the firm belief that were he charged with the task of milking a cow that held only one gallon of milk, he could convince her to surrender two gallons of milk without even touching her. :wink:

– Rob

Hi :slight_smile:

WOHOUW !!! That is the best date routine, BRAVO !!! :smiley: :smiley: :smiley:

You can… you can !!! :wink:

I get this error:

date: illegal time format
usage: date [-nu] [-r seconds] [+format]
       date [[[[[cc]yy]mm]dd]hh]mm[.ss] (1)

when using the following:

set theIODateTime to do shell script "date +%Y-%d-%m  %T"

The command works in the terminal, however, in the terminal the first quote is AFTER the “+” sign. The sample code earlier in this thread have the first quote BEFORE the the word “date”

I want to format the date as: yyyy-dd-mm hh:mm:ss

What am I doing wrong?

Thanks,
Brad Bumgarner, CTA

Since you have a space in your string, you need to quote it:

Jon


[This script was automatically tagged for color coded syntax by Script to Markup Code]

I KNEW it was something simple. For some reason, I kept trying to use double-quotes within double-quotes. As a graphics artist/typesetter (for over 20 years) you would THINK I would have figured that out for myself. :frowning: Oh well, it MUST be a Friday.

Thanks,
Brad Bumgarner, CTA

Another option would be to use the ‘quoted form’, within the do shell script command…

set theIODateTime to do shell script "date " & quoted form of "+%Y-%d-%m %T"
-->2003-17-10 14:50:16

Just out of interest, are these date shell scripts any good for dates other than the system date at the time they’re run?

Escape the embedded double quotes with the backslash ‘’ to get them properly sent to the shell.



do shell script "date "+%Y-%d-%m %T""


Andy