Correct timezone handling with TYPO3 and Fluid - mysql

Its confusing me. I've a property in my Model which is annotated with DateTime. In my Database its stored as timestamp. In Frontend I use the f:format.date viewhelper to output this property.
When I create a new record, and add f.e. 01.06.2017 10:00 in this field, in my database is stored the timestamp for 01.06.2017 08:00. In Frontend the output is correct. Until here everything is fine.
The last timechange in March lead to a + of two hours in output. I assume in October that will change again and the output will be than this: 01.06.2017 08:00.
How can I prevent this. Its definitely a problem when these dates change, because its important for the business.
How can I test what will happen in October?

The Problem occurs as TYPO3 saves times normalized as UTC. for normalization (and afterwards denormalization) it respects the timezone-settings of the server. Or settings given in LocalConfiguration.php.
Up to 6.2 there were two settings [SYS][serverTimeZone] and [SYS][phpTimeZone].
With 7.6 it is only [SYS][phpTimeZone] as the servertimezone is detected from php itself.
You now have the option to fake the timezone of your server to "UTC" by setting [SYS][phpTimeZone] to the string "UTC". In this way no times should be changed any more.

TYPO3 9.5 and newer
Use the environment (documentation)
// use TYPO3\CMS\Core\Utility\GeneralUtility;
// use TYPO3\CMS\Core\Context\Context;
$context = GeneralUtility::makeInstance(Context::class);
// Reading the current data instead of $GLOBALS
$currentTimezone = $context->getPropertyFromAspect('date', 'timezone');
$currentTstamp = $context->getPropertyFromAspect('date', 'timestamp');
$current = new DateTime('#'.$currentTstamp);
$current->setTimezone(new DateTimeZone($currentTimezone) );
In Fluid you may use a DateTime-Object:
// in PHP-ode of Viewhelper
//...
$this->registerArgument('date', 'mixed', 'Either an object implementing DateTimeInterface or a string that is accepted by DateTime constructor');
// ...
In HTML
{dateTimeObject -> f:format.date()}
<f:format.date format="d.m.Y">{dateTimeObject}</f:format.date>

Related

Is there a way to store database modifications with a versioning feature (for eventual versions comparaison)?

