<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Thorsten Suckow-Homberg</title>
	<atom:link href="http://thorsten.suckow-homberg.de/feed/" rel="self" type="application/rss+xml" />
	<link>http://thorsten.suckow-homberg.de</link>
	<description>About my work with conjoon, ExtJS and Sencha Touch.</description>
	<lastBuildDate>Mon, 28 Nov 2011 10:56:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Zend_Date, default time zones and DST</title>
		<link>http://thorsten.suckow-homberg.de/2011/11/17/zend_date-default-timezones-and-dst/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=zend_date-default-timezones-and-dst</link>
		<comments>http://thorsten.suckow-homberg.de/2011/11/17/zend_date-default-timezones-and-dst/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 18:15:36 +0000</pubDate>
		<dc:creator>Thorsten Suckow-Homberg</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[date]]></category>
		<category><![CDATA[dst]]></category>
		<category><![CDATA[I18N]]></category>
		<category><![CDATA[locale]]></category>
		<category><![CDATA[localization]]></category>
		<category><![CDATA[time zone]]></category>
		<category><![CDATA[timezone]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[zend_date]]></category>

		<guid isPermaLink="false">http://thorsten.suckow-homberg.de/?p=343</guid>
		<description><![CDATA[Is your application prepared to support different locales? Do you provide translations and different number formats based on a user's regional conditions? If so, how about time and calendar dates? Do you keep track of the <a title="UTC Offset explained" href="http://en.wikipedia.org/wiki/UTC_offfset" target="_blank">UTC Offset</a> and the <a title="DST explained" href="http://en.wikipedia.org/wiki/Daylight_saving_time" target="_blank">Daylight Saving Time (DST)</a> relative to the timezone your users live in, and are you able to convert dates properly to different time zones?]]></description>
			<content:encoded><![CDATA[<p class="wide">Is your application prepared to support different locales? Do you provide translations and different number formats based on a user&#8217;s regional conditions? If so, how about time and calendar dates? Do you keep track of the <a title="UTC Offset explained" href="http://en.wikipedia.org/wiki/UTC_offfset" target="_blank">UTC Offset</a> and the <a title="DST explained" href="http://en.wikipedia.org/wiki/Daylight_saving_time" target="_blank">Daylight Saving Time (DST)</a> relative to the time zone your users live in, and are you able to convert dates properly to different time zones? This article will show you how to utilize <code>Zend_Date</code> to make your application aware of all this.</p>
<ul class="accordion"><li><a href="#" class="opener"><strong>Intended Audience &#038; other Notes</strong></a><div class="slide-holder"><div class="slide"><p> Are you working with PHP and Zend Framework, and share a hearty dislike for I18N? Then this article is for you. </p>
<p class="message_yellow" style="font-size:13px;"> This article was written for Zend Framework 1.11 and PHP >= 5.2. Database examples are using MySQL. 
<br />
This article is aware of the fact that working with time-related functions may cause problems on systems where PHP supports only timestamps as unsigned 32-bit integers. Since this problems should've been fixed to a large degree with PHP 5.1.0, and the fact that even <code>Zend_Date</code> silently assumes that working with dates in the range of 1901 and 2038 using PHP internal functions will succeed, we are not paying too much attention to this.
</p><br class="clear" /></div></div></li></ul>
<div id="toc_container" class="toc_wrap_left toc_light_blue no_bullets">
<p class="toc_title">Table of Contents</p>
<ul class="toc_list">
<li><a href="#Michael_Tim_and_an_8_hour_offset">1 Michael, Tim and an 8 hour offset</a></li>
<li><a href="#Preparing_your_application">2 Preparing your application</a>
<ul>
<li><a href="#Make_the_time_zone_globally_configurable">2.1 Make the time zone globally configurable</a></li>
<li><a href="#Let_the_user_choose_a_time_zone">2.2 Let the user choose a time zone</a></li>
<li><a href="#Set_up_the_time_zone_for_each_request">2.3 Set up the time zone for each request</a></li>
</ul>
</li>
<li><a href="#The_0_meridian_for_your_data_storage">3 The 0 meridian for your data storage</a>
<ul>
<li><a href="#Choosing_the_MySQL_data_type_for_our_dates">3.1 Choosing the MySQL data type for our dates</a>
<ul>
<li><a href="#Unix_Timestamp">3.1.1 Unix Timestamp</a></li>
<li><a href="#datetime_Fields">3.1.2 datetime Fields</a></li>
</ul>
</li>
<li><a href="#Getting_that_UTC_date_ready_for_Mysql">3.2 Getting that UTC date ready for Mysql</a></li>
</ul>
</li>
<li><a href="#Being_soft_and_flexible">4 Being soft and flexible</a></li>
<li><a href="#Wrapping_things_up">5 Wrapping things up</a></li>
</ul>
</div>
<h3><span id="Michael_Tim_and_an_8_hour_offset">Michael, Tim and an 8 hour offset</span></h3>
<p class="wide">
Why would you want to convert dates to different time zones once they have been persisted in the data storage? Let&#8217;s say you are a London based developer and one of your clients works with this software you&#8217;ve written, a tool for creating, managing and sharing documents. This company is about to expand globally, and you&#8217;re excited that they just ordered a few more licenses for their new office in San Francisco. Michael, the former head of the financial department and one of the core users of your document sharing tool, will be the company&#8217;s first long time employee heading to the US, and a week before he moves, he introduces Tim &#8211; his replacement for the London based office &#8211; to the functionality of your software.<br />
&#8220;See&#8221;, Michael says, &#8220;once you have finished working with the document, you click the &#8216;share&#8217; button and it will automatically end up in my inbox for pending reviews.&#8221; He leans back, crossing the arms behind his head. &#8220;It&#8217;s that easy!&#8221;<br />
A few days later &#8211; Tim finally got his own user account set up by the company&#8217;s admin &#8211; Michael moves from London to San Francisco. Your application did its job really good over the past months, and everyone&#8217;s pleased with how smooth everything&#8217;s working, and how convenient it is to access and manage documents from any computer with a working internet connection<sup class='footnote'><a href='#fn-343-1' id='fnref-343-1' onclick='return fdfootnote_show(343)'>[1]</a></sup>.<br />
What nobody recognized yet &#8211; your application stored Michael&#8217;s (and everyone else&#8217;s) documents along with the absolute date of the time zone of London (<a title="GMT explained" href="http://en.wikipedia.org/wiki/Greenwich_Mean_Time" target="_blank">GMT</a>, that is), and he now continues to use your software in San Francisco. And he&#8217;s pretty confused about the strange dates that confront him now while looking at his document workspace. &#8220;Bananas&#8221;, he thinks.<br />
&#8220;This one draft here&#8221;, he takes a close look at the monitor while circling the mouse pointer over the document entry, &#8220;I know Tim created it and shared it with me last monday, but that was clearly not at 08:00 PM.&#8221;<br />
He scratches his head. &#8220;I remember receiving this draft around noon, or was it the other day? I went home around 07:00 PM, there&#8217;s no way I could have received the draft later on. Something must be broken&#8230; Or am I stressed out?&#8221;<br />
So what&#8217;s happening here? Well, he moved to the pacific time zone which relies upon <a title="PST explained" href="http://en.wikipedia.org/wiki/Pacific_Standard_Time" target="_blank">Pacific Standard Time (PST)</a>. And this time zone is exactly 8 hours behind the time zone he previously lived in (ignoring <a href="http://http://en.wikipedia.org/wiki/Daylight_saving_time" target="_blank" title="Daylight saving time explained">Daylight Saving Time</a> for now).<br />
Clicking somewhat lost through your application in search for a reasonable explanation, he notices that the software does not consider him being in a different time zone. Furthermore: He doesn&#8217;t find any option that would let him select a different time zone other than the one he lived in &#8211; and obviously where the software was developed.<br />
It&#8217;s definitely time for some improvements. We all want our software to be used across the globe, don&#8217;t we?</p>
<p class="message_blue" style="font-size:13px;"> 
To clarify things: Yes, Tim actually saved the draft at 08:00 PM, but according to GMT. Since London is 8 hours ahead of San Francisco, Michael must have received the draft somewhen around 12:00 noon PST - the time Tim actually sent the draft from London minus the 8 hour offset to PST. 
</p><br class="clear" />
<p class="wide">
Confused? Don&#8217;t worry, <a title="Zend_Date Reference Guide" href="http://framework.zend.com/manual/en/zend.date.html" target="_blank">Zend_Date</a> is here to help. As part of the <a title="Zend Framework Project Home" href="http://framework.zend.com/" target="_blank">Zend Framework</a>, <code>Zend_Date</code> allows for convenient access to operations related to calculations, formats and transformations of dates.
</p>
<h3><span id="Preparing_your_application">Preparing your application</span></h3>
<div class="one_half">
<p class="wide">
It is really important for software to be aware of the time zone it is currently serving as soon as there are any calculations related to dates and times involved.<br />
Wondering whether your software is affected by this problem? Are dates and times part of any entity in your software which need to be persisted? If you can answer this question with &#8220;Yes!&#8221; (or if your first thought was &#8220;ah, crap&#8230;&#8221;), then you have already given yourself the answer: To a certain degree, it is possible that your software messes with the users&#8217; feelings as soon as the time zone changes &#8211; whether it&#8217;s the time zone of your PHP environment or the time zone a user lives in. The following will give you some food for thought for your next planning meeting<sup class='footnote'><a href='#fn-343-2' id='fnref-343-2' onclick='return fdfootnote_show(343)'>[2]</a></sup>.</p>
</div><div class="one_half_last"><div class="modern_img_frame modern_three_col_large"><div class="modern_preload_three_col_large"><div class="attachment-fadeIn"><img src="/wp-content/uploads/2011/11/tba-275x145.png" alt="Zend_Date, default time zones and DST" class="thumbnail one_third_image " width="275" height="145" /></div></div>
</div><!-- end img_frame --><p class="message_blue" style="font-size:13px;"> 
Don't forget: Pain grows exponentially to the time spent deferring important decisions. </p><br class="clear" /></div><br class="clear" />
<p class="wide">
There are a few steps you should take into account when adding time zone support to your application, and all of them should be implemented in one or another way in your software:
</p>
<ul class="list list3">
<li>Make the time zone globally configurable</li>
<li>Provide a default time zone and let the user choose the timezone he currently lives in</li>
<li>Set the default time zone for further date calculations for each request</li>
</ul>
<h4><span id="Make_the_time_zone_globally_configurable">Make the time zone globally configurable</span></h4>
<p class="wide">
The time zone setting should be globally configurable without even touching PHP&#8217;s or the system&#8217;s configuration. When working with <code>Zend_Framework</code>, this can easily be done by using <a title="Zend_Config reference guide" href="http://framework.zend.com/manual/1.11/en/zend.config.html" target="_blank">Zend_Config</a>, a powerful component which helps in parameterizing your software. There are a lot of good tutorials out there so I won&#8217;t dive too deep into how to set up an application with <code>Zend_Config</code>, and give you a simple example instead:
</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="ini"><pre class="de1"><span class="re0"><span class="br0">&#91;</span>environment<span class="br0">&#93;</span></span> 
<span class="co0">; Specify the default time zone for the application here. For a list of </span>
<span class="co0">; timezones supported by PHP, see http://de.php.net/manual/en/timezones.php </span>
date.timezone.default <span class="sy0">=</span><span class="re2"> Europe/Berlin</span></pre></div></div></div></div></div></div></div>


<p class="message_blue" style="font-size:13px;"> 
Above: Code snippet showing part of a configuration file (ini-format) for a <code>Zend_Framework</code> application, defining the default time zone. 
</p><br class="clear" />
<p class="wide">
You can access the configuration by simply loading the ini-File using <code>Zend_Config_Ini</code>, and then query the settings accordingly.
</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="php"><pre class="de1"><span class="co1">// load the configuration </span>
<span class="re0">$config</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Config_Ini<span class="br0">&#40;</span><span class="st_h">'/path/to/config/file'</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="co1">// read out the time zone setting </span>
<span class="re0">$timezone</span> <span class="sy0">=</span> <span class="re0">$config</span><span class="sy0">-&gt;</span><span class="me1">environment</span><span class="sy0">-&gt;</span><span class="me1">date</span><span class="sy0">-&gt;</span><span class="me1">timezone</span><span class="sy0">-&gt;</span><span class="kw1">default</span><span class="sy0">;</span></pre></div></div></div></div></div></div></div>


<p class="message_blue" style="font-size:13px;"> 
Above: Code snippet demonstrating how to load and read out an ini-configuration file using <code>Zend_Config_Ini</code>. </p><br class="clear" />
<p class="wide">
Following this approach, we are now able to easily specify a default time zone value for our application that should later be used. This is our very first step to gain more independency from our server&#8217;s presets and escape the scourge of unwanted configuration locks.
</p>
<h4><span id="Let_the_user_choose_a_time_zone">Let the user choose a time zone</span></h4>
<p class="wide">
There are a lot of ways we can map a time zone to a user: We could bind this property to a user object which is available through the request lifetime for each and every signed in user, or we could create an individual settings-object, which &#8211; again &#8211; can be mapped 1:1 to a user.</p>
<p class="message_blue" style="font-size:13px;"> 
"What about guests visiting the application", you ask? Remember that we have set up a default time zone, right? You can use this value for each visitor, or you could guess the time zone, for example based on locale informations available through HTTP headers (<code>Accept-Language</code>), or by using Javascript to examine a few available client properties. Heck, you could even let a visitor choose a time zone and save this value to a cookie.
</p><br class="clear" />
<p class="wide">
For a list of available and supported time zones in PHP, you can visit <a title="list of supported time zones by PHP" href="http://de.php.net/manual/en/timezones.php" target="_blank">http://de.php.net/manual/en/timezones.php</a>. But if you want to create a drop-down box with a set of all time zones to choose from, it would be best to create this list automatically by using PHP&#8217;s native <a title="DateTimeZone object manual" href="http://de.php.net/manual/en/class.datetimezone.php" target="_blank">DateTimeZone</a> object, which is available for PHP >= 5.2:
</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="php"><pre class="de1"><span class="re0">$timezones</span> <span class="sy0">=</span> DateTimeZone<span class="sy0">::</span><span class="me2">listIdentifiers</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="kw1">for</span> <span class="br0">&#40;</span><span class="re0">$i</span><span class="sy0">=</span><span class="nu0">0</span><span class="sy0">,</span> <span class="re0">$len</span> <span class="sy0">=</span> <span class="kw3">count</span><span class="br0">&#40;</span><span class="re0">$timezones</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="re0">$i</span> <span class="sy0">&lt;</span> <span class="re0">$len</span><span class="sy0">;</span> <span class="re0">$i</span><span class="sy0">++</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> 
    <span class="kw1">echo</span> <span class="re0">$timezones</span><span class="br0">&#91;</span><span class="re0">$i</span><span class="br0">&#93;</span> <span class="sy0">.</span> <span class="st0">&quot;<span class="es1">\n</span>&quot;</span><span class="sy0">;</span> 
<span class="br0">&#125;</span></pre></div></div></div></div></div></div></div>


<p class="message_blue" style="font-size:13px;"> 
Above: Code snippet to list all time zones supported by PHP. (PHP >= 5.2 required for <code>DateTimeZone</code>).</p><br class="clear" />
<p class="wide">
The remaining work shouldn&#8217;t be too much of a challenge &#8211; we provide a settings section in our application where the user can specify the desired time zone. It&#8217;s simple as that.
</p>
<h4><span id="Set_up_the_time_zone_for_each_request">Set up the time zone for each request</span></h4>
<p class="wide">
We&#8217;re almost there &#8211; just one important step is missing: How do we tell which time zone the application should serve? Quite simple &#8211; put the application in a time zone context by applying best practices<sup class='footnote'><a href='#fn-343-3' id='fnref-343-3' onclick='return fdfootnote_show(343)'>[3]</a></sup>! And the best practice would be to call <a title="date_default_timezone_set() manual" href="http://de.php.net/manual/en/function.date-default-timezone-set.php" target="_blank">date_default_timezone_set()</a> in your bootstrapper, with the value of either the default time zone &#8211; or, if available &#8211; the user&#8217;s manually chosen time zone or the one you tried to autodetect.
</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="php"><pre class="de1"><span class="co1">// code to read out the users time zone from his settings,</span>
<span class="co1">// assuming that our user object provides a &quot;getTimezone()&quot; method</span>
<span class="re0">$timezone</span> <span class="sy0">=</span> <span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">getTimezone</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="re0">$result</span>   <span class="sy0">=</span> <span class="sy0">@</span><span class="kw3">date_default_timezone_set</span><span class="br0">&#40;</span><span class="re0">$timezone</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div></div></div></div></div></div>


<p class="message_blue" style="font-size:13px;"> 
Above: The code shows how to specify a default time zone for a request. Make sure the setting is valid during the whole request and doesn't change unintentionally. 
</p><br class="clear" /><p class="message_yellow" style="font-size:13px;"> 
We are using <code>@</code> in front of <code>date_default_timezone_set()</code> to suppress any <code>Notice</code> thrown by PHP in case the passed argument is invalid. It is up to you to add appropriate error behavior at this point.
</p><br class="clear" /><p class="message_blue" style="font-size:13px;"> 
<strong>Q:</strong> <em>I don't need to handle different time zones. I think I'm fine with adjusting the time zone in the </em><code>php.ini</code><em>, and reading it out accordingly, right?</em> 
<br />
<strong>A:</strong> Sure, go ahead, but for portability reasons it's best practice to set the default time zone manually. Once you're moving your application to another server or the <code>php.ini</code> needs to be changed regarding date/time zone settings, you'll be probably out of luck and need to implement this feature to a time when there is already a large amount of user generated dates/times spread like crazy in your data storage. 
<br />
<br />
<strong>Q:</strong> <em>I looked up the </em><code>date.timezone</code><em> setting in my</em> <code>php.ini</code><em>, but it's missing. So what timezone is my application running in if I do not set it manually?</em> 
<br />
<strong>A:</strong> It largely depends on what framework/libraries you are using, but in the most cases the default time zone is read out by calling <code>date_default_timezone_get()</code> (even <code>Zend_Date</code> uses it). According to the <a title="date_default_timezone_get() " href="http://de2.php.net/manual/en/function.date-default-timezone-get.php" target="_blank">PHP manual</a>, the timezone is determined in the following order: 
<br />
<em> <strong>*</strong> Reading the timezone set using the date_default_timezone_set() function (if any) 
<br />
<strong>*</strong> Prior to PHP 5.4.0 only: Reading the TZ environment variable (if non empty) 
<br />
<strong>*</strong> Reading the value of the date.timezone ini option (if set) 
<br />
<strong>*</strong> Prior to PHP 5.4.0 only: Querying the host operating system (if supported and allowed by the OS). This uses an algorithm that has to guess the timezone. This is by no means going to work correctly for every situation. A warning is shown when this stage is reached. Do not rely on it to be guessed correctly, and set date.timezone to the correct timezone instead. 
<br />
If none of the above succeed, date_default_timezone_get() will return a default timezone of UTC. </em> 
</p><br class="clear" /><br />
<h3><span id="The_0_meridian_for_your_data_storage">The 0 meridian for your data storage</span></h3>
<p class="wide">
We have just enhanced our application with support for serving different time zones, but how exactly would we want to store the dates/times in the underlying data storage of our application? By storing the data without any time offset<sup class='footnote'><a href='#fn-343-4' id='fnref-343-4' onclick='return fdfootnote_show(343)'>[4]</a></sup>! We use <strong>UTC</strong>/<strong>GMT</strong> as the preferred time zone for all of our date values.</p>
<p class="message_blue" style="font-size:13px;"> 
Looking at several dates marked with either GMT or UTC, users see no difference between them, so how do we distinguish them? And should we even care? Well, a fractional second difference exist between the two, but it is so small, that it won't affect your everyday work<sup class='footnote'><a href='#fn-343-5' id='fnref-343-5' onclick='return fdfootnote_show(343)'>[5]</a></sup>. To be on the safe side: Use UTC when in doubt. It means almost the same as GMT and it's kind of its modern successor. Atomic age and stuff, you know? 
</p><br class="clear" />
<p class="wide">
There are various steps involved in making sure we are putting the proper UTC date to our data storage &#8211; and to be able to serve this dates properly to different time zones:
</p>
<ul class="list list3">
<li>Choosing the MySQL data type for our dates</li>
<li>Converting user/system generated dates to UTC</li>
<li>Converting UTC dates back to a specific time zone</li>
</ul>
</ul>
<h4><span id="Choosing_the_MySQL_data_type_for_our_dates">Choosing the MySQL data type for our dates</span></h4>
<p class="wide">Storing UTC dates in our data storage boosts the (locale) portability of our software. However, we have to think about how our dates will be stored. We will take a look at two common alternatives:
</p>
<ul class="list list3">
<li>Saving dates and times as Unix timestamps</li>
<li>Saving dates and times in a <code>datetime</code> field</li>
</ul>
<p class="wide">
Both of them have advantages and disadvantages:
</p>
<h5><span id="Unix_Timestamp">Unix Timestamp</span></h5>
<p class="wide">
A Unix timestamp is an integer value which represents the elapsed seconds since <code>1970-01-01 00:00:00(GMT)</code>. This is the so called &#8220;Unix Epoch&#8221;. On 32-bit systems, the valid range of values reach from <code>1970-01-01 00:00:00 UTC</code> to <code>2038-01-19 03:14:07 UTC</code> (the upper limit denoted by the year 2038 is commonly referred to as the <a title="The Y2K38 problem" href="http://en.wikipedia.org/wiki/Year_2038_problem" target="_blank">Year 2038 problem</a>). The short range of 68 years which can be represented by unsigned 32-bit timestamps and the fact that you cannot use dates before 1970 (except for 64-bit systems where Unix timestamps are stored as signed 64-bit integers, or on most 32-bit systems where timestamps are stored as signed integers, supporting a range from <code>1901-12-13 20:45:54 UTC</code> to <code>2038-01-19 03:14:07 UTC</code>) narrows the use cases for timestamps somewhat down<sup class='footnote'><a href='#fn-343-6' id='fnref-343-6' onclick='return fdfootnote_show(343)'>[6]</a></sup>.</p>
<p class="message_yellow" style="font-size:13px;">
An operating system with support for signed 32-bit timestamps should be one of the prerequisites for our application in this case. Since PHP made <code>date_default_timezone_set()</code> available with version 5.1.0, and this version fixed some issues with supporting only unsigned integers on some 32-bit systems when working with timestamps, this is mandatory.
</p><br class="clear" /><p class="wide">
However, when dealing with &#8220;transient&#8221; dates, such as dates belonging to log entries or such, timestamps are proven to work. Oh, and it&#8217;s hard to figure out what date exactly a 4-byte long value represents without doing some good old math, don&#8217;t you think?<sup class='footnote'><a href='#fn-343-7' id='fnref-343-7' onclick='return fdfootnote_show(343)'>[7]</a></sup></p>
<p class="message_blue" style="font-size:13px;"> 
Unix timestamps are UTC dates. This means: They do not provide any offset to another timezone. You can simply add or subtract the needed offset in seconds from the timestamp<sup class='footnote'><a href='#fn-343-8' id='fnref-343-8' onclick='return fdfootnote_show(343)'>[8]</a></sup>. Et voilá - you have your localized date.
</p><br class="clear" /><p class="message_yellow" style="font-size:13px;">
Working with PHP on a 64-bit OS and using its functions to generate Unix timestamps? Beware, as timestamp-related functions in MySQL are not (yet) taking advantage of the large range of dates 64-bit timestamps can represent. See <a href="http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_unix-timestamp" title="MySQL UNIX_TIMESTAMP" target="_blank">the manual</a> for more information. If you want to store 64-bit timestamps in a MySQL table, make sure you do choose the appropriate data type for the column and do not need to rely on any MySQL timestamp-related functions for generating or comparing the therein stored values.
</p><br class="clear" /><h5><span id="datetime_Fields">datetime Fields</span></h5>
<p class="wide">
<code>datetime</code> fields in MySQL require dates to be in the format <code>YYYY-MM-dd HH:mm:ss</code> (example: <code>1999-05-03 20:15:00</code>) which makes it not only perfect readable, but also allows for complex date calculations by using MySQL&#8217;s built in functionality. The supported range for <code>datetime</code> values is <code>1000-01-01 00:00:00</code> to <code>9999-12-31 23:59:59</code>. This covers a wide range of dates<sup class='footnote'><a href='#fn-343-9' id='fnref-343-9' onclick='return fdfootnote_show(343)'>[9]</a></sup> and is perfect for storing UTC datetime values.</p>
<p class="message_blue" style="font-size:13px;">
Read more about MySQL's <code>datetime</code> <a title="MySQL's datetime manual" href="http://dev.mysql.com/doc/refman/5.0/en/datetime.html" target="_blank">here</a>.
</p><br class="clear" /><p class="message_yellow" style="font-size:13px;"> 
Beware of using MySQL's date calculation-functions which rely upon timezone settings, such as <a href="http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_now">NOW()</a>, as computed results will depend on the time zone settings of the host system the method gets called on. You will find more information about MySQL time zone settings <a href="http://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html">here</a>. 
</p><br class="clear" /><p class="message_blue" style="font-size:13px;">
For another point of view regarding Unix timestamps and <code>datetime</code> fields in MySQL databases, see <a href="http://billauer.co.il/blog/2009/03/mysql-datetime-epoch-unix-time/" target="_blank">this post by Eli Billauer</a>. 
</p><br class="clear" /><h4><span id="Getting_that_UTC_date_ready_for_Mysql">Getting that UTC date ready for Mysql</span></h4>
<p class="wide">
Since we&#8217;ve decided to store only UTC dates in our database, we go now back to <code>Zend_Date</code> and take a look at how we convert any date string to UTC date.
</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="php"><pre class="de1"><span class="co1">// we assume that the variable $date holds the date we want to add in </span>
<span class="co1">// UTC to the data storage </span>
<span class="co1">// the following works with date formats that include time zone offsets,</span>
<span class="co1">// e.g. Fri, 19 Jan 2007 22:08:13 +0100 (CET) </span>
<span class="co1">// read out the currently used timezone </span>
<span class="re0">$date</span>    <span class="sy0">=</span> <span class="st_h">'Fri, 19 Jan 2007 22:08:13 +0100 (CET)'</span><span class="sy0">;</span>
<span class="re0">$oldZone</span> <span class="sy0">=</span> <span class="kw3">date_default_timezone_get</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="co1">// set the new timezone to UTC to give PHP a hint what strtotime() has to </span>
<span class="co1">// do </span>
<span class="kw3">date_default_timezone_set</span><span class="br0">&#40;</span><span class="st_h">'UTC'</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="kw3">assert</span><span class="br0">&#40;</span><span class="kw3">date_default_timezone_get</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">===</span> <span class="st_h">'UTC'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// strtotime() is much more forgiving to date strings which </span>
<span class="co1">// do not comply to the exact standard </span>
<span class="re0">$dvalue</span> <span class="sy0">=</span> <span class="sy0">@</span><span class="kw3">strtotime</span><span class="br0">&#40;</span><span class="re0">$date</span><span class="br0">&#41;</span><span class="sy0">;</span> 
&nbsp;
<span class="co1">// reset default timezone to previous value </span>
<span class="kw3">date_default_timezone_set</span><span class="br0">&#40;</span><span class="re0">$oldZone</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="kw3">assert</span><span class="br0">&#40;</span><span class="kw3">date_default_timezone_get</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">===</span> <span class="re0">$oldZone</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// get back to Zend Date </span>
<span class="re0">$dateObject</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Date<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> 
try <span class="br0">&#123;</span> 
    <span class="re0">$dateObject</span><span class="sy0">-&gt;</span><span class="me1">set</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="re0">$dvalue</span> <span class="sy0">===</span> <span class="kw4">false</span> ? <span class="re0">$date</span> <span class="sy0">:</span> <span class="re0">$dvalue</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="br0">&#125;</span> catch <span class="br0">&#40;</span>Zend_Date_Exception <span class="re0">$e</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> 
     <span class="co1">// fall back to default date to have a value at last</span>
     <span class="re0">$dateObject</span><span class="sy0">-&gt;</span><span class="me1">set</span><span class="br0">&#40;</span><span class="st_h">'1970-01-01 00:00:00'</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="br0">&#125;</span> 
<span class="re0">$dateObject</span><span class="sy0">-&gt;</span><span class="me1">setTimezone</span><span class="br0">&#40;</span><span class="st_h">'UTC'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$result</span> <span class="sy0">=</span> <span class="re0">$dateObject</span><span class="sy0">-&gt;</span><span class="me1">get</span><span class="br0">&#40;</span><span class="st_h">'YYYY-MM-dd HH:mm:ss'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">assert</span><span class="br0">&#40;</span><span class="re0">$result</span> <span class="sy0">===</span> <span class="st_h">'2007-01-19 21:08:13'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">echo</span> <span class="re0">$result</span><span class="sy0">;</span></pre></div></div></div></div></div></div></div>


<p class="message_blue" style="font-size:13px;"> 
Above: Code snippet for converting a date of any time zone to a UTC date. 
</p><br class="clear" />
<p class="wide">
Note our first call to <code>strtotime()</code>. This is a native PHP function which is much more forgiving than <code>Zend_Date</code> when it comes to parsing date strings which do not comply to international standards. However, <code>strtotime()</code> can fail, and if it does, we delegate the parsing of the date to <code>Zend_Date</code>. It does not use <code>strtotime()</code> itself, but instead tokenizes the passed string for gathering all the information it needs. It even uses the BC Math extension (if available), which comes quite handy in case <code>strtotime()</code> failed with a date which is out of bounds. We&#8217;ll get to that later.</p>
<p class="message_yellow" style="font-size:13px;"> 
<strong>A:</strong> So if <code>strtotime()</code> does a better job when it comes to parsing malformed dates, why doesn't <code>Zend_Date</code> use it? 
</br />
<strong>Q:</strong> Remember what we've just learned about the limited range of dates you can represent with a timestamp? If you specify a date before 1901 or after 2038 in the above example, you're most likely to fail on systems where PHP supports timestamps only as (signed) 32-bit integer. <strong>If your use case includes the option of handling dates prior to 1901 or after 2038, do not rely on</strong> <code>strtotime()</code><strong> and use only </strong><code>Zend_Date</code><strong>!</strong>
Although it uses <a href="http://php.net/manual/en/function.mktime.php" title="mktime() manual page" target="_blank">mktime()</a> itself as long as the year is in between 1901 and 2038, it is able to fall back to internal calculations as soon as this value is out of bounds. See also the answer to the next question.
</strong>
<br />
<br />
<strong>Q:</strong> I've read that <code>Zend_Date</code> <a href="http://framework.zend.com/manual/en/zend.date.definition.theory.html" title="Zend_Date - Theory of operation" target="_blank">works internally with timestamps</a>. If the range of dates which timestamps can represent is limited, what kind of workaround does <code>Zend_Date</code> use itself?
<br />  
<strong>A:</strong> None. Well, at least not directly. On 32-bit systems, timestamps represented as signed 32-bit integers (which we assume to be the lowest common denominator for our target system), can work with dates ranging from <code>1901-12-13</code> to <code>2038-01-19</code> (+ a few hours). Zend Framework suggests to make the <a href="http://de3.php.net/bc" title="BC Math extension manual page" target="_blank">BC Math extension</a> available to your PHP installation if you want to support dates which are outside of this range.<sup class='footnote'><a href='#fn-343-10' id='fnref-343-10' onclick='return fdfootnote_show(343)'>[10]</a></sup>
</p><br class="clear" />
<p class="wide">
If parsing the date failed, we catch the exception and fall back to a default value of <code>1970-01-01 00:00:00</code>, but it&#8217;s up to you if you let the exception bubble up or replace the date with any value you want. It mainly depends on your use case and how sensitive your data is to wrong date values<sup class='footnote'><a href='#fn-343-11' id='fnref-343-11' onclick='return fdfootnote_show(343)'>[11]</a></sup>.<br />
The last step is to put <code>Zend_Date</code> into the UTC timezone, and &#8211; based on that &#8211; convert the string to the format <code>YYYY-MM-dd HH:mm:ss</code>, which is the required format for MySQL <code>datetime</code> fields.<br />
Let&#8217;s go back to <code>strtotime()</code> for a second. You should&#8217;ve noted that we temporarily set another timezone (UTC) so the internal date conversion knows what kind of output we excpect.<br />
This might confuse you at first, so let&#8217;s go through it in detail: Let&#8217;s assume we have the following date that needs to be converted to UTC: <code>Fri, 19 Jan 2007 22:08:13 +0100 (CET)</code>. The last part of the string includes the offset to the UTC time zone &#8220;<code>+0100 (CET)</code>&#8221; (means: CET is 1 hour ahead of UTC when no DST is available, otherwise it would be + 2 hrs), and the first part &#8220;<code>Fri, 19 Jan 2007 22:08:13</code>&#8221; is actually the local date that should be put into the UTC time zone and stored to the data storage. By telling <code>strtotime()</code> it should generate a Unix timestamp from that date and setting the default timezone to UTC, the offset is calculated against the local date. If, however, you&#8217;d set the default timezone to <code>America/Los_Angeles</code>, the offset to UTC (-08:00) for this time zone (PST) is computed against the UTC date of the local date. See a few examples:
</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="php"><pre class="de1"><span class="co1">// show which timezone our script runs in </span>
<span class="kw1">echo</span> <span class="kw3">date_default_timezone_get</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">.</span> <span class="st0">&quot;<span class="es1">\n</span>&quot;</span><span class="sy0">;</span> 
<span class="co1">// outputs the converted date, depending on the timezone initially set </span>
<span class="kw1">echo</span> <span class="st0">&quot;1: &quot;</span><span class="sy0">.</span><span class="kw3">date</span><span class="br0">&#40;</span><span class="st0">&quot;Y-m-d H:i:s&quot;</span><span class="sy0">,</span> <span class="kw3">strtotime</span><span class="br0">&#40;</span><span class="st_h">'Fri, 19 Nov 2007 22:08:13 +0100 (CET)'</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">.</span> <span class="st0">&quot;<span class="es1">\n</span>&quot;</span><span class="sy0">;</span> 
&nbsp;
<span class="co1">// lets have a look at DST. Set the timezone to a value of which we know</span>
<span class="co1">// that it uses DST</span>
<span class="kw3">date_default_timezone_set</span><span class="br0">&#40;</span><span class="st_h">'Europe/Berlin'</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="kw3">assert</span><span class="br0">&#40;</span><span class="kw3">date_default_timezone_get</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">===</span> <span class="st_h">'Europe/Berlin'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// no DST from end of Okt to end of March in Europe/Berlin,</span>
<span class="co1">// so the following will output 2007-01-19 22:08:13</span>
<span class="re0">$d</span> <span class="sy0">=</span> <span class="kw3">date</span><span class="br0">&#40;</span><span class="st0">&quot;Y-m-d H:i:s&quot;</span><span class="sy0">,</span> <span class="kw3">strtotime</span><span class="br0">&#40;</span><span class="st_h">'Fri, 19 Jan 2007 22:08:13 +0100 (CET)'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">assert</span><span class="br0">&#40;</span><span class="re0">$d</span> <span class="sy0">===</span> <span class="st_h">'2007-01-19 22:08:13'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">echo</span> <span class="st0">&quot;2: <span class="es4">$d</span> <span class="es1">\n</span>&quot;</span><span class="sy0">;</span> 
&nbsp;
<span class="co1">// summertime, i.e. CEST in Europe/Berlin, for example during August</span>
<span class="co1">// the following will output 2007-08-19 23:08:13, since the timezone is specified </span>
<span class="co1">// as CET, but during August, DST is active, so 1 hour wil be added </span>
<span class="re0">$d</span> <span class="sy0">=</span> <span class="kw3">date</span><span class="br0">&#40;</span><span class="st0">&quot;Y-m-d H:i:s&quot;</span><span class="sy0">,</span> <span class="kw3">strtotime</span><span class="br0">&#40;</span><span class="st_h">'Sun, 19 Aug 2007 22:08:13 +0100 (CET)'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">assert</span><span class="br0">&#40;</span><span class="re0">$d</span> <span class="sy0">===</span> <span class="st_h">'2007-08-19 23:08:13'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">echo</span> <span class="st0">&quot;3: <span class="es4">$d</span> <span class="es1">\n</span>&quot;</span><span class="sy0">;</span> 
&nbsp;
<span class="co1">// now specify CEST as a timezone - this tells that the date is in Central European </span>
<span class="co1">// Summer Time (2 hrs ahead of UTC)</span>
<span class="co1">// the output will be 2007-08-19 22:08:13</span>
<span class="re0">$d</span> <span class="sy0">=</span> <span class="kw3">date</span><span class="br0">&#40;</span><span class="st0">&quot;Y-m-d H:i:s&quot;</span><span class="sy0">,</span> <span class="kw3">strtotime</span><span class="br0">&#40;</span><span class="st_h">'Sun, 19 Aug 2007 22:08:13 +0200 (CEST)'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">assert</span><span class="br0">&#40;</span><span class="re0">$d</span> <span class="sy0">===</span> <span class="st_h">'2007-08-19 22:08:13'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">echo</span> <span class="st0">&quot;4: <span class="es4">$d</span> <span class="es1">\n</span>&quot;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// changing the timezone to UTC </span>
<span class="kw3">date_default_timezone_set</span><span class="br0">&#40;</span><span class="st_h">'UTC'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">assert</span><span class="br0">&#40;</span><span class="kw3">date_default_timezone_get</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">===</span> <span class="st_h">'UTC'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// ouputs 2007-01-19 21:08:13, the date converted to UTC time zone </span>
<span class="re0">$d</span> <span class="sy0">=</span> <span class="kw3">date</span><span class="br0">&#40;</span><span class="st0">&quot;Y-m-d H:i:s&quot;</span><span class="sy0">,</span> <span class="kw3">strtotime</span><span class="br0">&#40;</span><span class="st_h">'Fri, 19 Jan 2007 22:08:13 +0100 (CET)'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">echo</span> <span class="st0">&quot;5: <span class="es4">$d</span> <span class="es1">\n</span>&quot;</span><span class="sy0">;</span> 
<span class="kw3">assert</span><span class="br0">&#40;</span><span class="re0">$d</span> <span class="sy0">===</span> <span class="st_h">'2007-01-19 21:08:13'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// changing the timezone to America/Los_Angeles</span>
<span class="kw3">date_default_timezone_set</span><span class="br0">&#40;</span><span class="st_h">'America/Los_Angeles'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">assert</span><span class="br0">&#40;</span><span class="kw3">date_default_timezone_get</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">===</span> <span class="st_h">'America/Los_Angeles'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// outputs 2007-01-19 13:08:13, the specified date in the time </span>
<span class="co1">// zone of Los Angeles (America) </span>
<span class="co1">// calculate UTC date: </span>
<span class="co1">// (Fri, 19 Jan 2007 22:08:13 - (+01:00)) =  Fri, 19 Jan 2007 21:08:13 +00:00 (UTC)</span>
<span class="co1">// now substract 08:00 (PST is 8 hrs behind UTC) from the UTC date</span>
<span class="co1">// (Fri, 19 Jan 2007 21:08:13 +00:00 (UTC)) - (08:00)) </span>
<span class="co1">// == Fri, 19 Jan 2007 13:08:13 -08:00 (PST)   </span>
<span class="re0">$d</span> <span class="sy0">=</span> <span class="kw3">date</span><span class="br0">&#40;</span><span class="st0">&quot;Y-m-d H:i:s&quot;</span><span class="sy0">,</span> <span class="kw3">strtotime</span><span class="br0">&#40;</span><span class="st_h">'Fri, 19 Jan 2007 22:08:13 +0100 (CET)'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">echo</span> <span class="st0">&quot;6:  <span class="es4">$d</span> <span class="es1">\n</span>&quot;</span><span class="sy0">;</span>
<span class="kw3">assert</span><span class="br0">&#40;</span><span class="re0">$d</span> <span class="sy0">===</span> <span class="st_h">'2007-01-19 13:08:13'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// test this the same way around:</span>
<span class="kw3">date_default_timezone_set</span><span class="br0">&#40;</span><span class="st_h">'Europe/Berlin'</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="kw3">assert</span><span class="br0">&#40;</span><span class="kw3">date_default_timezone_get</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">===</span> <span class="st_h">'Europe/Berlin'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// outputs 2007-01-19 22:08:13</span>
<span class="re0">$d</span> <span class="sy0">=</span> <span class="kw3">date</span><span class="br0">&#40;</span><span class="st0">&quot;Y-m-d H:i:s&quot;</span><span class="sy0">,</span> <span class="kw3">strtotime</span><span class="br0">&#40;</span><span class="st_h">'Fri, 19 Jan 2007 13:08:13 -08:00 (PST)'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">echo</span> <span class="st0">&quot;7: <span class="es4">$d</span> <span class="es1">\n</span>&quot;</span><span class="sy0">;</span>
<span class="kw3">assert</span><span class="br0">&#40;</span><span class="re0">$d</span> <span class="sy0">===</span> <span class="st_h">'2007-01-19 22:08:13'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// Output generated:</span>
<span class="co1">// [your timezone]</span>
<span class="co1">// 1: [date based on your time zone]</span>
<span class="co1">// 2: 2007-01-19 22:08:13</span>
<span class="co1">// 3: 2007-08-19 23:08:13</span>
<span class="co1">// 4: 2007-08-19 22:08:13</span>
<span class="co1">// 5: 2007-01-19 21:08:13</span>
<span class="co1">// 6: 2007-01-19 13:08:13</span>
<span class="co1">// 7: 2007-01-19 22:08:13</span></pre></div></div></div></div></div></div></div>


<p class="message_blue" style="font-size:13px;"> 
Above: code snippet to illustrate the interaction between default time zones and <code>strtotime()</code>. The comments explain how the calculation works. If you want to know more about this, follow <a href="http://www.cl.cam.ac.uk/~mgk25/iso-time.html" title="A summary of the international standard date and time notation" target="_blank">this link</a>.
<br />
</p><br class="clear" /><p class="message_blue" style="font-size:13px;"> 
<strong>Rule of thumb</strong>: <code>local date - ((-/+)time offset) = UTC date</code>
</p><br class="clear" />
<p class="wide">
It&#8217;s quite easy once you get the hang of it. The most important part is to relate to UTC all the time, and simply take the offsets of other time zones into account during converting. By using the UTC timezone, you can safely and easily display them in other time zones.</p>
<p class="message_blue" style="font-size:13px;"> 
<strong>Q:</strong> When specifying the input date - why are we neither <code>strtotime()</code> nor <code>Zend_Date</code> telling which timezone it belongs to? 
<br />
<code>A:</code> Because we want PHP/Zend do the heavy lifting for us. See, sometimes we deal with date strings that come from resources we do not control, such as dates in email headers <sup class='footnote'><a href='#fn-343-12' id='fnref-343-12' onclick='return fdfootnote_show(343)'>[12]</a></sup>. Parsing a date string by hand involves a lot of work which was (thankfully) already done by other programmers, and this functionality is given to us by <code>strtotime()</code>/<code>Zend_Date</code>. You can, however, do a syntax check beforehand and disallow parsing for any date that looks fishy, e.g. if no offset information can be found. 
<br />
<strong>Q:</strong> So what happens if there is no additional time zone information in the string I pass to <code>strtotime()</code> or <code>Zend_Date</code>? 
<br />
<strong>A:</strong> In this case, both functions will fall back to the default time zone previously set with <code>date_default_timezone_set()</code>. 
</p><br class="clear" /><br />
<h3><span id="Being_soft_and_flexible">Being soft and flexible</span></h3>
<p class="wide">
Now that you have prepared your application to store UTC dates in the format <code>YYYY-MM-dd HH:mm:ss</code>, you are able to display them properly based on the time zone you have specified by using <code>date_default_timezone_set()</code>. We return to <code>Zend_Date</code> now to convert UTC dates to the default time zone cosen by you or your application&#8217;s user, as mentioned above.
</p>
<p class="wide">
Let&#8217;s first have a look at an error-prone solution and see why this is not the right way to do it:
</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="php"><pre class="de1"><span class="co1">//creating Zend_Date and pass our datetime value from the data storage to </span>
<span class="co1">// the constructor </span>
<span class="re0">$dateObject</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Date<span class="br0">&#40;</span><span class="st_h">'2007-01-19 14:08:13'</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="kw1">echo</span> <span class="re0">$date</span><span class="sy0">-&gt;</span><span class="me1">get</span><span class="br0">&#40;</span><span class="st_h">'YYYY-MM-dd HH:mm:ss'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div></div></div></div></div></div>


<p class="message_red" style="font-size:13px;"> 
Above: Code snippet demonstrating how <code>Zend_Date</code> should not be used when converting <code>datetime</code> values to the application's time zone. 
</p><br class="clear" />
<p class="wide">
So why is this wrong? Well, first off we&#8217;re simply passing a string to <code>Zend_Date</code> which provides no further information about its time zone, and therefor its offset (remember our date string &#8220;<code>Fri, 19 Jan 2007 22:08:13 +0100 (CET)</code>&#8220;? The timezone and offset information at its end helps functions like <code>strtotime()</code> when they look for any additional information for which region in the world the date was created for). Thus, <code>Zend_Date</code> will fall back to the timezone it has detected when it internally queried the return value of <code>date_default_timezone_get()</code>, and uses this value for converting.<br />
Secondly, we&#8217;re not specifying the target time zone the date should be converted to. Guess what? By echoing the return value of <code>Zend_date::get()</code> in this case, the converted value will be the same as the value we just passed to <code>Zend_Date::__construct()</code> (whereas getting the same value is not an error: This happens when an input date with zero offset is converted to a timezone which in turn does not have an offset itself<sup class='footnote'><a href='#fn-343-13' id='fnref-343-13' onclick='return fdfootnote_show(343)'>[13]</a></sup>).<br />
Let&#8217;s have a look at another example:
</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="php"><pre class="de1"><span class="co1">//create Zend_Date and pass the datetime value to the constructor</span>
<span class="re0">$dateObject</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Date<span class="br0">&#40;</span><span class="st_h">'2007-01-19 14:08:13'</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="co1">// set the time zone </span>
<span class="re0">$dateObject</span><span class="sy0">-&gt;</span><span class="me1">setTimezone</span><span class="br0">&#40;</span>date_timezone_default_get<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="kw1">echo</span> <span class="re0">$dateObject</span><span class="sy0">-&gt;</span><span class="me1">get</span><span class="br0">&#40;</span><span class="st_h">'YYYY-mm-dd HH:ii:ss'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div></div></div></div></div></div>


<p class="message_red" style="font-size:13px;">
Above: Code snippet demonstrates how <code>Zend_Date</code> should not be used when converting UTC <code>datetime</code> values to the application's time zone. 
</p><br class="clear" />
<p class="wide">
Well, we&#8217;re not doing anything different here, are we? We simply do a call to <code>Zend_Date::setTimezone()</code> to set the <code>Zend_Date</code>-object to the time zone it was already set to. It already checks the value of <code>date_timezone_default_get()</code> internally. Relax. Take a break. And then have a look at a working example.
</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="php"><pre class="de1"><span class="co1">// create Zend_Date object </span>
<span class="re0">$dateObject</span> <span class="sy0">=</span> <span class="kw2">new</span> Zend_Date<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="co1">// put the Date_Object into the UTC time zone </span>
<span class="re0">$dateObject</span><span class="sy0">-&gt;</span><span class="me1">setTimezone</span><span class="br0">&#40;</span><span class="st_h">'UTC'</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="co1">// set the UTC date the date object must work with </span>
<span class="re0">$dateObject</span><span class="sy0">-&gt;</span><span class="me1">set</span><span class="br0">&#40;</span><span class="st_h">'2007-01-19 14:08:13'</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="co1">// now, set the time zone of the object to the time zone our application runs in </span>
<span class="re0">$dateObject</span><span class="sy0">-&gt;</span><span class="me1">setTimezone</span><span class="br0">&#40;</span><span class="kw3">date_default_timezone_get</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span> 
<span class="co1">// display the UTC date converted to our time zone </span>
<span class="kw1">echo</span> <span class="re0">$dateObject</span><span class="sy0">-&gt;</span><span class="me1">get</span><span class="br0">&#40;</span><span class="st_h">'YYYY-MM-dd HH:mm:ss'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div></div></div></div></div></div>


<p class="message_green" style="font-size:13px;"> 
Above: Code snippet to illustrate how to convert UTC datetime values to a specific time zone using <code>Zend_Date</code>. 
</p><br class="clear" /><p class="message_blue" style="font-size:13px;"> 
<strong>Q:</strong> Can't <code>Zend_Date</code> just guess which timezone the string belongs to?
<br />
<strong>A:</strong> No, that won't work, since there is no information about the time zone offset in a <code>YYYY-MM-dd HH:mm:ss</code>-formatted date string. We know that it's a UTC date, but we have to forward this information to <code>Zend_Date</code>.
</p><br class="clear" /><br />
<h3><span id="Wrapping_things_up">Wrapping things up</span></h3>
<p class="wide">
Adding time zone support to your PHP application isn&#8217;t too much of a hassle, and not only will the user benefit from it, but so do you by eliminating a potential source for errors.<br />
There aren&#8217;t too many steps involved in adding time zone support, and it&#8217;s best done at a very early implementation cycle to spare you the problems that occur when persisted data has to be converted back to UTC if you do not know which time zones the dates originally belong to.
</p>
<p class="wide">
As mentioned earlier &#8211; if you need to make your code work on each and every (32-bit) OS where PHP is available and you need to consider those OSs where PHP only supports unsigned 32-bit timestamps, you need to check whether dates which get processed with PHP internal functions are in between <code>1970-01-01</code> and <code>2038-01-19</code>. In this case, you have to use a different approach than the one this article is about, since <code>Zend_Date</code> assumes that your target system supports at least signed 32-bit integers when working time related functions (PHP supporting only timestamps as unsigned 32-bit timestamps is a known problem which has been fixed since 5.1.0).<br />
An additional &#8220;soft&#8221; approach when deploying your application would be to require the availability of the BC Math extension, so <code>Zend_Date</code> can take advantage of it.<br />
The best configuration for a PHP system that covers a large range of dates would be a 64-bit OS. Your webpage should be guaranteed to run even in the far away future.
</p>
<p class="wide">
Oh, and did I mention the Unit Tests you should write for your date manipulating functions to get started in the first place?<br />
Happy PHPing!</p>
<div class="hr_shadow" /></div><div class='footnotes' id='footnotes-343'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-343-1'>They were specially excited about phone calls during the weekends when their division manager would ask them to check a document for them. Write once, run anywhere. <span class='footnotereverse'><a href='#fnref-343-1'>&#8617;</a></span></li>
<li id='fn-343-2'>You are an agilist, aren&#8217;t you? <span class='footnotereverse'><a href='#fnref-343-2'>&#8617;</a></span></li>
<li id='fn-343-3'>They are proven to work <span class='footnotereverse'><a href='#fnref-343-3'>&#8617;</a></span></li>
<li id='fn-343-4'>You remember that 8 hour offset from San Francisco &#8211; London that ended up in the data storage? You don&#8217;t want that! <span class='footnotereverse'><a href='#fnref-343-4'>&#8617;</a></span></li>
<li id='fn-343-5'>Should you be working for the <a href="http://en.wikipedia.org/wiki/Large_Hadron_Collider">LHC</a>, then the fractional second difference should definitely matter to you. <span class='footnotereverse'><a href='#fnref-343-5'>&#8617;</a></span></li>
<li id='fn-343-6'>Think about birthdates. Even Facebook&#8217;s userbase does not only exist of people like &#8220;awesomesauce_1988&#8243; and the like <span class='footnotereverse'><a href='#fnref-343-6'>&#8617;</a></span></li>
<li id='fn-343-7'>Unless your first name is Sheldon and you tend to embrace your genius to the fullest <span class='footnotereverse'><a href='#fnref-343-7'>&#8617;</a></span></li>
<li id='fn-343-8'>Assuming you converted the date to a timestamp properly <span class='footnotereverse'><a href='#fnref-343-8'>&#8617;</a></span></li>
<li id='fn-343-9'>Watch out, PHP programmers working in history-related institutions! <span class='footnotereverse'><a href='#fnref-343-9'>&#8617;</a></span></li>
<li id='fn-343-10'>Take a look at <code>Zend_Locale_Math</code> to understand how <code>Zend_Date</code> utilizes <code>BC Math</code> <span class='footnotereverse'><a href='#fnref-343-10'>&#8617;</a></span></li>
<li id='fn-343-11'>Ever wondered how these emails from 1970 end up in your inbox? <span class='footnotereverse'><a href='#fnref-343-11'>&#8617;</a></span></li>
<li id='fn-343-12'>How many email clients do you know, and how many of them are <strong>looking out</strong> to push their own proprietary standard through? <span class='footnotereverse'><a href='#fnref-343-12'>&#8617;</a></span></li>
<li id='fn-343-13'>London Calling <span class='footnotereverse'><a href='#fnref-343-13'>&#8617;</a></span></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://thorsten.suckow-homberg.de/2011/11/17/zend_date-default-timezones-and-dst/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>How conjoon migrated quickly from Trac to JIRA</title>
		<link>http://thorsten.suckow-homberg.de/2011/11/10/how-conjoon-quickly-migrated-from-trac-to-jira/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-conjoon-quickly-migrated-from-trac-to-jira</link>
		<comments>http://thorsten.suckow-homberg.de/2011/11/10/how-conjoon-quickly-migrated-from-trac-to-jira/#comments</comments>
		<pubDate>Thu, 10 Nov 2011 11:12:25 +0000</pubDate>
		<dc:creator>Thorsten Suckow-Homberg</dc:creator>
				<category><![CDATA[conjoon]]></category>
		<category><![CDATA[Hacks]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://thorsten.suckow-homberg.de/?p=300</guid>
		<description><![CDATA[conjoon is currently being migrated to the Atlassian&#8217;s software suite: Jira, Confluence, Crowd, Fisheye&#8230; you name it. While the Trac importer that comes with Jira worked out of the box, I had to do some work to set all previously by Trac defined relations properly up. I also had to add dates to the ticket workflow by hand, but I&#8217;m pretty sure it was worth it: Jira is a powerful issue tracker and with all the integration points spread among ...]]></description>
			<content:encoded><![CDATA[<p>conjoon is currently being migrated to the <a href="http://www.atlassian.com">Atlassian&#8217;s</a> software suite: <a href="http://www.atlassian.com/software/jira">Jira</a>, <a href="http://www.atlassian.com/software/confluence">Confluence</a>, <a href="http://www.atlassian.com/software/crowd">Crowd</a>, <a href="http://www.atlassian.com/software/fisheye">Fisheye</a>&#8230; you name it. While the <a href="http://trac.edgewall.org">Trac</a> importer that comes with Jira worked out of the box, I had to do some work to set all previously by Trac defined relations properly up. I also had to add dates to the ticket workflow by hand, but I&#8217;m pretty sure it was worth it: Jira is a powerful issue tracker and with all the integration points spread among the Atlassian software products each tool is plugged and connected to another one. Simply great if you want to do code reviews, create release notes, share content from the issue tracker with the confluence wiki and so on.</p>
<p>However, one last thing I wanted to do is to enable to show the source activity for all the tickets and revisions that were processed when we used Trac as our wiki/issue tracker. An easy task if you think about changing ticket relations within the database (i.e. transform #{TICKETNUMBER} to {PROJECTKEY}-{TICKETNUMBER}), but if you want to update the commit messages in the repository, too &#8211; it gets ugly. Or at least you&#8217;re in danger  getting your hands dirty. Here&#8217;s what I did to change all the commit messages in conjoon&#8217;s repository to match Jira conventions:</p>


<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="bash"><pre class="de1"><span class="co4">console:/# </span><span class="kw2">svn co</span> file:<span class="sy0">///</span>repository</pre></div></div></div></div></div></div></div>


<p class="message_blue" style="font-size:13px;">Do a checkout of your repository. Use the file-Protocol for performance reason.</p><br class="clear" />

<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="bash"><pre class="de1"><span class="co4">console:/# </span><span class="kw2">svn log</span> <span class="re5">-v</span> <span class="re5">--xml</span> <span class="sy0">&gt;</span> logfile.log</pre></div></div></div></div></div></div></div>


<p class="message_blue" style="font-size:13px;">Next, fetch all the log-information out of the working copy, and save it to a file.</p><br class="clear" />

<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="php"><pre class="de1"><span class="kw2">&lt;?php</span>
<span class="re0">$file</span> <span class="sy0">=</span> <span class="st0">&quot;./logfile.log&quot;</span><span class="sy0">;</span>
<span class="re0">$dir</span> <span class="sy0">=</span> <span class="st0">&quot;./&quot;</span><span class="sy0">;</span>
<span class="re0">$xml</span>     <span class="sy0">=</span> <span class="kw3">simplexml_load_string</span><span class="br0">&#40;</span><span class="kw3">file_get_contents</span><span class="br0">&#40;</span><span class="re0">$file</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$tickets</span> <span class="sy0">=</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">for</span> <span class="br0">&#40;</span><span class="re0">$i</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> <span class="re0">$i</span> <span class="sy0">&lt;</span> <span class="nu0">1500</span><span class="sy0">;</span> <span class="re0">$i</span><span class="sy0">++</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="re0">$tickets</span><span class="br0">&#91;</span><span class="st_h">'#'</span><span class="sy0">.</span><span class="re0">$i</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="st_h">'CN-'</span><span class="sy0">.</span><span class="re0">$i</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$xml</span> <span class="kw1">as</span> <span class="re0">$tag</span> <span class="sy0">=&gt;</span> <span class="re0">$data</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$tag</span> <span class="sy0">==</span> <span class="st_h">'logentry'</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="re0">$revision</span> <span class="sy0">=</span> <span class="re0">$data</span><span class="sy0">-&gt;</span><span class="me1">attributes</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">revision</span><span class="sy0">;</span>
        <span class="re0">$msg</span> <span class="sy0">=</span> <span class="br0">&#40;</span>string<span class="br0">&#41;</span><span class="re0">$data</span><span class="sy0">-&gt;</span><span class="me1">children</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">msg</span><span class="sy0">;</span>
        <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">strpos</span><span class="br0">&#40;</span><span class="re0">$msg</span><span class="sy0">,</span> <span class="st_h">'#'</span><span class="br0">&#41;</span> <span class="sy0">!==</span> <span class="kw4">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            <span class="re0">$msg</span> <span class="sy0">=</span> <span class="kw3">str_replace</span><span class="br0">&#40;</span><span class="kw3">array_keys</span><span class="br0">&#40;</span><span class="re0">$tickets</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw3">array_values</span><span class="br0">&#40;</span><span class="re0">$tickets</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="re0">$msg</span><span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="kw3">file_put_contents</span><span class="br0">&#40;</span><span class="re0">$dir</span> <span class="sy0">.</span><span class="st_h">'/r'</span><span class="sy0">.</span><span class="re0">$revision</span><span class="sy0">,</span> <span class="re0">$msg</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div></div></div></div></div></div>


<p class="message_blue" style="font-size:13px;">I used this PHP snippet to transform the xml data to individual files, each holding the commit message for the revision indicated by the file name. If you want to use this script, make sure you're setting the path variables and the number of tickets to appropriate values.</p><br class="clear" />

<div class="wp-geshi-highlight-wrap5"><div class="wp-geshi-highlight-wrap4"><div class="wp-geshi-highlight-wrap3"><div class="wp-geshi-highlight-wrap2"><div class="wp-geshi-highlight-wrap"><div class="wp-geshi-highlight"><div class="php"><pre class="de1"><span class="kw2">&lt;?php</span>
&nbsp;
<span class="kw1">for</span> <span class="br0">&#40;</span><span class="re0">$i</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> <span class="re0">$i</span> <span class="sy0">&lt;</span> <span class="nu0">1500</span><span class="sy0">;</span> <span class="re0">$i</span><span class="sy0">++</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="re0">$file</span> <span class="sy0">=</span> <span class="st0">&quot;./commits/r<span class="es4">$i</span>&quot;</span><span class="sy0">;</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">file_exists</span><span class="br0">&#40;</span><span class="re0">$file</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw3">exec</span><span class="br0">&#40;</span><span class="st0">&quot;svnadmin setlog ./conjoon-rep --bypass-hooks -r <span class="es4">$i</span> <span class="es4">$file</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div></div></div></div></div></div>


<p class="message_blue" style="font-size:13px;">After all messages were collected and the old Trac style ticket number was replaced with the Jira ticket numbers, I ran this script, which simply loops over the available files and calls svnadmin to replace the commit message with the one found in the file.</p><br class="clear" /><p>Before you intend to change your commit messages, please make sure you read and understand &#8220;<a href="http://subversion.apache.org/faq.html#change-log-msg">changing SVN log messages</a>&#8220;.</p>
]]></content:encoded>
			<wfw:commentRss>http://thorsten.suckow-homberg.de/2011/11/10/how-conjoon-quickly-migrated-from-trac-to-jira/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>conjoon &#8211; dev notes</title>
		<link>http://thorsten.suckow-homberg.de/2010/06/01/conjoon-dev-notes/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=conjoon-dev-notes</link>
		<comments>http://thorsten.suckow-homberg.de/2010/06/01/conjoon-dev-notes/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 02:48:52 +0000</pubDate>
		<dc:creator>Thorsten Suckow-Homberg</dc:creator>
				<category><![CDATA[conjoon]]></category>
		<category><![CDATA[My Projects]]></category>
		<category><![CDATA[datastorage]]></category>
		<category><![CDATA[in progress]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://www.siteartwork.de/2010/06/01/conjoon-dev-notes/</guid>
		<description><![CDATA[Conjoon_Db_LobAccess_StorageMediator<br />
General purpose: Automatically decide if LOBs have to be stored in the  server&#8217;s file system (and provide appropriate base functionality), while  providing the database as a fallback in any case.<br />
&#8220;A storage mediator is responsible for determining whether to store lobs  in the database or in the file system. It takes care of processing  various operations related to lobs such as retrieving their content and  properly storing them, while maintaining relations between the db ...]]></description>
			<content:encoded><![CDATA[<p><code>Conjoon_Db_LobAccess_StorageMediator</code><br />
General purpose: Automatically decide if LOBs have to be stored in the  server&#8217;s file system (and provide appropriate base functionality), while  providing the database as a fallback in any case.</p>
<p>&#8220;A storage mediator is responsible for determining whether to store lobs  in the database or in the file system. It takes care of processing  various operations related to lobs such as retrieving their content and  properly storing them, while maintaining relations between the db data  and the lob itself, no matter if it has been saved in the filesystem or  the db.<br />
While configuring the system is up to the server administrator, a  mediator is able to provide fallbacks if the used instances of <code>Conjoon_File_LobAccess</code> and <code>Conjoon_Db_LobAccess</code> have been implemented  properly: As long as the hint for the storage_container maintains valid,  lob data can be retrieved from the filesystem even if the application&#8217;s  configuration is set to storing the lobs in the database (this goes for  lobs that have been saved before  configuration changed).&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://thorsten.suckow-homberg.de/2010/06/01/conjoon-dev-notes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>conjoon demo available</title>
		<link>http://thorsten.suckow-homberg.de/2010/03/30/conjoon-demo-available/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=conjoon-demo-available</link>
		<comments>http://thorsten.suckow-homberg.de/2010/03/30/conjoon-demo-available/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 14:06:40 +0000</pubDate>
		<dc:creator>Thorsten Suckow-Homberg</dc:creator>
				<category><![CDATA[conjoon]]></category>
		<category><![CDATA[demo]]></category>
		<category><![CDATA[extjs]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://www.siteartwork.de/2010/03/30/conjoon-demo-available/</guid>
		<description><![CDATA[While I was working on a new version of conjoon (which was released just now &#8211; see http://www.conjoon.org/blog/2010/03/30/conjoon-0-1-2-released/), I finally had the time to set up a public demo of conjoon. I thought the best way to provide a public demo where multiple users share on installation was to branch the main dev line into a &#8220;demo&#8221; branch, removing and/or altering some functionality so the demo provides almost all features of a custom install, yet not giving anonymous users full ...]]></description>
			<content:encoded><![CDATA[<p>While I was working on a new version of conjoon (which was released just now &#8211; see <a title="conjoon 0.1.2 release announcements" href="http://www.conjoon.org/blog/2010/03/30/conjoon-0-1-2-released/" target="_blank">http://www.conjoon.org/blog/2010/03/30/conjoon-0-1-2-released/</a>), I finally had the time to set up a <a title="official conjoon demo" href="http://demo.conjoon.org" target="_blank">public demo of conjoon</a>. I thought the best way to provide a public demo where multiple users share on installation was to branch the main dev line into a &#8220;demo&#8221; branch, removing and/or altering some functionality so the demo provides almost all features of a custom install, yet not giving anonymous users full access over some of the features.</p>
<p>Users still have to apply for a demo account, however, this process is fully automated and the data is only needed to set up accounts in the conjoon demo&#8217;s database. <a title="conjoon demo registration" href="http://www.conjoon.org/demo" target="_blank">You can register for an account here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://thorsten.suckow-homberg.de/2010/03/30/conjoon-demo-available/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>conjoon &#8211; bundled preview available</title>
		<link>http://thorsten.suckow-homberg.de/2009/12/09/conjoon-bundled-preview-available/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=conjoon-bundled-preview-available</link>
		<comments>http://thorsten.suckow-homberg.de/2009/12/09/conjoon-bundled-preview-available/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 13:35:40 +0000</pubDate>
		<dc:creator>Thorsten Suckow-Homberg</dc:creator>
				<category><![CDATA[conjoon]]></category>
		<category><![CDATA[extjs]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://www.siteartwork.de/2009/12/09/conjoon-bundled-preview-available/</guid>
		<description><![CDATA[<br />
Yes, you might think the &#8220;ALL NEW!&#8221; stamp is kind of cheesy and the colors might be too bright, but that&#8217;s just how I&#8217;d like to announce the immediate availability of a preview version for conjoon 0.1 &#8211; in a very reserved way, of course.<br />
conjoon V0.1RC1Pr935 is available from the conjoon project page and brings you a sneek peak of things to come. This release brings you<br />
<br />
<br />
system sounds<br />
configurable workbench, i.e. lots of drag &#38; ...]]></description>
			<content:encoded><![CDATA[<p><img style="margin: 10px; float: left;" title="ALL NEW!" src="http://www.conjoon.org/images/all_new.png" alt="ALL NEW!" /></p>
<p>Yes, you might think the &#8220;ALL NEW!&#8221; stamp is kind of cheesy and the colors might be too bright, but that&#8217;s just how I&#8217;d like to announce the immediate availability of a preview version for conjoon 0.1 &#8211; in a very reserved way, of course.</p>
<p>conjoon V0.1RC1Pr935 is available from the <a title="conjoon project home" href="http://www.conjoon.org" target="_blank">conjoon project page</a> and brings you a sneek peak of things to come. This release brings you</p>
<p></p>
<ul>
<li>system sounds</li>
<li>configurable workbench, i.e. lots of drag &amp; drop goodies</li>
<li>a <a title="Twitter home" href="http://www.twitter.com" target="_blank">Twitter</a> client with lots of features</li>
<li>enhanced Youtube panel</li>
<li>backend performance improvements (caching)</li>
<li>Ext 3.0 to allow for a more stable, even faster responding UI</li>
<li>Zend Framework 1.9.4 to allow for a more stable backend</li>
<li>backend support for Ext.Direct-API (stacked requests, stacked responses)</li>
<li>bug fixes, enhancements, and more&#8230;</li>
</ul>
<p>There are some known issues with IE7/IE8 related to some user extensions that conjoon uses, that&#8217;s why I labeled the release as a preview and offer a &#8220;build&#8221; version only (i.e. no dev sources), but it&#8217;s fully functional in all other major browsers. Go grab your copy, it&#8217;s totally free. If you want to leave feedback, I&#8217;d be more than happy to welcome you <a title="conjoon forums" href="http://www.conjoon.org/forum" target="_blank">in the conjoon forums</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://thorsten.suckow-homberg.de/2009/12/09/conjoon-bundled-preview-available/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ext.ux.Livegrid &#8211; project home moved</title>
		<link>http://thorsten.suckow-homberg.de/2009/05/03/extuxlivegrid-project-home-moved/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=extuxlivegrid-project-home-moved</link>
		<comments>http://thorsten.suckow-homberg.de/2009/05/03/extuxlivegrid-project-home-moved/#comments</comments>
		<pubDate>Sun, 03 May 2009 09:31:36 +0000</pubDate>
		<dc:creator>Thorsten Suckow-Homberg</dc:creator>
				<category><![CDATA[Ext.ux.Livegrid]]></category>
		<category><![CDATA[My Projects]]></category>
		<category><![CDATA[extjs]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.siteartwork.de/2009/05/03/extuxlivegrid-project-home-moved/</guid>
		<description><![CDATA[<br />
The project home for Ext.ux.Livegrid has been finally moved &#8211; you can find it now at the official webpage www.ext-livegrid.com.<br />
The prior project home will redirect you automatically to the new page &#8211; please update your bookmarks accordingly.<br />
Connected with the new project home is a wiki/bugtracker which you will find at wiki.ext-livegrid.com<br />
]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.siteartwork.de/images/ext-ux-livegrid-projecthome.jpg" title="Ext.ux.Livegrid project home" alt="Ext.ux.Livegrid project home" style="margin: 10px; float: left" /></p>
<p>The project home for Ext.ux.Livegrid has been finally moved &#8211; you can find it now at the official webpage <a href="http://www.ext-livegrid.com" target="_blank">www.ext-livegrid.com</a>.<br />
The prior project home will redirect you automatically to the new page &#8211; please update your bookmarks accordingly.</p>
<p>Connected with the new project home is a wiki/bugtracker which you will find at <a href="http://wiki.ext-livegrid.com" target="_blank">wiki.ext-livegrid.com</a></p>
]]></content:encoded>
			<wfw:commentRss>http://thorsten.suckow-homberg.de/2009/05/03/extuxlivegrid-project-home-moved/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>t3n magazine: conjoon interview</title>
		<link>http://thorsten.suckow-homberg.de/2009/03/19/t3n-magazine-conjoon-interview/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=t3n-magazine-conjoon-interview</link>
		<comments>http://thorsten.suckow-homberg.de/2009/03/19/t3n-magazine-conjoon-interview/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 13:27:32 +0000</pubDate>
		<dc:creator>Thorsten Suckow-Homberg</dc:creator>
				<category><![CDATA[My Projects]]></category>
		<category><![CDATA[conjoon]]></category>
		<category><![CDATA[interview]]></category>
		<category><![CDATA[media]]></category>
		<category><![CDATA[news]]></category>

		<guid isPermaLink="false">http://www.siteartwork.de/2009/03/19/t3n-magazine-conjoon-interview/</guid>
		<description><![CDATA[<br />
There is an interview about conjoon in the news area of the t3n magazine. You can read it here.<br />
I answer several questions related to the development process and you will find out why I had a hard time figuring out a name for the project. It goes without saying that I recommend ExtJS and Zend Framework for your daily work as an app builder there, too.<br />
Thanks to the yeebase team for  their interest in the software!<br ...]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.siteartwork.de/images/t3n-interview.png" title="t3n interview screenshot" alt="t3n interview screenshot" style="margin: 10px; float: left" /></p>
<p>There is an interview about <a href="http://www.conjoon.org" title="conjoon Project Home" target="_blank">conjoon</a> in the news area of the <a href="http://t3n.yeebase.com" title="T3N Magazine Home" target="_blank">t3n magazine</a>. You can read it <a href="http://t3n.de/news/interview-thorsten-suckow-homberg-denke-conjoon-noch-239814/" title="t3n interview " target="_blank">here</a>.</p>
<p>I answer several questions related to the development process and you will find out why I had a hard time figuring out a name for the project. It goes without saying that I recommend <a href="http://www.extjs.com" title="Ext JS Project Home" target="_blank">ExtJS</a> and <a href="http://framework.zend.com" title="Zend framework Project Home" target="_blank">Zend Framework</a> for your daily work as an app builder there, too.</p>
<p>Thanks to the <a href="http://www.yeebase.com" title="Yeebase Home" target="_blank">yeebase</a> team for  their interest in the software!</p>
]]></content:encoded>
			<wfw:commentRss>http://thorsten.suckow-homberg.de/2009/03/19/t3n-magazine-conjoon-interview/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ext.ux.Livegrid in Sun&#8217;s xVM Ops Center</title>
		<link>http://thorsten.suckow-homberg.de/2009/02/10/extuxlivegrid-in-suns-xvm-ops-center/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=extuxlivegrid-in-suns-xvm-ops-center</link>
		<comments>http://thorsten.suckow-homberg.de/2009/02/10/extuxlivegrid-in-suns-xvm-ops-center/#comments</comments>
		<pubDate>Tue, 10 Feb 2009 07:58:25 +0000</pubDate>
		<dc:creator>Thorsten Suckow-Homberg</dc:creator>
				<category><![CDATA[Ext.ux.Livegrid]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[clients]]></category>
		<category><![CDATA[extjs]]></category>

		<guid isPermaLink="false">http://www.siteartwork.de/2009/02/10/extuxlivegrid-in-suns-xvm-ops-center/</guid>
		<description><![CDATA[It&#8217;s been in the works for over 2 months now, and I&#8217;m happy to finally announce that Sun Microsystems&#8216; xVM Ops Center uses the Ext.ux.Livegrid-component.<br />
Sun xVM is Sun&#8217;s overall brand for virtualization and management software, and the xVM Ops Center is a tool for datacenter automization and virtualization management of servers at high-scale.<br />
I&#8217;m glad to see the component has received such good reviews so far. The new release is still pending, but conjoon keeps me busy and since ...]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been in the works for over 2 months now, and I&#8217;m happy to finally announce that <a href="http://www.sun.com" title="Sun Microsystems" target="_blank">Sun Microsystems</a>&#8216; <a href="http://www.sun.com/software/products/xvmopscenter/" title="Sun xVM Ops Center" target="_blank">xVM Ops Center</a> uses the <a href="http://www.ext-livegrid.com" title="Ext.ux.Livegrid project home" target="_blank">Ext.ux.Livegrid</a>-component.<br />
<a href="http://www.sun.com/software/products/xvm/" title="Sun xVM" target="_blank">Sun xVM</a> is Sun&#8217;s overall brand for virtualization and management software, and the xVM Ops Center is a tool for datacenter automization and virtualization management of servers at high-scale.<br />
I&#8217;m glad to see the component has received such good reviews so far. The new release is still pending, but <a href="http://www.conjoon.org" title="conjoon project home" target="_blank">conjoon</a> keeps me busy and since the livegrid provides necessary core functionality, development is an ongoing process.<br />
Another big company (working in the financial sector) is incorporating <a href="http://www.ext-livegrid.com" title="Ext.ux.Livegrid project home" target="_blank">Ext.ux.Livegrid</a> in their software and with the upcoming <a href="http://extjs.com/blog/2009/02/03/ext-conference-2009/" title="Ext JS 2009 conference blog entry" target="_blank">Ext JS conference</a> you can tell that the guys over at <a href="http://www.extjs.com" title="Ext JS" target="_blank">Ext JS</a> are doing an incredible job.<br />
At last, I want to thank Scott for his effort in keeping me in touch with the legal department over at Sun. It&#8217;s been exciting to work with you on the drafts, Scott, and getting your professional feedback. Wish you all the best!</p>
]]></content:encoded>
			<wfw:commentRss>http://thorsten.suckow-homberg.de/2009/02/10/extuxlivegrid-in-suns-xvm-ops-center/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>conjoon stats from ohloh.net</title>
		<link>http://thorsten.suckow-homberg.de/2009/02/04/conjoon-stats-from-ohlohnet/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=conjoon-stats-from-ohlohnet</link>
		<comments>http://thorsten.suckow-homberg.de/2009/02/04/conjoon-stats-from-ohlohnet/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 10:23:37 +0000</pubDate>
		<dc:creator>Thorsten Suckow-Homberg</dc:creator>
				<category><![CDATA[conjoon]]></category>
		<category><![CDATA[My Projects]]></category>
		<category><![CDATA[extjs]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://www.siteartwork.de/2009/02/04/conjoon-stats-from-ohlohnet/</guid>
		<description><![CDATA[<br />
<br />
<br />
<br />
<br />
 <br />
a:link, a:hover, a:visited {<br />
color:#B30000;<br />
}<br />
a:link, a:hover, a:visited {<br />
color:#B30000;<br />
}<br />
<br />
]]></description>
			<content:encoded><![CDATA[<p><script src="http://www.ohloh.net/p/309339/widgets/project_basic_stats.js" type="text/javascript"></script></p>
<p><script src="http://www.ohloh.net/p/309339/widgets/project_partner_badge.js" type="text/javascript"></script></p>
<p><script src="http://www.ohloh.net/p/309339/widgets/project_languages.js" type="text/javascript"></script></p>
<p><script src="http://www.ohloh.net/p/309339/widgets/project_factoids.js" type="text/javascript"></script></p>
<p><script src="http://www.ohloh.net/p/309339/widgets/project_cocomo.js" type="text/javascript"></script></p>
<style type="text/css"> 
a:link, a:hover, a:visited {
color:#B30000;
}
a:link, a:hover, a:visited {
color:#B30000;
}</p>
</style>
]]></content:encoded>
			<wfw:commentRss>http://thorsten.suckow-homberg.de/2009/02/04/conjoon-stats-from-ohlohnet/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>1st Annual Ext JS Conference (Miami, Orlando)</title>
		<link>http://thorsten.suckow-homberg.de/2009/02/03/1st-annual-ext-js-conference-miami-orlando/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=1st-annual-ext-js-conference-miami-orlando</link>
		<comments>http://thorsten.suckow-homberg.de/2009/02/03/1st-annual-ext-js-conference-miami-orlando/#comments</comments>
		<pubDate>Tue, 03 Feb 2009 10:59:36 +0000</pubDate>
		<dc:creator>Thorsten Suckow-Homberg</dc:creator>
				<category><![CDATA[Sencha]]></category>
		<category><![CDATA[conferences]]></category>
		<category><![CDATA[extjs]]></category>

		<guid isPermaLink="false">http://www.siteartwork.de/2009/02/03/1st-annual-ext-js-conference-miami-orlando/</guid>
		<description><![CDATA[The 1st annual Ext JS Conference was announced today. It will take place in Orlando, Miami, from the 14th to the 16th of April, 2009 in the  Ritz-Carlton Grande Lakes hotel. According to the session list it looks like it will be all about theExt JS 3.0 release.<br />
I&#8217;m excited to finally meet the Ext JS staff personally and tech-talk with the community members .<br />
They offer an early registration discount for registering by the 10th of February, so ...]]></description>
			<content:encoded><![CDATA[<p>The 1st annual <a href="http://extjs.com/blog/2009/02/03/ext-conference-2009/" title="Ext JS Conference" target="_blank">Ext JS Conference</a> was announced today. It will take place in Orlando, Miami, from the 14th to the 16th of April, 2009 in the  <a href="http://www.ritzcarlton.com/en/Properties/Orlando/Default.htm" target="_blank">Ritz-Carlton Grande Lakes</a> hotel. According to the <a href="http://extjs.com/conference/sessions/">session list</a> it looks like it will be all about theExt JS 3.0 release.</p>
<p>I&#8217;m excited to finally meet the <a href="http://extjs.com/conference/attendees/" title="Ext JS Conference attendee list" target="_blank">Ext JS staff personally and tech-talk with the community members </a>.</p>
<p>They offer an early registration discount for registering by the 10th of February, so make sure you subscribe today!</p>
]]></content:encoded>
			<wfw:commentRss>http://thorsten.suckow-homberg.de/2009/02/03/1st-annual-ext-js-conference-miami-orlando/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

