Date and Time

Top  Previous  Next

Why have a tutorial just on dates and times?

Since Object Pascal and Javascript deal with dates quite differently. Sadly dates coming from JS to SmartMS can be a issue. Because they are a surprisingly complex and rich subject matter.

 

The TDateTime data type in SmartMS

In Delphi, Date and time processing depends on the TDateTime variable. It is used to hold a date and time combination. Smart Mobile Studio Smart Mobile Studio represents a DateTime type as a Float type, similar to TDateTime. The System.Types unit defines a type alias type TDateTime = Float.

 

DateTimetoStr (Now)

 

As I said, Object Pascal and Javascript deal with dates differently. The function DateTimetoStr (Now) return differents results.

Example:

DateTimetoStr (Now) using Delphi, result is: 7/25/2014 5:30:54 PM

DateTimetoStr (Now) using SmartMS, result is: 2014-07-25 20:30:54

The problem is the fact it shows the UTC date and not the local date time. An workaround is illustrated by the following examples:

 

 

Code example: Display Local DateTime 1 - add SmartCL.RegEx unit.

function DateTimeToStr2 : string;

var md : Variant;

r1,r2,r3: TW3Regex;

begin

 r1 := TW3Regex.Create('d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|''g');

 r2 := TW3Regex.Create('\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b''g');

 r3 := TW3Regex.Create('[^-+\dA-Z]''g');

  asm

    var dF=function(){var t1=RegExp(@r1.FRegEx),t2=RegExp(@r2.FRegEx),t3=RegExp(@r3.FRegEx),p=function(v,l){v=String(v);l=l||2;while(v.length<l)v='0'+v;return v;};return function(dt,m1,u){if(arguments.length==1 && Object.prototype.toString.call(dt)=="[object String]" &&! '/\d/'.test(dt)){m1=dt;dt=undefined;} dt=dt?new Date(dt):new Date;if(isNaN(dt))throw SyntaxError('invalid date');m1=String(dF.m1s[m1]||m1||dF.m1s['default']);if(m1.slice(0,4)=='UTC:'){m1=m1.slice(4);u=true;} var _=u?'getUTC':'get',d=dt[_+'Date'](),D=dt[_+'Day'](),m=dt[_+'Month'](),y=dt[_+'FullYear'](),H=dt[_+'Hours'](),M=dt[_+'Minutes'](),s=dt[_+'Seconds'](),L=dt[_+'Milliseconds'](),o=u?0:dt.getTimezoneOffset(),flags={d:d,dd:p(d),mm:p(m+1),yyyy:y,hh:p(H%12||12),HH:p(H),MM:p(M),s:s,ss:p(s),l:p(L,3),L:p(L>99?Math.round(L/10):L),t:H<12?'a':'p',tt:H<12?'am':'pm',T:H<12?'A':'P',TT:H<12?'AM':'PM',Z:u?'UTC':(String(dt).match(t2)||['']).pop().replace(t3,''),o:(o>0?'-':'+')+p(Math.floor(Math.abs(o)/60)*100+Math.abs(o)%60,4),S:['th','st','nd','rd'][d%10>3?0:(d%100-d%10!=10)*d%10]};return m1.replace(t1,function($0){return $0 in flags?flags[$0]:$0.slice(1,$0.length-1);});};}();dF.m1s={};Date.prototype.format=function(u){return dF(this,u);};@md = new Date().format('yyyy-mm-dd HH:MM:ss');

   end;

 result := md;

end;

 

 

ShowMessage(DateTimeToStr2);

 

 

Result is: 2014-07-25 17:30:54

------------------------------------------------------------

 

 

 

Code example: Display Local DateTime 2 - add W3C.Date unit.

procedure TForm1.W3Button1Click(Sender: TObject);

var Date: JDate = JDate.Create;

 

begin

// Get local date time

// calculate local date & time

// Get local date time

WriteLn(DateTimeToStr( Date.AsDateTime));   // 2014-07-25 21:44:17

WriteLn(DateTimetoStr(Now));                // 2014-07-25 21:44:17

WriteLn(DateToStr( Date.AsDateTime));       // 2014-07-25

WriteLn(TimeToStr( Date.AsDateTime));       // 21:44:17

 

