Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

how do I get ampm format for time?

 [1/19] from: bobr::dprc::net at: 19-Jan-2001 1:51


how do I format dates to am/pm format like: "hh:mm pm EST" is there a more succinct way to write this? time-ampm: func [ dt ] [ rejoin [ ; handle hh:mm part ( replace ( copy/part ( rejoin [ (either dt/time < 10:00 [ "0" ] [ "" ]) ; hh:mm vs [h]h:mm either dt/time > 12:59:59 [ mold dt/time - 12:00 ] [ mold dt/time ] ] ) 5 ) "00:" "12:" ) ; midnite-1am is special ; handle " pm EST" parts either dt/time > 11:59:59 [ " pm" ] [ " am" ] EST ]] yes this does the job, perhaps a mold could be factored out and some parens are not needed. now the challenge is to write something that handles the exceptions with less code. this version allows coding by deletion since the two parts hh:mm vs am/pm indicator are treated separately and simply concatenated.

 [2/19] from: carl:cybercraft at: 19-Jan-2001 22:08


Hi Bob, You can extract hours, minutes and seconds from a time value...
>> a-time: 17:40
== 17:40
>> a-time/hour
== 17
>> a-time/minute
== 40 which can make things simplier. So... am-pm: func [time] [ ap: to-string time hour: time/hour either hour < 12 [ap: join ap "AM"][ap: join ap "PM"] if hour > 12 [replace ap to-string hour to-string (hour - 12)] if hour = 0 [replace ap to-string hour to-string 12] return ap ] This seems to work, though I'm sure others can improve on it. On 19-Jan-01, Bob Racko wrote:
> how do I format dates to am/pm format > like: "hh:mm pm EST"
<<quoted lines omitted: 22>>
> since the two parts hh:mm vs am/pm indicator > are treated separately and simply concatenated.
-- Carl Read [carl--cybercraft--co--nz]

 [3/19] from: gjones05:mail:orion at: 19-Jan-2001 4:52


Rebol/Core User's Guide (page 63) also gives the following example: print either now/time < 12:00 ["AM"]["PM"] This approach could be easily adapted to: time-ampm: func [dt] [either dt < 12:00 [return join dt "AM"][return join dt - 12:00 "PM"]]
>> time-ampm 8:00
== "8:00AM"
>> time-ampm 18:00
== "6:00PM" Hope this is helpful. Scott

 [4/19] from: rchristiansen:pop:isdfa:sei-it at: 19-Jan-2001 10:57


This function should accomplish what you're looking for. time-meridian: func [ time-data [time!] ][ either time-data/hour < 12 [ meridian-time: rejoin [time-data/hour ":" time-data/minute " a.m. EST"] ][ meridian-time: rejoin [time-data/hour ":" time-data/minute " p.m. EST"] ] ] USAGE:
>> time-meridian now/time
== "10:57 a.m. EST" -Ryan

 [5/19] from: bo:rebol at: 19-Jan-2001 9:52


