• Forum
  • Doc
  • Screenshots
  • Download
  • Donate
  • Contributors
  • Contact
  • Follow @phpfreechat
  • DEMO
  • Board index ‹ Version 1.x branch ‹ Contributions (v1.x)
  • Change font size
  • FAQ
  • Register
  • Login

User timezone

Post a bug fix, a new feature, a theme ...

Moderators: OldWolf, re*s.t.a.r.s.*2

Post a reply
9 posts • Page 1 of 1

Postby Peter » Mon May 07, 2007 9:38 pm

In the current version time values are based on the server time. User's timezones are not taken into account. A change of this behavior would be of interest for a lot of users.

I suggest the following changes:

In pfcglobalconfig.class.php add these 3 blue lines and add the blue values to var $_dyn_params:

class pfcGlobalConfig
{
var $serverid = ""; // this is the chat server id (comparable to the server host in IRC)

// these parameters are dynamic (not cached)
var $time_offset = 0;
var $date_format = "m-d-Y";
var $time_format = "h:i a";
...
var $_dyn_params = array("time_offset", "date_format","time_format","nick","isadmin","islocked","admins","frozen_channels", "channels", "privmsg", "nickmeta","baseurl");
...

Now we can pass time offsets and format strings thru initializing $params:

Code: Select all
        $params["time_offset"] = 8*3600;
        $params["date_format"] = "d/m/Y";
        $params["time_format"] = "H:i:s";
        $chat = new phpFreeChat( $params );

In pfccontainer.class.php change function write($chan, $nick, $cmd, $param) like

function write($chan, $nick, $cmd, $param)
{
$c =& pfcGlobalConfig::Instance();
if ($chan == NULL) $chan = 'SERVER';

$msgid = $this->_requestMsgId($chan);
$time = time() + $c->time_offset;
// format message
$data = "n";
$data .= $msgid."t";

$data .= gmdate($c->date_format, $time)."t";
$data .= gmdate($c->time_format, $time)."t";

$data .= $nick."t";
$data .= $cmd."t";
$data .= $param;

// write message
$this->setMeta("channelid-to-msg", $this->encode($chan), $msgid, $data);

// delete the obsolete message
$old_msgid = $msgid - $c->max_msg - 20;
if ($old_msgid > 0)
$this->rmMeta("channelid-to-msg", $this->encode($chan), $old_msgid);

return $msgid;
}

gmdate is necessary in order to reset to GMT time.

This is the best method to control user timezones, because we can pass user data from sql via $params.

In flat file mode the log stores timestamps in formatted strings, therefore users may see different time formats. I would suggest to store the timestamps like "timestamp_xxxxxxxxxx" and with a new function in pfccontainer.class.php we can format those timestamps with a preg_replace:

Code: Select all
  function format_time($time) {
    if (!$time) return "tt";
    $c =& pfcGlobalConfig::Instance();
    $time += $c->time_offset;
    return gmdate($c->date_format, $time)."t".gmdate($c->time_format, $time)."t";
  }

@kerphi:
I have noticed a small problem: time offsets can be positive and negative integers. The type test might reject negative offsets, because the default value is 0 (recognized as a positive type).
Peter
New member
 
Posts: 5
Joined: Mon May 07, 2007 2:55 pm
Top

Postby myjewchat » Tue May 08, 2007 6:48 am

your code displays users date besides time
myjewchat
Member
 
Posts: 15
Joined: Sat May 05, 2007 7:52 pm
Top

Postby Peter » Tue May 08, 2007 6:58 am

Take a look at the original code: It intends to display both, date and time.

If you don't want to have the date, pass an empty string for $params['date_format'].
Peter
New member
 
Posts: 5
Joined: Mon May 07, 2007 2:55 pm
Top

Postby phpfreechat » Wed May 09, 2007 9:30 am

Nice contribution however I cannot integrate your code in the official source code because I don't like the fact that you hardcode the time+offset in the container.
Why don't you calculate the time+offset just when the user read the data (in pfccontainer::read method) ?

Please adapt your code and I will integrate it.
phpfreechat
Site Admin
 
Posts: 2657
Joined: Tue Feb 07, 2006 3:35 pm
Location: France
Top

Postby myjewchat » Wed May 09, 2007 1:19 pm

if you show users local time it will be good feature
myjewchat
Member
 
Posts: 15
Joined: Sat May 05, 2007 7:52 pm
Top

Postby Peter » Thu May 10, 2007 6:21 pm

Hi Stéphane,

it took me some time to understand you, but now it is so clear. And by the way: This is a great great software.

Ok, method write does not mean "write to the browser" but "write to the storage system". And since read ist the reverse method, the second problem is solved, too.

Here we go (changes in blue):

function write($chan, $nick, $cmd, $param)
{
$c =& pfcGlobalConfig::Instance();
if ($chan == NULL) $chan = 'SERVER';

$msgid = $this->_requestMsgId($chan);

$data = "n";
$data .= $msgid."t";

$data .= time()."t";

$data .= $nick."t";
$data .= $cmd."t";
$data .= $param;

// write message
$this->setMeta("channelid-to-msg", $this->encode($chan), $msgid, $data);

// delete the obsolete message
$old_msgid = $msgid - $c->max_msg - 20;
if ($old_msgid > 0)
$this->rmMeta("channelid-to-msg", $this->encode($chan), $old_msgid);

return $msgid;
}

/**
* Read the last posted commands from a channel or from the server
* Notice: the returned array is ordered by id
* @param $chan if NULL then read from the server, otherwise read from the given channel
* @param $from_id read all message with a greater id
* @return array() contains the formated command list
*/
function read($chan, $from_id)
{
$c =& pfcGlobalConfig::Instance();
if ($chan == NULL) $chan = 'SERVER';

// read new messages id
$new_msgid_list = array();
$new_from_id = $from_id;
$msgid_list = $this->getMeta("channelid-to-msg", $this->encode($chan));
for($i = 0; $i<count($msgid_list["value"]); $i++)
{
$msgidtmp = $msgid_list["value"][$i];

if ($msgidtmp > $from_id)
{
if ($msgidtmp > $new_from_id) $new_from_id = $msgidtmp;
$new_msgid_list[] = $msgidtmp;
}
}

// read messages content and parse content
$datalist = array();
foreach ( $new_msgid_list as $mid )
{
$line = $this->getMeta("channelid-to-msg", $this->encode($chan), $mid, true);
$line = $line["value"][0];
if ($line != "" && $line != "n")
{
$formated_line = explode( "t", $line );
$data = array();
$data["id"] = trim($formated_line[0]);
$data["date"] = gmdate($c->date_format, $formated_line[1] + $c->time_offset);
$data["time"] = gmdate($c->time_format, $formated_line[1] + $c->time_offset);
$data["sender"]= $formated_line[2];
$data["cmd"] = $formated_line[3];
$data["param"] = $formated_line[4];

$datalist[$data["id"]] = $data;
}
}
ksort($datalist);

return array("data" => $datalist,
"new_from_id" => $new_from_id );
}

It is not necessary to store the timestamp twice, but then we have to use $formated_line[1] 2 times, for date and for time. The following field keys -1.

Now the storage system contains only unix timestamps (server time) and we can format the data in user format and user time zone. (by the way: in original code time is stored in a hardcoded user format)

As I have seen the mysql container stores timestamps in an extra field and the leave_value contains the timestamp, too. It's a little bit redundant. Perhaps write method should always pass the timestamp and the leave_value shouldn't have the timestamp in it. But this seems to force more changes in code design.

Passing offset and format strings via $params as before.

Concerning the problem with negative offsets:

I have changed this blue line in pfcglobalconfig.class.php with the red change:
function _saveParamsTypes()
{
$vars = get_object_vars($this);
foreach($vars as $k => $v)
{
if (is_string($v)) $this->_params_type["string"][] = $k;
else if (is_bool($v)) $this->_params_type["bool"][] = $k;
else if (is_array($v)) $this->_params_type["array"][] = $k;
else if (is_int($v) && $v>0) $this->_params_type["positivenumeric"][] = $k;
else $this->_params_type["misc"][] = $k;
}
}

I am not happy with this modification, but is helps.

There is another problem in getnewmsg.class.php, line 95:
Code: Select all
                    date("d/m/Y") == $m_date ? 1 : 0,

I guess you want to surpress the date display when the message is from the current day. Then it should be:
date($c->date_format) == $m_date ? 1 : 0,

Perhaps you should use formatted time strings as "late" as possible.

Same for some system strings like $GLOBALS["i18n"]["%s joins %s". They are stored in the user language. It might be better to store them as system variables and to replace them with the user language equivelants, when the data is read (read method above).
Last edited by Peter on Thu May 10, 2007 7:21 pm, edited 1 time in total.
Peter
New member
 
Posts: 5
Joined: Mon May 07, 2007 2:55 pm
Top

Postby phpfreechat » Fri May 11, 2007 10:46 am

Thank you Peter for your detailed post I really appreciate your code quality and your comments.
I just integrated your contribution (rev 1025) with little modifications from myself, here is the patch :
Code: Select all
Index: src/commands/getnewmsg.class.php
===================================================================
--- src/commands/getnewmsg.class.php   (révision 1023)
+++ src/commands/getnewmsg.class.php   (copie de travail)
@@ -79,8 +79,8 @@
     foreach ($data as $d)
     {
       $m_id          = $d["id"];
-      $m_date        = $d["date"];
-      $m_time        = $d["time"];
+      $m_date        = gmdate($c->date_format, $d["timestamp"] + $c->time_offset);
+      $m_time        = gmdate($c->time_format, $d["timestamp"] + $c->time_offset);
       $m_sender      = $d["sender"];
       $m_recipientid = $recipientid;
       $m_cmd         = $d["cmd"];
@@ -92,8 +92,8 @@
                     $m_recipientid,
                     $m_cmd,
                     $m_param,
-                    date("d/m/Y") == $m_date ? 1 : 0,
-                    $oldmsg ? 1 : 0);
+                    gmdate($c->date_format, time() + $c->time_offset) == $m_date ? 1 : 0, // posted today ?
+                    $oldmsg ? 1 : 0); // is it a new message in the current session or is it a part of the history
       $data_sent = true;
     }
     if (count($js) != 0)