WriteLn(Date.toLocaleString);               // 25/7/2014 18:44:17

 

// my local date time

myDate := EncodeDate(Date.getFullYear, Date.getMonth+1, Date.getDate)+EncodeTime(Date.getHours, Date.getMinutes, Date.getSeconds, Date.getMilliseconds);

 

WriteLn(DateTimeToStr(myDate));             // 2014-07-25 18:44:17

WriteLn(DateToStr(myDate));                 // 2014-07-25

WriteLn(TimeToStr(myDate));                 // 18:44:17

 

end;

 

Result is:

2014-07-25 21:44:17

2014-07-25 21:44:17

2014-07-25

21:44:17

 

25/7/2014 18:44:17

 

2014-07-25 18:44:17

2014-07-25

18:44:17

--------------------------------

 

 

 

mytoggle_plus1JS code generated:

function W3Button1Click(Self, Sender$9) {

      var myDate = 0;

      var Date$2 = null;

      var Date$2 = new Date();

      WriteLn(DateTimeToStr(JDateHelper$GetAsDateTime(Date$2)));

      WriteLn(DateTimeToStr(Now()));

      WriteLn(DateToStr(JDateHelper$GetAsDateTime(Date$2)));

      WriteLn(TimeToStr(JDateHelper$GetAsDateTime(Date$2)));

      WriteLn(Date$2.toLocaleString());

      myDate = EncodeDate(Date$2.getFullYear(),Date$2.getMonth()+1,Date$2.getDate())+

               EncodeTime(Date$2.getHours(),Date$2.getMinutes(),Date$2.getSeconds(),Date$2.getMilliseconds());

      WriteLn(DateTimeToStr(myDate));

      WriteLn(DateToStr(myDate));

      WriteLn(TimeToStr(myDate));

   }

 

function JDateHelper$GetAsDateTime(Self$7) {

   return (Self$7.getTime()/86400000)+25569;

}

 

function JDateHelper$SetAsDateTime(Self$8, dt) {

   Self$8.setTime((dt-25569)*86400000);

}

 

function Now() { var d=new Date(); return d.getTime()/8.64e7+25569 };

function EncodeTime(h,m,s,z) { return (h+(m+(s+z*0.001)/60)/60)/24 };

function EncodeDate(y,m,d) { return Math.round(Date.UTC(y,m-1,d)/864e5+25569) };

function DateToStr(v) { return FormatDateTime("yyyy-mm-dd", v) };

function DateTimeToStr(v) { return FormatDateTime("yyyy-mm-dd hh:nn:ss", v) };

function TimeToStr(v) { return FormatDateTime("hh:nn:ss", v) };

 

function FormatDateTime(fmt, v) {

   function pad2(v) { return (v<10)?"0"+v:v; };

   function pad3(v) { return (v<100)?"0"+pad2(v):v; };

   var res="";

   var dt=new Date((v-25569)*864e5);

   if (isNaN(dt.getTime())) return "#VAL!";

   var i=0;

   var c, tok;

   while (i<fmt.length) {

      c=fmt.charAt(i);

      tok="";

      while ((fmt.charAt(i)==c)&&(i<fmt.length)) {

         tok+=c;

         i++;

      }

      switch (tok) {

         case "d": res+=(dt.getUTCDate()); break;

         case "dd": res+=pad2(dt.getUTCDate()); break;

         case "ddd": res+=fmtShortDayNames[dt.getUTCDay()]; break;

         case "dddd": res+=fmtLongDayNames[dt.getUTCDay()]; break;

         case "m": res+=dt.getUTCMonth()+1break;

         case "mm": res+=pad2(dt.getUTCMonth()+1); break;

         case "mmm": res+=fmtShortMonthNames[dt.getUTCMonth()]; break;

         case "mmmm": res+=fmtLongMonthNames[dt.getUTCMonth()]; break;

         case "yy": res+=pad2(dt.getUTCFullYear()%100); break;

         case "yyyy": res+=dt.getUTCFullYear(); break;

         case "h": res+=dt.getUTCHours(); break;

         case "hh": res+=pad2(dt.getUTCHours()); break;

         case "n": res+=dt.getUTCMinutes(); break;

         case "nn": res+=pad2(dt.getUTCMinutes()); break;

         case "s": res+=dt.getUTCSeconds(); break;

         case "ss": res+=pad2(dt.getUTCSeconds()); break;

         case "z": res+=dt.getUTCMilliseconds(); break;

         case "zzz": res+=pad3(dt.getUTCMilliseconds()); break;

         default: res+=tok;

      }

   }

   return res;

}

 

 

 

 

 