I based this off what Scott submitted but reduced it a bit: time-ampm: func [dt][join dt // 12:00 [pick "AP" dt < 12:00 "M"]] It shows an alternate method of tackling this problem using a few REBOL tricks. Anybody have a shorter version? I'm sure there is one out there... -Bo On 19-Jan-2001/4:52:34-6:00, [gjones05--mail--orion--org] wrote:
>"Rebol/Core User's Guide" (page 63) also gives the following example: >print either now/time < 12:00 ["AM"]["PM"]
<<quoted lines omitted: 57>>
>[rebol-request--rebol--com] with "unsubscribe" in the >subject, without the quotes.
-- Bohdan "Bo" Lechnowsky REBOL Adventure Guide REBOL Technologies 707-467-8000 (http://www.rebol.com) The Official Source for REBOL Books (http://www.REBOLpress.com)

 [6/19] from: bo:rebol at: 19-Jan-2001 10:02


Before anyone else pipes in, I just realized I used a few extra characters. If I'm gonna try to do this succinctly, I might as well go all out, eh? ;-) time-ampm: func[dt][join dt // 12:0[pick"AP"dt < 12:0"M"]] I don't recommend doing this for readability's sake, but it does show the smartness of the language parser. And I did challenge someone to make it shorter... -Bo On 19-Jan-2001/4:52:34-6:00, [gjones05--mail--orion--org] wrote:
>"Rebol/Core User's Guide" (page 63) also gives the following example: >print either now/time < 12:00 ["AM"]["PM"]
<<quoted lines omitted: 57>>
>[rebol-request--rebol--com] with "unsubscribe" in the >subject, without the quotes.
-- Bohdan "Bo" Lechnowsky REBOL Adventure Guide REBOL Technologies 707-467-8000 (http://www.rebol.com) The Official Source for REBOL Books (http://www.REBOLpress.com)

 [7/19] from: doug:vos:eds at: 19-Jan-2001 13:17


saves 8 characters from your version :) ampm: func[t][join t // 12:0[pick"AP"t < 12:0"M"]]

 [8/19] from: jeff:rebol at: 19-Jan-2001 11:39


Howdy, Bo:
> Before anyone else pipes in, I just realized I used a few > extra characters. If I'm gonna try to do this succinctly,
<<quoted lines omitted: 4>>
> challenge someone to make it shorter... > -Bo
Sweet and short, but it gives unusual results around noon and midnight:
>> time-ampm 12:00
== "0:00PM"
>> time-ampm 24:00
== "0:00PM"
>> time-ampm :59
== "0:59AM"
>> time-ampm 12:59
== "0:59PM It would be nice to be able to distinguish 12:00 AM from 12:00 PM and to have the typical digital clock format which includes the hour 12-- so, a bit longer but well behaved around lunch and the witching hour: time-ampm: func [dt [time!] /dd/merid][ merid: pick [PM AM] found? all [24:0 > dt dt >= 12:0 ] reduce [(dd: dt // 12:0) + pick [12:0 0] 1:0 > dd merid] ]
>> time-ampm 12:0
== [12:00 PM]
>> time-ampm 24:0
== [12:00 AM]
>> time-ampm 12:59
== [12:59 PM]
>> time-ampm :59
== [12:59 AM] -jeff

 [9/19] from: rphilipp:suffolk:lib:ny:us at: 19-Jan-2001 17:50


Hi Group, This may not be as concise but how about this script: REBOL [ ] what-time?: does [ either now/time < 12:00:00 [join now/time " AM"] [ join (now/time - 12:00:00) " PM"] ] usage:
>> what-time?
== "5:47:10 PM"

 [10/19] from: bo:rebol at: 19-Jan-2001 16:34


Classic case of forgetting to test boundary cases... Oops! -Bo On 19-Jan-2001/11:39:01-8:00, [jeff--rebol--net] wrote:
> Howdy, Bo: > [...] > Sweet and short, but it gives unusual results around noon and > midnight: > [...] > -jeff
-- Bohdan "Bo" Lechnowsky REBOL Adventure Guide REBOL Technologies 707-467-8000 (http://www.rebol.com) The Official Source for REBOL Books (http://www.REBOLpress.com)

 [11/19] from: gjones05:mail:orion at: 19-Jan-2001 18:57


Hi, Jeff, Bo, et al Sorry to beat a dead horse, but as Larry Wall has said, there's more than one way to do things (and apologies to Bertrand Meyer ;-). Jeff and others politely pointed out my programming-logic gaff from early this morning. However, being a REBOL newbie, I have really enjoyed seeing all the ways to tackle the problem (great way to learn the tricks of the language). I would normally be more than satisfied with Jeff's solution: time-ampm: func [dt [time!] /dd/merid][ merid: pick [PM AM] found? all [24:0 > dt dt >= 12:0 ] reduce [(dd: dt // 12:0) + pick [12:0 0] 1:0 > dd merid] ] but I was bothered that I couldn't get the logic to be correct using few tricks without the code seeming to grow exponentially in comparison to Jeff's, with his neat tricks. I mulled on it this evening and came up with: time-ampm-mine: func [dt [time!]] [ either dt >= 12:0 [ join (either dt < 13:0 [dt] [dt - 12:0]) "PM" ][ join (either dt < 1:0 [dt + 12:0] [dt]) "AM"] ] It seems to work at all the "boundary" cases, but please yell if I overlooked something. Being curious as to the affect that the differences in sources would have on execution time, I set up a loop to iterate the functions 1 million times and measured times. On my 500 mhz (de)Celeron, my function averaged 22 to 23 seconds, and Jeff's averaged 38 to 40 seconds. I still prefer Jeff's because of the "beauty" of the tricks used. As always, this information and 35 cents may buy you a phone call. Cheers, Scott

 [12/19] from: bobr:dprc at: 20-Jan-2001 14:46


At 06:57 PM 1/19/01 -0600, GS Jones wrote:
>Hi, Jeff, Bo, et al > >It seems to work at all the "boundary" cases, but please yell if I >overlooked something.
nearly everyone missed something. shall I grade all of us on a curve? #1) I consider that most of you overlooked a biggie. Succinct was chosen as a precise word. It doesn't only mean small or fast or unreadable. (smile) It particularly doesn't mean "change the spec". It doesn't matter how fast you make it if I must insert an intermediate function to convert what you wrote into what would function as a drop-in replacement. You would have to benchmark the intermediate too. I used the word named 'dt (vs tm) as an argument in my example for a reason. I also did not restrict the argument type for a reason. I was passing date!s (not time!s) into it. Specifically I was passing structures that would have a /time path or refinement to them. These were not just time paths to things I made up, they had to work with standard rebol return values that had a /time refinement. In some cases I made a /local dt and copied your argument to the local as in myampm: func [ adt /local dt ] [ dt: adt/time ... <your code here> ] in order to avoid the intermediate function call overhead. Here are test cases derived from actual working sections of the code where the function is used. time-ampm modified? %user.r time-ampm ( oo: make object! [ time: now ] ) time-ampm now #2) most of you did not get the fact that the result was to be fixed width (zero padded on the left) -- the clue was in the comment ; hh:mm vs [h]h:mm This one turned out to be less important as the system I was trying to mimic [remember my reason for starting the "How do I thread(s)" ??? ] said fixed width in the spec but in implementation [reality] was variable width and not 0 padded! this one has a boundary case which wrecks even my own code. time-ampm 20-Jan-2001/18:57:53 #3) what about being able to get only what you are interested in?
>this version allows coding by deletion >since the two parts ...
However, This part of the challenge seems to have been ignored. In the area of potential refinements, I saw very little in the replies that could be easily tweaked return the two separate values (AM PM vs 12 hrfmt). I guess it was the excitement of the hunt. so here you also have a lesson in "coupling and cohesion". RT is to be congratulated in the cohesion of the base date!time! refinements. I will let you each decide how badly you sacrificed coupling in the interest of beating a benchmark. ____________________ Overall, I appreciate the effort and thanks for your participation. Most of you figured out that there was little I stood to gain by putting up my challenge if my own code worked adequately already. Indeed, I was also trying to make the community (not just RT) aware of practical and potential extensions (see http://rebol.com/contribution_source.html ) or alternatively, refinements to the base time!date! types involved. (see refinements below) Being the stickler for orthogonality I am, I noted that REBOL can accept 12hour format but is not so good at emitting it (or allowing the programmer to). print 20-Jan-2001/08:57PM By pointing out so many different ways one can make mistakes at the boundaries in emitting it and getting you to come up with a concise function that does it all, I make it attractive to be standardized or codified. If any of you want to resubmit a better and more concise solution (read succinct) that RT can consider for a to-ampm (like to-idate) with refinements that allow selective inclusion/exclusion of the parts then lets hear it! In the meantime, what if it were just a simple part of the datatypes involved? As I have watched Rebol evolve, being able to get [at] only what you are interested in is a characteristic of the base type support in the language. --proposed refinements-- Date Refinements: /year -- Returns the year only. /month -- Returns the month only. /day -- Returns the day of the month only. /time -- Returns the time only. /zone -- Returns the time zone offset from GMT only. /date -- Returns date only. /weekday -- Returns day of the week as integer (Sunday is day 7). /inampm -- time portion as [h]h:mm:ss[A|P]M, variable width hh, first hour is 12 not 0 can be combined with /time to return time only portion Time Refinements: /hour -- (stet) /minute -- (stet) /second -- (stet) /ampm -- ante meridiem, returns "AM" or "PM" /in12hr -- [h]h:mm:ss, variable width hh, first hour is 12 not 0 example: { ftim: modified? %/databse/srcobjs print ftim/inampm print now/inampm }

 [13/19] from: jeff:rebol at: 20-Jan-2001 12:40


Howdy, Senator Racko:
> #1) I consider that most of you overlooked a biggie.
Likewise: Some of us (me) had no idea this was intended as a Programming Challenge (way too busy to read the whole thread), and was only paying attention when they noticed a bug in some posted code. I just get a little edgy when people start extrapolating from some code I banged out and posted to the list into a large scale assessments of my work, or the company I work for. :) Of course, it's best to always post code that you think is well polished, as a representative of your company, but I don't necessarily feel obliged to meet specific requirements of a non-customer especially if I'm not aware of those particular requirements. :-) A suggestion: Threads that are Programming Challenges should put "[PROGRAMMING CHALLENGE]", or something like that, in the subject line so I can avoid accidentally posting in those threads. (-: Muchos gracias, and salud! -jeff

 [14/19] from: carl:cybercraft at: 21-Jan-2001 12:55


On 21-Jan-01, [jeff--rebol--net] wrote:
> Howdy, Senator Racko: >> #1) I consider that most of you overlooked a biggie.
<<quoted lines omitted: 3>>
> thread), and was only paying attention when they noticed a > bug in some posted code.
I'd cut-and-pasted Bob's function and gave it a time to see what it did with it, but it just gave me an error, which I thought may have been due to the cutting-and-pasting, (I miss attachments on this list, as I'm sure others do), so I just assumed that what he wanted was a way to convert times to AM-PM format, (since REBOL /can /do the opposite), as it's not difficult to extract times from dates if that's what's wanted. Oh well. (: -- Carl Read [carl--cybercraft--co--nz]

 [15/19] from: gjones05:mail:orion at: 20-Jan-2001 14:38


Mr. Racko, Clearly you seem to be on a mission of some sort. I'll let that be your business. I just joined this discussion list a couple days ago, and my original submission yesterday morning was in response to an email that seemed to have been an original thread. That message simply asked how one might print in the twelve hour format. In trying to learn this language that is new for me, I was contributing in a way that I thought was respectful to the users of the list service. I was unaware that there had apparently been a pre-existing thread that had begun with your challenge. As such, I personally found your submission today to be offensive. Perhaps I am being overly sensitive. Perhaps I am just plain mistaken. But clearly I will be far more reticent to contribute my two coppers. There is a chance that other newcomers may feel similarly, which would be a shame for both the list, as well as, the language. As for a grade, Mr. Racko, you are welcome to give me a plain "F" with no curve for being both an innocent contributing newcomer and not being omniscent. I believe that my contribution was appropriate to the question being asked in this thread. While your mission may be worthwhile, I question your methods. Now please excuse me while I bow out into the very deep background of this discussion list. With respect, - Scott

 [16/19] from: jeff:rebol at: 21-Jan-2001 8:47


Howdy, Bob Racko: Since we're laying into you now: (-: You do make some good points in your message about date type, (grating and apparently at the expense of others, though well meaning, that they appear). :-) Comments below:
> In some cases I made a /local dt and copied your argument > to the local as in
<<quoted lines omitted: 5>>
> time-ampm modified? %user.r > time-ampm ( oo: make object! [ time: now ] )
(Parens are gratuitous above.) Accepting input like the above really complicates your function because you then have two /time refinements to take before you get to your time! value. You have to have stuff like this: if not time? adt [adt: adt/time while [not time? adt][adt: adt/time]] I don't think functions should go rummaging around too far to find the data they're supposed to operate on.
> time-ampm now
But your function does take time! values, yes? time-ampm: func [adt [time! date! object!][ all [not time? adt adt: adt/time] .. can save yourself a gratuitous local. Type specifiers help prevent things like unset! accidently falling into your function as well.
>#2) most of you did not get the fact that the result was to > be fixed width (zero padded on the left) -- the clue was in > the comment ; hh:mm vs [h]h:mm
FORM and MOLD of time values will strip any leading zeros, and I see in your original post that you are interested in a string result. Text formating, to me, is a whole different question. If your time-ampm function renders your time into a string then you loose the semantic use of the original value and can't use the function in composition with others that might continue to operate on 12hour times.
> In the area of potential refinements, I saw very little in > the replies that could be easily tweaked return the two > separate values (AM PM vs 12 hrfmt). I guess it was the > excitement of the hunt.
Again, I didn't know that was desired, but a slight modification my version could have done that easy enough. Ha ha. time-ampm: func [dt [time! date! object!] /dd/ampm/merid][ all [not time? dt dt: dt/time] ampm: pick [PM AM] found? all [24:0 > dt dt >= 12:0 ] if merid [return ampm] reduce [(dd: dt // 12:0) + pick [12:0 0] 1:0 > dd ampm] ] time-ampm/merid now == AM
> so here you also have a lesson in "coupling and cohesion". > RT is to be congratulated in the cohesion of the base > date!time! refinements. I will let you each decide how > badly you sacrificed coupling in the interest of beating a > benchmark.
I would think that rendering your time values to a string would eradicate the possibility of loose coupling.
> Indeed, I was also trying to make the community (not just > RT) aware of practical and potential extensions (see > http://rebol.com/contribution_source.html )
Yes-- contributions so far have been very minimal.
> or > alternatively, refinements to the base time!date! types
<<quoted lines omitted: 11>>
> (like to-idate) with refinements that allow selective > inclusion/exclusion of the parts then lets hear it!
TO-IDATE is a fudge function there to meet a specific practical need within the protocol handlers-- (likewise CVS-DATE function). I suppose an ampm function would be for useful for similar fudge. So I suppose string output is what you'd have to get.
> In the meantime, what if it were just a simple part of the > datatypes involved?
<<quoted lines omitted: 3>>
> language. > --proposed refinements--
...
> /inampm -- time > portion as [h]h:mm:ss[A|P]M,
<<quoted lines omitted: 6>>
> -- [h]h:mm:ss, variable width hh, first hour is 12 not > 0
I don't know-- do the /ampm refinements permanently side effect the datatype? The issue is one of FORM and MOLD of a date! or time! value, not a question of accessing inner data in the value as the rest of the date/time refinements do. date: now ampm-date: date/ampm ? Doesn't really make sense. The other way to go is a system setting that affects how things like date! and time! values are printed. You see this, for instance, with system/options/binary-base . The larger question of text formating is one we have talked about addressing with a format dialect. Using parse block, it's pretty easy to make little formatting dialects to experiment with. Someone might make a dialect that just handles the many numerous ways to FORM, MOLD and print dates and times. Cheers! -jeff

 [17/19] from: bobr:dprc at: 21-Jan-2001 4:10


At 12:55 PM 1/21/01 +1200, Carl Read wrote:
>I'd cut-and-pasted Bob's function and gave it a time to see what it >did with it, but it just gave me an error, which I thought may have >been due to the cutting-and-pasting,
I tried to go back and paste my sample in as well and got an error. Since I took it from a running example this made me curious. I then discovered that the line interpreter is fussy about needing an unclosed block on the function declaration line and my word processor was helping out a bit too much by moving the next open block down. time-ampm: func [dt] [stuff] gives an error when pasted. time-ampm: func [dt] [ stuff] does not. I understand that this is due to the parser/linescanner presuming an unclosed block means more is coming and the linscanner in this instance does not get a hint that 'func wants another argument.

 [18/19] from: bobr:dprc at: 21-Jan-2001 5:22


At 12:40 PM 1/20/01 -0800, Jeff wrote:
> Howdy, Senator Racko: > > #1) I consider that most of you overlooked a biggie.
<<quoted lines omitted: 3>>
> thread), and was only paying attention when they noticed a > bug in some posted code.
I am grateful for the help. Yes, I see that early on in the thread the conversion happened to time! from the unspecified obj/time form. Looks to me like the olde gossip game (where noise introduced early on gets amplified) happens here too.
> Of course, it's best to always post code that you think is > well polished...
I see now where my own "polishing" may have broken my example!! (smile)
> A suggestion: Threads that are Programming Challenges should > put "[PROGRAMMING CHALLENGE]", or something like that, in > the subject line so I can avoid accidentally posting in > those threads. (-:
EEK! if you stop posting then many of us will not really learn from you. Every thread I post with "How do I" subject is designed to be saved for training others. in fact it seems we are on the anniversary of this thread-prefix ...
>I am activating this thread and others like it >with the same prfix to solve some real problems.
<<quoted lines omitted: 6>>
>in C, squeak, expect, python plus a few more >as I am the custodian of at least 2 other rare languages. ...1/18/00
Though I have to filter a lot of email that comes generally to the list, I keep filters on this prefix wide open and read them all. Sometimes the responses I get back are not appropriate. For several I have injected, there hasn't been much discussion stimulated. For this I blame myself but rather than pester, I have decided to actively-listen. I would rather deal with some crankyness or upset than ask questions on a prefix that nearly guarantees that the people who can make a difference about it will ignore it. They aren't all programming-challenges either since I have plenty of material to cover that deals with issues and conventions for which I believe there is not a pleasant programmable solution. Eye openers for people who design the language and its environment. For this ampm example I was able to start with a program that worked (maybe a bit quirky). I could tell when writing it that I could do better but I was already applying the best series of principles at my disposal. So, with an interest of becoming a better coder myself, I introduced it as a "make my code succinct" thread. Meanwhile something even deeper bothered me -- That there are many ways to incorrectly construct such a simple function. I was counting on the fact that in other areas, RT has put in their own code in subsequent releases to head off common errors before they bite someone. In addition I felt I could get the real advocates (those with time) to think about the deeper problem as a lead-in to an eye opener about refinements to basic types and how they evolve. If I start small with a real-world example I get even better attention. Among the things I was trying to stir up was discussion about how folks (inside or outside RT) decide what is a (possibly contributed) mezzanine function, what goes into a datatype-refinement and what gets left out altogether. That exact decision strategy is one I think others (outside of RT) would like to know so we can more appropriately pitch our suggestions. Of course I could infer one -- and after writing an elaborate paper about it discover that the answer is simply: "oh, Carl decides that! :)" which is only funny up to the point you start thinking about buying more Carl-insurance. Jeff, you have demonstrated great flexibility in adapting and understanding the snips posted which is to your credit. Yours was also the easiest to decouple into separate refinements. I am sorry you are so pressed for time to not be able to go back to the first thread in a series.

 [19/19] from: jeff:rebol at: 21-Jan-2001 10:25


Howdy, Bob:
> Among the things I was trying to stir up was discussion > about how folks (inside or outside RT) decide what is a
<<quoted lines omitted: 8>>
> to the point you start thinking about buying more > Carl-insurance.
Here's my perspective on how it works: For "definitional" questions, mezzanines and natives especially, Carl is always the ultimate authority and guiding light-- his creativity and designs are the first principles of REBOL, of course, as he is REBOL's father. All of the engineering team collaborates, though, pool our ideas, figure out the best way to do different things. We, or various people from around the world point out missing things that REBOL should logically do-- or the way REBOL would do it. Someone says "yeah! It should do that!" We wander into Carl's office, interrupt what he's working on, bring up the issue, discuss it, pull in someone else, argue this and that. Or we write up the design in a REP (REBOL Enhancement Proposal) (and other people have submitted these too), we implement the feature, then we advertise the work, and Carl then signs off or not on the feature's inclusion when release time comes. Carl always surprises us with a much slicker way to fit something in, but we're also always improving in our own understanding of "The REBOL way". Sometimes, Carl leaves it up to the rest of us to investigate and familiarize ourselves with specific problem domains or areas of functionality, determine the goals, how it would best fit into REBOL and then attack the problem. "You'd be the best one to answer that" is his confounding response for these times when you try and get him to spit out the answer to X when you've been wracking your brains on X for a month of sundays. So, in principle, just to give the rest of the team a little credit :-), I'd phrase it like this: "Carl ultimately decides or approves these things, but the rest of us kids help out too."
> I am sorry you are so pressed for time to not be able to go > back to the first thread in a series.
Sorry for being defensive. In the future I'll be sure to go back and read the first posts of "how do I" threads before I answer one (although, a lot other non Racko Training threads also begin with that preamble). (-: -jeff

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted