DateTime is bloomin' complicated!

IanMc

Well-Known Member
Licensed User
Longtime User
DateTime

Ooh, its very complicated.... I think perhaps either it isn't finished or else someone is veering away from the concept of BASIC being a high level language.

You might as well just give us inline assembler and we'll program it ourselves in assembly language :)

Please regard this post as constructive criticism and note that Erel himself has remarked that he sometimes is not aware of difficulties that new users may encounter as attested to by this thread:
http://www.b4x.com/forum/basic4andr...ls/9049-collecting-tips-beginners-wanted.html

The thing I like about BASIC and B4a especially is that I can hold it in my head and that makes it a joy to use.

Now I get the idea with 'ticks' and these are represented in a Long variable, ok so (you don't give us any examples but...) a typical example of this long variable number would be the date and time of writing this text which is:
12:49pm on Sunday the 20th of January 2013
(by the way, if you want to represent a date and time like that be prepared for some serious programming)

So the tick value for the above date and time, heck let's begin to call it DateTime is: 1358686183885
There, that wasn't so hard to give an example now was it?

So here's a quick 'lightning quiz' for you. Using the very friendly B4a BASIC language take that long integer '1358686183885' and turn it back into the format as above:
12:49pm on Sunday the 20th of January 2013
Shouldn't be so hard right? I'm sure BASIC has some nice easy useful functions to do it right?


So then, if you're a mathmatician you can add and subtract numbers to that long integer and if you do
DateTime.Now and get a number like the example above then that big long number represents milliseconds since the 1st of January 1970
(one presumes that was Erel's birthdate :) ) hehe.

But we are given some rather low-level functions to manipulate these massive numbers so that's great then but not very friendly.

Awwww, does ianyweany want some little fluffy basic pink boxes with easy functions cozy nestled inside?
Well Yes, he does :) then he can hold them in his head without having to re-learn everything about DateTime each and every time he needs to use it!

Look what I have to do to get the name of the day or the name of the month

lblMyLabel.Text = "Hello today it is " & .... erm ... oh I give up :( but I need it, search the forum, nope, search the wiki, nope, where is that code I wrote a couple of months ago... oh here it is...

Dim dayName("noDay", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") as String

Dim monthName("noMonth", "January", "February", "March" ... oh you know where I'm going with this.

Actually I did find the answer to naming the days of the week on the forum from some other poor soul who was under the same kind of torture :) Here:
http://www.b4x.com/forum/basic4android-updates-questions/15104-getdayofmonth.html#post85683


So now it would seem that if I do:
lblMyLabel.Text = "Hello today it is " & dayName(GetDayOfWeek(1358686183885))
Then that might supply me with something friendly like "Hello today it is Sunday"
But it might not! because some people might not have their days of the week set the same as me, because although you would have
thought that everyone starts work on a Monday and therefore Monday is the first day of the week, it would seem that some people start work on a Sunday..... go figure :)
Perhaps the pope does? Sunday being religious and all? Therefore we obviously need a new BASIC function If NOT Pope Then .... hehe :)

So, I may or may not have a reliable way of getting the name of the day of the week and if not then my app will just look silly telling someone it's Monday when its Sunday but ok.

A nice useful BASIC function enabling me not to have to re-learn everything about DateTime each time I use it might have been:

lblMyLabel.Text=DateTime.dayName(1358686183885)

Another one might be:
lblMyLabel.Text=DateTime.monthName(1358686183885)

I'll bet these are already in there somewhere and can probably be got at using the reflector library so the above functions might only need to be wrappers and hopefully fairly easy to implement?

Perhaps some other useful BASIC functions might be:

text = DateTime.daySuffix(1358686183885) ' Returns either 'st', 'rd', 'nd' or 'th' then you can do 'Saturday the 24th of February' or 'Friday the 2nd of January' or 'Thursday the 3rd of March' etc.

I know it is fairly easy to program, if the number ends with 2 its nd if it ends with 3 then its rd, if it ends with 1 its st and everything else is th (i think) but it could be a handy function then we wouldn't have to dig out that old code each time or in other words, we could hold it in our heads.

See BASIC! Easy to remember, friendly.

B4X:
Dim wroteDT as long = 1358686183885

lblMyLabel.Text="Because I wrote this text at " & _
 DateTime.ampmTime(wroteDT) & " on " & DateTime.dayName(wroteDT) & _
" the " & DateTime.GetDayOfMonth(wroteDT) & _
DateTime.daySuffix(wroteDT) " of " & _
DateTime.monthName(wroteDT) & " " & _
DateTime.GetYear(wroteDT) & _
" my fingers are knackered because of all that typing. It would have been a whole lot easier," & _
"  although these functions would come in handy to split up the various elements of a DateTime string " & _ 
"yet what about if I just told you that I wrote this text at " & _
DateTime.ampmTime(wroteDT) & " on " & DateTime.longDate(wroteDT) & _
" " & DateTime.GetYear(wroteDT) & " ?"
DateTime.ampmTime might serve up the DateTime's time element as a string such as: 12:49pm or 0:49am and DateTime.longDate would return a string like Sunday the 20th of January thus to get the string as I wrote it at the top of this post would be:

lblMyLabel.Text = DateTime.ampmTime(wroteDT) & " on " & DateTime.longDate(wroteDT) & " " & DateTime.GetYear(wroteDT)

or perhaps just lblMyLabel.Text = DateTime.longDate2(wroteDT)

which either way would come out as =:

12:49pm on Sunday the 20th of January 2013

Phew!
 
Last edited:

IanMc

Well-Known Member
Licensed User
Longtime User
Nope, with respect I wrote about that in my post :)

although I did miss out the DateTime. part it was just for illustration

So now it would seem that if I do:
lblMyLabel.Text = "Hello today it is " & dayName(GetDayOfWeek(1358686183885))
Then that might supply me with something friendly like "Hello today it is Sunday"

So correctly written it should read:
So now it would seem that if I do:
lblMyLabel.Text = "Hello today it is " & dayName(DateTime.GetDayOfWeek(1358686183885))
Then that might supply me with something friendly like "Hello today it is Sunday"
But that doesn't really change the points that I am trying to get across.
 
Last edited:
Upvote 0

IanMc

Well-Known Member
Licensed User
Longtime User
Wrote some routines, good for the brain anyway :)

B4X:
Sub TimeDate_Click 'this would be the click event for a button.
   Dim dtNow As Long   'just for testing, strings written to the log.
   dtNow = DateTime.Now   
   Log(longDate(dtNow))
   Log(" ")
   Log(ampmTimeAndlongDate(dtNow))
End Sub

Sub dayName(dt As Long) As String
   Dim dayNames() As String:dayNames = Array As String("","Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
   Return dayNames(DateTime.GetDayOfWeek(dt))
End Sub

Sub monthName(dt As Long) As String
   Dim monthNames() As String:monthNames = Array As String("", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December")
   Return monthNames(DateTime.GetMonth(dt))
End Sub

Sub ampmTime(dt As Long) As String
   Dim h As Int
    Dim i As Double
   i = DateTime.GetMinute(dt)
   h = DateTime.GetHour(dt)
   If h <= 11 Then Return h & ":" & NumberFormat(i, 2, 0) & "am"
   h = h - 12
   If h = 0 Then h = 12 'coz we can't have hours as zero :)
   Return h & ":" & NumberFormat(i, 2, 0) & "pm"
End Sub

'Sub Time(dt As Long) As String 'erm... this sub would need some formatting and don't call it 'Time' bad idea, bad idea :)
'   Return DateTime.GetHour(dt) & ":" & DateTime.GetMinute(dt)
'End Sub

Sub dayWithSuffix(dt As Long) As String
   Dim s As String
   s = DateTime.GetDayOfMonth(dt)
   If s.EndsWith("1") Then Return s & "st"
   If s.EndsWith("2") Then Return s & "nd"
   If s.EndsWith("3") Then Return s & "rd"
   Return s & "th"
End Sub

Sub longDate(dt As Long) As String
   Return dayName(dt) & " " & dayWithSuffix(dt) & " of " & monthName(dt) & ", " & DateTime.GetYear(dt)     
End Sub

Sub ampmTimeAndlongDate(dt As Long) As String
   Return ampmTime(dt) & " on " & longDate(dt)  
End Sub

They're not fully tested, what's a good way to generate DateTime Long integers for various times?

Cheers

ian
 
Last edited:
Upvote 0

IanMc

Well-Known Member
Licensed User
Longtime User
Here in Southern England it's

am

pm

afore mornin' and past mornin' :)

(just joking but actually a cool way for children to learn what each one means)
 
Upvote 0

MLDev

Active Member
Licensed User
Longtime User
Hi IanMc

You can do all that now with DateTime.DateFormat and DateTime.TimeFormat.

For example I just tried this:

B4X:
DateTime.DateFormat = "EEEE MMMMM dd yyyy hh:mm aaa"
Log(DateTime.Date(DateTime.Now))

And got this:

Sunday January 20 2013 02:56 PM

See this for more info.
 
Last edited:
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
Hi IanMc

You can do all that now with DateTime.DateFormat and DateTime.TimeFormat.

For example I just tried this:

B4X:
DateTime.DateFormat = "EEEE MMMMM dd yyyy hh:mmaaa"
Log(DateTime.Date(DateTime.Now))
And got this:

Sunday January 20 2013 02:56PM

See this for more info.

Ah, excellent info!
 
Upvote 0

IanMc

Well-Known Member
Licensed User
Longtime User
Doh!

But mine's prettier ;)

Plus when I try to find these things in the docs I see in the KeyWord_Views.pdf document:

DateFormat As String
Gets or sets the format used to parse date strings.
See this page for the supported patterns: formats.
The default pattern is MM/dd/yyyy (04/23/2002 for example).

where the word 'formats.' is a link that leads to this page:
http://download-llnw.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html

Which is about as much use as a wooden eye at a keyhole :)
 
Upvote 0

IanMc

Well-Known Member
Licensed User
Longtime User
:signOops:

Ignore this one folks

B4X:
Sub dayWithSuffix(dt As Long) As String
    Dim s As String
    s = DateTime.GetDayOfMonth(dt)
    If s.EndsWith("1") Then Return s & "st"
    If s.EndsWith("2") Then Return s & "nd"
    If s.EndsWith("3") Then Return s & "rd"
    Return s & "th"
End Sub

till i fix it or you'll get 1st 2nd 3rd and then 11st 12nd 13rd :D hehe.

I've written these routines loads of times over the years.

Corse you can all chime in and help me fix it if you want :)

cheers

ian
 
Upvote 0

IanMc

Well-Known Member
Licensed User
Longtime User
:D Yay! fixed it

B4X:
Sub dayWithSuffix(dt As Long) As String
   Dim i As Int
   Dim s As String
   i = DateTime.GetDayOfMonth(dt)
   'i = dt 'test
   s = i
   If  i >= 4 AND i <= 20 Then Return s & "th"
   If s.EndsWith("1") Then Return s & "st"
   If s.EndsWith("2") Then Return s & "nd"
   If s.EndsWith("3") Then Return s & "rd"
   Return s & "th"
End Sub

You can also alter it to use it for any other number that you want to end with a suffix and to test this if you un-rem the 'i = dt 'test line like i have in the below code you can test it with a loop:

B4X:
Sub Test_Click 'will be the action for a button
        Dim L as long
        For L = 1 to 101
             Log(dayWithSuffix(L))
        Next
End Sub

Sub dayWithSuffix(dt As Long) As String
   Dim i As Int
   Dim s As String
   i = DateTime.GetDayOfMonth(dt)
   i = dt 'test
   s = i
   If  i >= 4 AND i <= 20 Then Return s & "th"
   If s.EndsWith("1") Then Return s & "st"
   If s.EndsWith("2") Then Return s & "nd"
   If s.EndsWith("3") Then Return s & "rd"
   Return s & "th"
End Sub

Then click on the button while you are viewing the log.

Erm ... :signOops: only it starts talking Hobbit after 110 :) hehe.

I'll fix it .... eventually :)

I did once do it in PowerBASIC,,, now where's my old code for that ... GANDALF! HAVE YOU SEEN MY OLD PB CODE ANYWHERE?
 
Last edited:
Upvote 0

IanMc

Well-Known Member
Licensed User
Longtime User
Fixed it :)

Here it is:
B4X:
Sub daySuffix(i As Int) As String 'add suffix to integer such as 10th 3rd 1st 2022nd etc.
   Dim s As String
   Dim j As Int
   s = i 'change the int to a string
   j = i 'make a copy of i that we can chop up
   If s.Length > 2 Then s = s.SubString(s.Length - 2)
   j = s 'j is now a number that is no bigger than 2 digits
   If j >= 4 AND j <= 20 Then Return i & "th" 'these last few
   If s.EndsWith("1") Then Return i & "st"    'lines work out
   If s.EndsWith("2") Then Return i & "nd"    'the correct suffix
   If s.EndsWith("3") Then Return i & "rd"    'and send back the 
   Return i & "th" 'original number as a string with the correct suffix after it.
End Sub

I decided to make it into a generic subroutine that can be used with any number so if you want to use it with the day number returned from DateTime you'd do this:

MyString = daySuffix(DateTime.GetDayOfMonth(dt))

This is not the most elegant way of doing it, RegEx would probably be much better and I'll look into that as RegEx are so useful for everything :)

Included is a little project I made to demo this and the other routines.
It also uses Erel's cool CustomListView to make the screen scrolly :)

Oh and I put the subs into another code module called MySubs so they can be called from anywhere within a project.
 

Attachments

  • MySubs.zip
    10.5 KB · Views: 202
  • MySubs.apk
    119.8 KB · Views: 215
Upvote 0

corwin42

Expert
Licensed User
Longtime User
It seems that you love to play around with dates and times :). The problem with your routines is that they only give english results.

Have you seen the AHLocale library with the AHLocale, AHDateTime and AHDateUtils objects. Much stuff for you to play with. :D
 
Upvote 0

IanMc

Well-Known Member
Licensed User
Longtime User
Yes I read one of Margret's posts about considering other languages when making an app, I think many more people will download it (and possibly buy it) if it is multi-language. I shall definitely be looking into it in the future.

For now my first app is nearing completion and I just want to get it out there, but then afterwards I shall have a good look at it.

I made a mistake in the ampmTime sub where it might show the time as 0:00am at midnight, here's a corrected version:
B4X:
Sub ampmTime(dt As Long) As String
   Dim h As Int
    Dim i As Double
   i = DateTime.GetMinute(dt)
   h = DateTime.GetHour(dt)
   If h <= 11 Then 
      If h = 0 Then h = 12 'coz we can't have hours as zero :)
      Return h & ":" & NumberFormat(i, 2, 0) & "am"
   End If
   h = h - 12
   If h = 0 Then h = 12 'coz we can't have hours as zero :)
   Return h & ":" & NumberFormat(i, 2, 0) & "pm"
End Sub
 
Upvote 0
Top