Displaying FormatDateTime in SmartMS

 

 

There are a number of routines that convert date and or time values to strings for display or file storage purposes, such as dateTimeToStr and TimeToString. But the most important is the FormatDateTime. It provides comprehensive formatting control.

 

Code example: FormatDateTime with SmartMS

procedure TForm1.W3Button1Click(Sender: TObject);

var

  myDate: Float;

begin

  myDate := EncodeDate(2014725) + EncodeTime(5678);

 

  // Date only - numeric values with no leading zeroes (except year)

  WriteLn(' d/m/yy = ' +

    FormatDateTime('d/m/yy', myDate));

 

  // Date only - numeric values with leading zeroes

  WriteLn(' dd/mm/yy = ' +

    FormatDateTime('dd/mm/yy', myDate));

 

  // Use short names for the day, month, and add freeform text ('of')

  WriteLn(' ddd d of mmm yyyy = ' +

    FormatDateTime('ddd d of mmm yyyy', myDate));

 

  // Use long names for the day and month

  WriteLn('dddd d of mmmm yyyy = ' +

    FormatDateTime('dddd d of mmmm yyyy', myDate));

 

  // Use the ShortDateFormat settings only

  WriteLn(' dddd = ' +

    FormatDateTime('dddd', myDate));

 

  WriteLn(' mmmmm = ' +

    FormatDateTime('mmmm', myDate));

 

  WriteLn(' yyyy = ' +

    FormatDateTime('yyyy', myDate));

 

  // Time only - numeric values with no leading zeroes

  WriteLn(' h:n:s.z = ' +

    FormatDateTime('h:n:s.z', myDate));

 

  // Time only - numeric values with leading zeroes

  WriteLn(' hh:nn:ss.zzz = ' +

    FormatDateTime('hh:nn:ss.zzz', myDate));

 

  // DateTime - numeric values with leading zeroes

  WriteLn('dd-mm-yyyy hh:nn:ss = ' +

    FormatDateTime('dd-mm-yyyy hh:nn:ss', myDate));

 

  WriteLn('The meeting is on' + FormatDateTime(' dddd, mmmm d, yyyy, ' +

    'at hh:nn:ss', StrToDateTime('2014-08-25 17:39:45')));

 

  WriteLn(DayOfMonth(myDate));

  WriteLn(DayOfTheWeek(myDate));

  WriteLn(DayOfWeek(myDate));

  WriteLn(DayOfYear(myDate));

 

end;

 

Result is:

d/m/yy = 25/7/14

 dd/mm/yy = 25/07/14

 ddd d of mmm yyyy = fri 25 of jul 2014

 dddd d of mmmm yyyy = friday 25 of july 2014

 dddd = friday

 mmmmm = july

 yyyy = 2014

 h:n:s.z = 5:6:7.7

 hh:nn:ss.zzz = 05:06:07.007

 dd-mm-yyyy hh:nn:ss = 25-07-2014 05:06:07

 The meeting is on monday, august 25, 2014, at 17:39:45

 25

 5

 6

 206 

------------
 

 

Date and Time calculations

 

The largest benefit of TDateTime (Float) is the range of calculations SmartMS can do for you. These can be found on the SmartMS built-in functions.
 

Code example: Custom date functions with SmartMS

function TodayFloat;

begin

  Result := Date;

end;

 

function YesterdayFloat;

begin

  Result := Date - 1;

end;

 

function TomorrowFloat;

begin

  Result := Date + 1;

end;

 

procedure TForm1.W3Button1Click(Sender: TObject);

begin

WriteLn('Today is '+DateToStr(Today)); // Set to the start of the current day

WriteLn('Yesterday is '+DateToStr(Yesterday));  // Set to the start of yesterday

WriteLn('Tomorrow is '+DateToStr(Tomorrow)); // Set to the start of tomorrow