I'm working on a project where users could upload excel files into a MySQL database. Those files are the main source of our data as they come directly from the contractors working with the company. They contain a large number of rows (23000 on average for each file) and 100 columns for each row!
The problem I am facing currently is that the same file could be changed by someone (either the contractor or the company) and when re-uploading it, my system should detect changes, update the actual data, and save the action (The fact that the cell went from a value to another value :: oldValue -> newValue) so we can go back and run a versions comparison (e.g 3 re-uploads === 3 versions). (oldValue Version1 VS newValue Version5)
I developed a tiny mechanism for saving the changes => I have a table to save Imports data (each time a user import a file a new row will be inserted in this table) and another table for saving the actual changes
Versioning data
I save the id of the row that have some changes, as well as the id and the table where the actual data was modified (Uploading a file results in a insertion in multiple tables, so whenever a change occurs, I need to know in which table that happened). I also save the new value and the old value which is gonna help me with restoring the "archives data".
To restore a version : SELECT * FROM 'Archive' WHERE idImport = ${versionNumber}
To restore a version for one row : SELECT * FROM 'Archive' WHERE idImport = ${versionNumber} and rowId = ${rowId}
To restore all version for one row : SELECT * FROM 'Archive' WHERE rowId = ${rowId}
To restore version for one table : SELECT * FROM 'Archine' WHERE tableName = ${table}
Etc.
Now with this structure, I'm struggling to restore a version or to run a comparaison between two versions, which makes think that I've came up with a wrong approach since it makes it hard to do the job! I am trying to know if anyone had done this before or what a good approach would look like?
Cases when things get really messy :
The rows that have changed in a version might not have changed in the other version (I am working on a time machine to search in other versions when this happens)
The rows have changed in both versions but not the same fields. (Say we have a user table, the data of the user with id 15 have changed in 2nd and 5th upload, great! Now for the second version only the name was changed, but for the fifth version his address was changed! When comparing these two versions, we will run into a problem constrcuting our data array. name went from "some"-> NULL (Name was never null. No name changes in 5th version) and address went from NULL -> "some' is which obviously wrong).
My actual approach (php)
<?php
//Join records sets and Compare them
foreach ($firstRecord as $frecord) {
//Retrieve first record fields that have changed
$fFields = $frecord->fieldName;
//Check if the same record have changed in the second version as well
$sId = array_search($frecord->idRecord, $secondRecord);
if($sId) {
$srecord = $secondRecord[$sId];
//Retrieve straversee fields that have changed
$sFields = $srecord->fieldName;
//Compare the two records fields
foreach ($fFields as $fField) {
$sfId = array_search($fField, $sFields);
//The same field for the same record was changed in both version (perfect case)
if($sfId) {
$sField = $sFields[$sfId];
$deltaRow[$fField]["oldValue"] = $frecord->deltaValue;
$deltaRow[$fField]["newValue"] = $srecord->deltaValue;
//Delete the checked field from the second version traversee to avoid re-checking
unset($sField[$sfId]);
}
//The changed field in V1 was not found in V2 -> Lookup for a value
else {
$deltaRow[$fField]["oldValue"] = $frecord->deltaValue;
$deltaRow[$fField]["newValue"] = $this->valueLookUp();
}
}
$dataArray[] = $deltaRow;
//Delete the checked record from the second version set to avoid re-checking
unset($secondRecord[$srecord]);
}
I don't know how to deal with that, as I said I m working on a value lookup algorithm so when no data found in a version I will try to find it in the versions between theses two so I can construct my data array. I would be very happy if anyone could give some hints, ideas, improvements so I can go futher with that.
Thank you!
Is there a way to store database modifications with a versioning feature (for eventual versions comparaison [sic!])?
What constitutes versioning depends on the database itself and how you make use of it.
As far as a relational database is concerned (e.g. MariaDB), this boils down to the so called Normal Form which is in numbers.
On Database Normalization: 5th Normal Form and Beyond you can find the following guidance:
Beyond 5th normal form you enter the heady realms of domain key normal form, a kind of theoretical ideal. Its practical use to a database designer os [sic!] similar to that of infinity to a bookkeeper - i.e. it exists in theory but is not going to be used in practice. Even the most demanding owner is not going to expect that of the bookkeeper!
One strategy to step into these realms is to reach the 5th normal form first (do this just in theory, by going through all the normal forms, and study database normalization).
Additionally you can construe versioning outside and additional to the database itself, e.g. by creating your own versioning system. Reading about what you can do with normalization will help you to find better ways to decide on how to structure and handle the database data for your versioning needs.
However, as written it depends on what you want and need. So no straight forward "code" answer can be given to such a general question.

How to work with input dates in a MySql / Laravel (5.6) / AngularJs application?

In my application, a user can specify a date in a form, via a datepicker. Doing so, the date has this format : "2018-05-16T12:45:30Z".
Then, I want to store it in a MySql database, in a TIMESTAMP column.
Later, the user can edit his data. Consequently, the datepicker has to be initialized with the date coming from the server, previously saved.
To manage this, I created an accessor and a mutator :
public function setDateNameInputAttribute($value)
{
$this->attributes['date_name_input'] = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $value);
}
public function getDateNameInputAttribute($value)
{
return Carbon::parse($value)->format('Y-m-d\TH:i:s\Z');
}
This code works fine : my front-end reads UTC (Zulu) dates and I can insert timestamps in my database.
However, it's not perfect.
Let's say I need for whatever reason to add one hour to a stored date
$myObject = MyClass::find(1);
$theDate = $myObject->dateNameInput;
Now $theDate is a "T Z format" string, because of the accessor. I could recreate a Carbon object to do my addition, but I think this Carbon -> string -> Carbon transition would be ugly. How can I make a nice operation ?
If my applications contains a lot of input dates, with many different model names, is there a way to generalize my accessor and my mutator ?
Actually, is my first approach good ?
Thanks for reading !

Joomla 2.5 Component - Store date/time, display on different timezones

Developing a component for Joomla v2.5, I'm using a table with a mysql timestamp column.
One of the component's settings is the "Timezone". I don't want to use server timezone, as code will run on different servers/timezones and I want to be indepedent. So the idea is to store timestamps in mysql, and display the correct date/time according to the component's parameter. The main drawback is the timezone that mysql server uses, that make the whole situation complicated. So, is there a way to store current timestamp in an universal format in MySQL and display it in the correct way?
The ultimate goal is for the component to be able to display the correct date/time based on the component's parameter, eg. user changes the parameter on the fly, no modification on the database take place, only on the "View"
In order to display the date in the correct timezone I use this:
JHtml::date($date_from_mysql , 'd/m/Y H:i:s', $my_component_timezone_parameter)
Please share your thoughts.
try
jimport ('joomla.utilities.date');
$date = new JDate($mydate);
$curdate = $date->toFormat('%Y-%m-%d %H:%M:%S');
for timezone settings
try http://docs.joomla.org/JDate::setTimezone/1.6
http://www.webamoeba.co.uk/site/index.php/articles-joomla-date-time
or try to override the store method in your table class:
public function store($updateNulls = false)
{
// get date
$date = JFactory::getDate();
// set variable for timestamp
$this->myDate = $date->toMySQL();
return parent::store($updateNulls);
}

How to get hibernate to store a date?

I have a Spring / Hibernate project and I am trying to store a date into the database but it's not working. It must be something stupid but I have no idea what I am doing wrong.
Here is my code:
user.setFailedPasswordAnswerAttemptCount(0);
user.setLastLoginDate(new Date());
user.setIsOnline(true);
The other two variables (failedPasswordAnswerAttemptCount and isOnline) are getting written to the database without issue. I have also tried it with just passing a java.util.Date instead of a java.sql.Timestamp...same result. Here is how the property is defined on the user object:
private Date lastLoginDate;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="last_login_date")
public Date getLastLoginDate() {
return this.lastLoginDate;
}
public void setLastLoginDate(Date lastLoginDate) {
this.lastLoginDate = lastLoginDate;
}
Here is the column definition:
`last_login_date` datetime DEFAULT NULL
Any help? I don't even know what else to look for as this should be working.
Some more detail about the error: No errors or strange messages in the hibernate log. The hibernate log is showing a parameterized query but it isn't telling me what it is actually writing. It looks like it's not updating the column at all. In other words, if there is already a date there it doesn't change, or if it is null it doesn't change.
Update: I have looked at the logs and it looks like hibernate does write the proper data, but then immediately writes the incorrect data again. I see the following entry in the log:
11:15:12.280 [http-bio-8080-exec-26] TRACE o.h.e.def.AbstractSaveEventListener - detached instance of: com.hi.model.User
11:15:12.280 [http-bio-8080-exec-26] TRACE o.h.e.def.DefaultMergeEventListener - merging detached instance
And right after that I see it putting the old value back in for the lastLoginDate.
Why are you using
Date date = new Date();
user.setLastLoginDate(new Timestamp(date.getTime()));
and not just this?
user.setLastLoginDate(new Date());
First - You may not want to use Date and Timestamp at the same time.(e.g. for collections, etc)
There are some classes in the Java platform libraries that do extend an instantiable
class and add a value component. For example, java.sql.Timestamp
extends java.util.Date and adds a nanoseconds field. The equals implementation
for Timestamp does violate symmetry and can cause erratic behavior if
Timestamp and Date objects are used in the same collection or are otherwise intermixed.
The Timestamp class has a disclaimer cautioning programmers against
mixing dates and timestamps. While you won’t get into trouble as long as you
keep them separate, there’s nothing to prevent you from mixing them, and the
resulting errors can be hard to debug. This behavior of the Timestamp class was a
mistake and should not be emulated. (Bloch, Effective Java, 2nd Ed.)
Second - I checked your examples, and it works fine for me on mysql-connector(5.1.21) / hibernate (4.0.1)
I prepared simple test project with arquillian integration test(You need to prepare jboss before running it):
https://github.com/rchukh/StackOverflowTests/tree/master/13803848
If you can provide some more information it might help - hibernate version, mysql version, mysql engine(MyISAM, InnoDB, etc.)
Otherwise it is possible that this is just a misconfiguration.
I found the problem. I am refactoring some code and it looks like I was doing this:
//get user object
User user = getUser();
//call a function which modifies user
functionModifiesUser();
//modify user
user.blah = blah;
entityManager.merge(user);
So the parent function had a stale copy of the user object when I tried to save it. Actually, removing the merge statement was enough to fix it. But I have refactored the code to put all this in one place.
Setting the column last_login_date as timestamp should work, at least works for me.