Index: src/pfccontainer.class.php
===================================================================
--- src/pfccontainer.class.php   (révision 1023)
+++ src/pfccontainer.class.php   (copie de travail)
@@ -352,6 +352,7 @@
    */
   function isNickOnline($chan, $nickid)
   {
+    if (!$nickid) return false;
     if ($chan == NULL) $chan = 'SERVER';
 
     $ret = $this->getMeta("channelid-to-nickid",
@@ -380,8 +381,7 @@
     // format message
     $data = "n";
     $data .= $msgid."t";
-    $data .= date("d/m/Y")."t";
-    $data .= date("H:i:s")."t";
+    $data .= time()."t";
     $data .= $nick."t";
     $data .= $cmd."t";
     $data .= $param;
@@ -434,12 +434,11 @@
       {
         $formated_line = explode( "t", $line );
         $data = array();
-        $data["id"]    = trim($formated_line[0]);
-        $data["date"]  = $formated_line[1];
-        $data["time"]  = $formated_line[2];
-        $data["sender"]= $formated_line[3];
-        $data["cmd"]   = $formated_line[4];
-        $data["param"] = $formated_line[5];
+        $data["id"]        = trim($formated_line[0]);
+        $data["timestamp"] = $formated_line[1];
+        $data["sender"]    = $formated_line[2];
+        $data["cmd"]       = $formated_line[3];
+        $data["param"]     = $formated_line[4];
         $datalist[$data["id"]] = $data;
       }
     }
Index: src/pfcglobalconfig.class.php
===================================================================
--- src/pfcglobalconfig.class.php   (révision 1023)
+++ src/pfcglobalconfig.class.php   (copie de travail)
@@ -133,6 +133,20 @@
   var $debugxajax          = false;
 
   /**
+   * This is the user time zone
+   * it is the difference in seconds between user clock and server clock
+   */
+  var $time_offset         = 0;
+  /**
+   * How to display the dates in the chat
+   */
+  var $date_format         = "d/m/Y";
+  /**
+   * How to display the time in the chat
+   */
+  var $time_format         = "H:i:s";
+ 
+  /**
    * This parameter is useful when your chat server is behind a reverse proxy that
    * forward client ip address in HTTP_X_FORWARDED_FOR http header.
    * see : http://www.phpfreechat.net/forum/viewtopic.php?id=1344
@@ -142,7 +156,7 @@
   
   // private parameters
   var $_sys_proxies         = array("lock", "checktimeout", "checknickchange", "auth", "noflood", "censor", "log");
-  var $_dyn_params          = array("nick","isadmin","islocked","admins","frozen_channels", "channels", "privmsg", "nickmeta","baseurl");
+  var $_dyn_params          = array("nick","isadmin","islocked","admins","frozen_channels", "channels", "privmsg", "nickmeta","baseurl","time_offset","date_format","time_format");
   var $_params_type         = array();
   var $_query_string        = '';
   
@@ -266,7 +280,7 @@
       if (is_string($v))                $this->_params_type["string"][]  = $k;
       else if (is_bool($v))             $this->_params_type["bool"][]    = $k;
       else if (is_array($v))            $this->_params_type["array"][]   = $k;
-      else if (is_int($v) && $v>=0)     $this->_params_type["positivenumeric"][] = $k;
+      else if (is_int($v) && $v>0)      $this->_params_type["positivenumeric"][] = $k;
       else $this->_params_type["misc"][] = $k;
     }
   }

I have something to say about your comment :
Perhaps you should use formatted time strings as "late" as possible.

I totally agree with you and the later is client side. However my javascript skills are not great and I don't know well how to manipulate dates/time zone in javascript. If you are motivated it would be great to do the time_offset calculations client side... and maybe it could be possible to "detect" automatically the user time zone with javascript functions, I don't know.

About the string like "%s joins %s", I agree too that it should not be hardcoded in the container data in order to allow clients with customized interface languages on the same chat.
This is something to do if you are motivated to contribute you are really welcomed.

Thanks you Peter and I hope to work with you again in the future :)
phpfreechat
Site Admin
 
Posts: 2657
Joined: Tue Feb 07, 2006 3:35 pm
Location: France
Top

Postby rocknolds » Sat Nov 17, 2007 10:55 am

so where can i get the final goods with the integration?
http://sms-cebu.org
rocknolds
Member
 
Posts: 15
Joined: Thu Jul 12, 2007 12:41 pm
Top

Postby phpfreechat » Wed Nov 21, 2007 3:12 pm

It is available in the latest release.
phpfreechat
Site Admin
 
Posts: 2657
Joined: Tue Feb 07, 2006 3:35 pm
Location: France
Top


Post a reply
9 posts • Page 1 of 1

Return to Contributions (v1.x)

Who is online

Users browsing this forum: No registered users and 3 guests

  • Board index
  • The team • Delete all board cookies • All times are UTC + 1 hour
Powered by phpBB® Forum Software © phpBB Group
Sign in
Wrong credentials
Sign up I forgot my password
.
jeu-gratuit.net | more partners
Fork me on GitHub