WriteLn('DateTimeToISO8601 is '+DateTimeToISO8601(Now())); Set to the current day and time

WriteLn('DateTimeToStr is '+DateTimeToStr(Now()));

WriteLn('DateToISO8601 is '+DateToISO8601(Now()));

WriteLn('DateToStr is '+DateToStr(Now()));

WriteLn('DateToWeekNumber is '+ IntToStr( DateToWeekNumber(Now())) );

WriteLn('DateToYearOfWeek is '+ IntToStr( DateToYearOfWeek(Now())) );

WriteLn('DayOfMonth is ' + IntToStr( DayOfMonth(Now())) );

WriteLn('DayOfTheWeek is '+ IntToStr( DayOfTheWeek(Now())) );

WriteLn('DayOfWeek is '+ IntToStr( DayOfWeek(Now())) );

WriteLn('DayOfYear is '+ IntToStr( DayOfYear(Now())) );

end;

 

Result is:

Today is 2014-07-20

Yesterday is 2014-07-19

Tomorrow is 2014-07-21

DateTimeToISO8601 is 2014-07-20T19:54Z

DateTimeToStr is 2014-07-20 19:54:03

DateToISO8601 is 2014-07-20

DateToStr is 2014-07-20

DateToWeekNumber is 29

DateToYearOfWeek is 2014

DayOfMonth is 20

DayOfTheWeek is 7

DayOfWeek is 1

DayOfYear is 201

--------------------------

 

 

Show Long and Short named date values

 

Delphi provides some useful day and month names, such as: LongDayNames, ShortDayNames, LongMonthNames, ShortMonthNames, etc. With Smart Mobile Studio, you have to define this names in your own code, for instance:

·LongDayNames variable provides an array of full string names of the days of the week.

It is important to note that these day arrays start with index 1 = Sunday. This is not a good standard (it is not ISO 8601 compliant), so be careful when using with ISO 8601 compliant routines such as DayOfTheWeek

·ShortMonthNames variable provides an array of short string names of the months of the year.

Note that these month name array start with index = 1.

 

Code example: Display the long day names

procedure TForm1.W3Button3Click(Sender: TObject);

var LongDayNames : array[1..7of string = ['Sunday','Monday','Tuesday','Wednesday',

                                            'Thursday','Friday','Saturday'];

    myDate : Float;

    day    : string;

begin

  myDate := EncodeDate(20141225);

  day := LongDayNames[DayOfWeek(myDate)];

  ShowMessage('Christmas day 2014 is on a '+day);

end;

 

Result is: Christmas day 2014 is on a Thursday

------------------------------------------------------------
 

Code example: Display the short month names

procedure TForm1.W3Button2Click(Sender: TObject);

var

 month : Integer;

 ShortMonthNames : array[1..12of string = ['Jan','Feb','Mar','Apr','May','Jun',

                                             'Jul','Aug','Sep','Oct','Nov','Dec'];

begin

  for month := 1 to 12 do // Display the short and long month names

    begin

     ShowMessage(ShortMonthNames[month]);

    end;

end;

 

Result is:

Jan

Feb

Mar

Apr

May

Jun

Jul

Aug

Sep

Oct

Nov

Dec

------

 

TIP: If you use DateTimeToStr( ) function in your code, SmartMS will generate this JS code which define theses variables: fmtShortDayNames, fmtLongDayNames, fmtShortMonthNames and fmtLongMonthNames.

 

Code example: Display long and short date names:

procedure TForm1.W3Button2Click(Sender: TObject);

var

 m, d : Integer;

begin

for m := 0 to 11 do // Display the short and long month names

begin

  asm

    WriteLn(fmtShortMonthNames[@m]);

    WriteLn(fmtLongMonthNames[@m]);

  end;

end;

 

for d := 0 to 6 do // Display the short and long day names

begin

  asm

    WriteLn(fmtShortDayNames[@d]);

    WriteLn(fmtLongDayNames[@d]);

  end;

end;

 

end;

 

Result is:

------------

jan

january

feb

february

mar

march

apr

april

may

may

jun

june

jul

july

aug

august

sep

september

oct

october

nov

november

dec

december

 

sun

sunday

mon

monday

tue

tuesday

wed

wednesday

thu

thursday

fri

friday

sat

saturday

---------------