-
Notifications
You must be signed in to change notification settings - Fork 443
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for using a custom Date class #532
Add support for using a custom Date class #532
Conversation
If your project uses a date library that doesn't extend \DateTime (e.g. Zend_Date), then you currently have to convert to and from ActiveRecord\DateTime when interacting with models, which is a pain and error prone. We've had to fix quite a number of bugs due to missing conversions. This commit removes the need for that by adding support for using a custom date class. The custom class is set in ActiveRecord\Config, which uses similar logic to the logger methods for the getter and setter. The ActiveRecord\Config->set_date_class() method checks if the provided class has "format" and "createFromFormat" methods, which are all that are required. I changed everything that created new date objects to use "createFromFormat()" instead of the constructor, because many date libraries don't accept a date string in the constructor. Besides, I think createFromFormat() is better in general because it's more explicit. For the "attribute_of" method, I made that an optional feature by introducing an interface that defines it, which ActiveRecord\Model->assign_attribute() checks for. The reason I made this optional is because if you use an immutable date class (e.g. PHP's DateTimeImmutable), you don't need to worry about the dirty flagging, so there's no need to have that method.
?> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is unrelated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, that's been fixed. Let me know when/if you'd like me to squash these commits into one.
Have you considered adding a .editorconfig file? That would prevent these sorts of issues. I can enter another PR with one if that sounds like something you'd like to see.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case editorconfig is unrelated, because this wouldn't have been edited anyway :) Even though if we would add a editorconfig, it would be set to insert a newline, which then will gradually roll out through. So yeah I'm pro-editorconfig.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #534
This could be valuable, but I don't like the name for |
Yeah, I realize now that Otherwise, |
@@ -460,12 +460,15 @@ public function assign_attribute($name, $value) | |||
} | |||
|
|||
// convert php's \DateTime to ours | |||
if (!($value instanceof DateTime) && $value instanceof \DateTime) | |||
$value = new DateTime($value->format('Y-m-d H:i:s T')); | |||
if (is_object($value) && get_class($value) === 'DateTime') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The double instanceof
has been introduced just recently, and according to a (not so scientific?) benchmark the instanceof
was performing better than get_class
with string comparison.
See that conversation here: #531 (comment)
As suggested by @koenpunt. I also added createFromFormat() and format() to the interface.
Okay, I renamed Thanks for looking at this, and let me know if there's anything else. |
@jpfuentes2 I don't mind resolving the conflict, so feel free to merge #533 first. It can be resolved by just passing the timezone as the third parameter to |
Okay, it should be good to merge now. |
Thanks! 🚀 |
PHP 7.0, mysql 5.7, ubuntu I understand you need somewhere to set the date format? PDOException: SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '2016-05-12 21:40:03 MSK' for column 'updated_at' at row 1 in ***/vendor/php-activerecord/php-activerecord/lib/Connection.php:322 Stack trace: #0 |
@visavi I'm pretty sure that error isn't the result of this PR. The message indicates it happened in The problem is that |
Damn. @koenpunt the merge order of this PR and #533 caused a regression here. Now the time-zone is back to being pulled from the string. PR incoming... /cc: @jpfuentes2 |
Hm, how did I miss that.. |
Eh, it happens. More tests always helps these kinds of things, but I've got that covered in the PR: |
@Rican7 sorry about that. I wasn't aware that the timezone abbreviation represented by "T" could be different than the "full" timezone. That's pretty weird. |
@MasonM no problem. Yea, time-zones are hard. Abbreviations can be ambiguous. The only safe way is to use IANA identifiers. Regardless of what's used, though, the trick is to always grab the object as is, instead of serializing and then deserializing, you know? |
Bugfix - Explicit Time Zone assignment regression from #532
If your project uses a date library that doesn't extend \DateTime (e.g. Zend_Date), then you currently have to convert to and from ActiveRecord\DateTime when interacting with models, which is a pain and error prone. We've had to fix quite a number of bugs due to missing conversions. This commit removes the need for that by adding support for using a custom date class. The custom class is set in ActiveRecord\Config, which uses similar logic to the logger methods for the getter and setter. The ActiveRecord\Config->set_date_class() method checks if the provided class has "format" and "createFromFormat" methods, which are all that are required. I changed everything that created new date objects to use "createFromFormat()" instead of the constructor, because many date libraries don't accept a date string in the constructor. Besides, I think createFromFormat() is better in general because it's more explicit. For the "attribute_of" method, I made that an optional feature by introducing an interface that defines it, which ActiveRecord\Model->assign_attribute() checks for. The reason I made this optional is because if you use an immutable date class (e.g. PHP's DateTimeImmutable), you don't need to worry about the dirty flagging, so there's no need to have that method.
If your project uses a date library that doesn't extend \DateTime (e.g. Zend_Date), then you
currently have to convert to and from ActiveRecord\DateTime when interacting with models, which is a
pain and error prone. We've had to fix quite a number of bugs due to missing conversions. This
commit removes the need for that by adding support for using a custom date class.
The custom class is set in ActiveRecord\Config, which uses similar logic to the logger methods for
the getter and setter. The ActiveRecord\Config->set_date_class() method checks if the provided class
has "format" and "createFromFormat" methods, which are all that are required.
I changed everything that created new date objects to use "createFromFormat()" instead of the
constructor, because many date libraries don't accept a date string in the constructor. Besides, I
think createFromFormat() is better in general because it's more explicit.
For the "attribute_of" method, I made that an optional feature by introducing an interface that
defines it, which ActiveRecord\Model->assign_attribute() checks for. The reason I made this optional
is because if you use an immutable date class (e.g. PHP's DateTimeImmutable), you don't need to
worry about the dirty flagging, so there's no need to have that method.