Losing DateTimeOffset precision when using C#

I have a SQL Server table with a CreatedDate field of type DateTimeOffset(2).
A sample value which is in the table is 2010-03-01 15:18:58.57 -05:00
As an example, from within C# I retrieve this value like so:
var cmd = new SqlCommand("SELECT CreatedDate FROM Entities WHERE EntityID = 2", cn);
var da = new SqlDataAdapter(cmd);
DataTable dt =new DataTable();
da.Fill(dt);
And I look at the value:
MessageBox.Show(dt.Rows[0][0].ToString());
The result is 2010-03-01 15:18:58 -05:00, which is missing the .57 that is stored in the database.
If I look at dt.Rows[0][0] in the Watch window, I also do not see the .57, so it appears it has been truncated.
Can someone shed some light on this? I need to use the date to match up with other records in the database and the .57 is needed.
Thanks!
Darvis
SQL Server doesn't have millisecond precision.
Here's an article that goes into the details:
Advanced SQL Server DATE and DATETIME Handling
EDIT
I'm guessing C# shouldn't show the same behavior. Keep in mind that the DateTime.ToString() method doesn't include milliseconds unless you specify a Format Provider.
The Watch window would also be showing you ToString(). Try setting a Breakpoint and use the Inspector to get the more detailed information being stored and see if you mililseconds are there.
Fill should change the data in the dataset to match the data in the datasource -- have you tried any other methods to retrieve the data to see if other classes retrieve the data in the format you are hoping for? Simple tests like sqldatasource/gridview, etc