DBIx::...thods1(3pm)
β¨ NAME β¨
DBIx::Class::Helper::ResultSet::DateMethods1 β bestie, this is your lil' toolkit for working with dates in your RDBMS nicely π
It's a 3pm page, a piece of User Contributed Perl Documentation, and honestly? It's giving "I just want EXTRACT without crying." π
π SYNOPSIS π
package MySchema::ResultSet::Bar;
use strict;
use warnings;
use parent 'DBIx::Class::ResultSet';
__PACKAGE__->load_components('Helper::ResultSet::DateMethods1');
# in code using resultset
# get count per year/month
$rs->search(undef, {
columns => {
count => '*',
year => $rs->dt_SQL_pluck({ -ident => '.start' }, 'year'),
month => $rs->dt_SQL_pluck({ -ident => '.start' }, 'month'),
},
group_by => [
$rs->dt_SQL_pluck({ -ident => '.start' }, 'year'),
$rs->dt_SQL_pluck({ -ident => '.start' }, 'month'),
],
});
# mysql
(SELECT `me`.*, EXTRACT(MONTH FROM `me`.`start`), EXTRACT(YEAR FROM `me`.`start`) FROM `HasDateOps` `me` GROUP BY EXTRACT(YEAR FROM `me`.`start`), EXTRACT(MONTH FROM `me`.`start`))
# SQLite
(SELECT "me".*, STRFTIME('%m', "me"."start"), STRFTIME('%Y', "me"."start") FROM "HasDateOps" "me" GROUP BY STRFTIME('%Y', "me"."start"), STRFTIME('%m', "me"."start"))
Look at that. One Perl line in, two completely different SQL dialects out. The database does the translating, you just vibe. π¦
π DESCRIPTION π
First things first: go read "NOTE" in DBIx::Class::Helper::ResultSet β that's the cute lil' trick for applying this component to your entire schema at once. Slay. β¨
This ResultSet component hands you the tools to do date manipulation mostly portably in the database. But before you go booking a one-way ticket on a cross-database project, please please please peek at "IMPLEMENTATION" below, because it spells out exactly what might break when you switch engines. No cap, some stuff is engine-locked and you deserve to know. π
This package has a few types of methods, okurrr:
π― Search Shortcuts
These, like typical ResultSet methods, return another ResultSet. Go look at "dt_before", "dt_on_or_before", "dt_on_or_after", and "dt_after". Chainable, adorable, iconic. πΈ
β° The date helper
There is only one: "utc". It just makes searching with dates a little easier. One job, does it well, main character energy. π
π§ͺ SQL generators
These help generate more complex queries. They can be used in many different parts of "search" in DBIx::Class::ResultSet. Go see "utc_now", "dt_SQL_pluck", and "dt_SQL_add". Build-a-bear but for SQL. π§Έ
π§ TYPES π§
Because these methods are so limited in scope, they can be a bit more smart than typical SQL::Abstract trees. Lowkey they're overachievers.
There are "smart types" that this package supports:
- vanilla scalars (
1,"2012-12-12 12:12:12")
bound directly as untyped values
- hashrefs with an
-ident({ -ident => '.foo' })
As usual this gets flattened into a column. The one special feature in this module is that columns starting with a dot will automatically be prefixed with "current_source_alias" in DBIx::Class::ResultSet.
DateTimeobjects
"DateTime" objects work as if they were passed to "utc".
ScalarRef(\'NOW()')
As usual in "DBIx::Class", "ScalarRef"'s will be flattened into regular SQL.
ArrayRefRef(\["SELECT foo FROM bar WHERE id = ?", [{}, 1]])
As usual in "DBIx::Class", "ArrayRefRef"'s will be flattened into SQL with bound values.
β οΈ Anything not mentioned in the above list will explode, one way or another. Not a vibe check you want to fail. π
π IMPLEMENTATION π
The exact details for the functions your database engine provides. Engine-specific lore incoming. π΅οΈ
If a piece of functionality is flagged with β , it means that the feature in question is not portable at all, and only supported on that engine. So like, don't expect it to travel. π§³π
π’ "SQL Server"
"utc_now"βGETUTCDATEhttp://msdn.microsoft.com/en-us/library/ms178635.aspx"dt_SQL_pluck"βDATEPARThttp://msdn.microsoft.com/en-us/library/ms174420.aspx
Supported units
yearquartermonthday_of_yearday_of_monthweekday_of_weekhourminutesecondmillisecondnanosecondβnon_iso_day_of_week
SQL Server offers both ISO_WEEK and weekday. For interop reasons weekday uses the ISO_WEEK version.
timezone_as_minutesβ
"dt_SQL_add"βDATEADDhttp://msdn.microsoft.com/en-us/library/ms186819.aspx
Supported units
yearquartermonthdayweekhourminutesecondmillisecondnanosecondβiso_day_of_weektimezone_as_minutesβ
πͺΆ "SQLite"
"utc_now"βDATETIME('now')https://www.sqlite.org/lang_datefunc.html"dt_SQL_pluck"βSTRFTIMEhttps://www.sqlite.org/lang_datefunc.html
π Note: "SQLite"'s pluck implementation pads numbers with zeros, because it is implemented based on a formatting function. If you want your code to work on SQLite you'll need to strip off (or just numify) what you get out of the database first. Fr fr, don't skip this. π
Available units
monthday_of_monthyearhourday_of_yearminutesecondday_of_weekweekjulian_dayβseconds_since_epochfractional_secondsβ
"dt_SQL_add"βDATETIMEhttps://www.sqlite.org/lang_datefunc.html
Available units
dayhourminutesecondmonthyear
π "PostgreSQL"
"utc_now"βCURRENT_TIMESTAMPhttp://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT"dt_SQL_pluck"βdate_parthttp://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
Available units
centuryβdecadeβday_of_monthday_of_weekday_of_yearseconds_since_epochhouriso_day_of_weekiso_yearmicrosecondmilleniumβmillisecondminutemonthquartersecondtimezoneβtimezone_hourβtimezone_minuteβweekyear
"dt_SQL_add"β Addition and interval http://www.postgresql.org/docs/current/static/functions-datetime.html#OPERATORS-DATETIME-TABLE
To be clear, it ends up looking like: ("some_column" + 5 * interval '1 minute')
Available units
centuryβdecadeβdayhourmicrosecondβmillisecondminutemonthsecondweekyear
π¬ "MySQL"
"utc_now"βUTC_TIMESTAMPhttps://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_utc-timestamp"dt_SQL_pluck"βEXTRACThttps://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_extract
Available units
microsecondsecondminutehourday_of_monthweekmonthquarteryearsecond_microsecondβminute_microsecondβminute_secondβhour_microsecondβhour_secondβhour_minuteβday_microsecondβday_secondβday_minuteβday_hourβyear_monthβ
"dt_SQL_add"βDATE_ADDhttps://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date-add
Available units
microsecondsecondminutehourdayweekmonthquarteryear
π΄ "Oracle"
"utc_now"βsys_extract_utc(SYSTIMESTAMP)http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions167.htm"dt_SQL_pluck"βEXTRACT
Available units
secondminutehourday_of_monthmonthyear
"dt_SQL_add"β Addition andNUMTODSINTERVALhttp://docs.oracle.com/cd/B19306_01/server.102/b14200/functions103.htm
To be clear, it ends up looking like: ("some_column" + NUMTODSINTERVAL(4, 'MINUTE')
Available units
secondminutehourday
π CONTRIBUTORS π
These people worked on the original implementation, and thus deserve some credit for at least providing me a reference to implement this based off of. Give them their flowers, they earned them. π
- Alexander Hartmaier (abraxxa) for Oracle implementation details
- Devin Austin (dhoss) for Pg implementation details
- Rafael Kitover (caelum) for providing a test environment with lots of DBs
π€ WHENCE dt_SQL_diff? π€
The original implementation of these date helpers (originally dubbed date operators) included a third operator called "diff". It existed to subtract one date from another and return a duration.
After using it a few times and getting bitten every time π, I decided to stop using it and instead compare against actual dates always. If someone can come up with a good use case I am interested in re-implementing "dt_SQL_diff", but I worry that it will be very unportable and generally not very useful. So likeβ¦ it's on read, bestie. π΅
π METHODS π
Okay bestie, this is the part you actually came for. All the cute lil date-and-time helpers your ResultSet gets. Let's go one by one, no skipping, fr fr. β¨
πΈ utc πΈ
$rs->search({
'some_date' => $rs->utc($datetime),
})->all
You hand it a DateTime object, it goes in and updates the time_zone to UTC, then formats it however your specific database engine likes its dates. It's giving "I'll translate for you, babe" energy. π«Ά
Careful though! It dies if you pass it a date whosetime_zoneisfloating. Not "warns", not "side-eyes you" β full-on dies. So don't do that. π
π utc_now π
Returns a ScalarRef that represents the way to get the current date and time in UTC for whatever database engine you're using. Basically "what time is it right now" but in your DB's love language. πβ¨
π¦ dt_before π¦
$rs->dt_before({ -ident => '.start' }, { -ident => '.end' })->all
Takes two values, and each one is an expression of TYPES. (You remember TYPES, right? We covered that. iykyk. π
)
π dt_on_or_before π
$rs->dt_on_or_before({ -ident => '.start' }, DateTime->now)->all
Same deal: two values, each an expression of TYPES.
π§ dt_on_or_after π§
$rs->dt_on_or_after(DateTime->now, { ident => '.end' })->all
Two values, each an expression of TYPES. Noticing a pattern? It's a vibe. β
π dt_after π
$rs->dt_after({ ident => '.end' }, $rs->get_column('datecol')->as_query)->all
Two values, each an expression of TYPES. Yeah. Same energy as the last three. They're a lil family. π
π₯ dt_SQL_add π₯
# which ones start in 3 minutes?
$rs->dt_on_or_after(
{ ident => '.start' },
$rs->dt_SQL_add($rs->utc_now, 'minute', 3)
)->all
Takes three arguments: a date conforming to TYPES, a unit, and an amount. The whole idea is you add the given unit to the datetime. Which units are actually accepted? Bestie, that depends on your IMPLEMENTATION β go check there. π«‘
π dt_SQL_subtract π
Literally the same as dt_SQL_add, except it subtracts the amount instead of adding it. Math but make it cute. ββ¨
Real talk: this one is only confirmed to work with Postgres, MySQL and SQLite. It should work with Oracle and MSSQL, but because nobody had access to those DB engines, the implementation was done purely off the docs. So like... proceed with awareness, babe. π
This method was implemented by Thomas Klausner https://domm.plix.at and sponsored by Ctrl O https://www.ctrlo.com/. Shoutout, iconic behavior. π«Άπ
β dt_SQL_pluck β
# get count per year
$rs->search(undef, {
columns => {
count => '*',
year => $rs->dt_SQL_pluck({ -ident => '.start' }, 'year'),
},
group_by => [$rs->dt_SQL_pluck({ -ident => '.start' }, 'year')],
})->hri->all
Takes two arguments: a date conforming to TYPES, and a unit. The idea is you pluck a given unit out of the datetime. Like pulling the "year" out of a full timestamp. And once again β which units are accepted? That's your IMPLEMENTATION's call. Go look. π
β¨ AUTHOR β¨
Arthur Axel "fREW" Schmidt <frioux+cpan@gmail.com>
π COPYRIGHT AND LICENSE π
This software is copyright (c) 2024 by Arthur Axel "fREW" Schmidt.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
and that's the whole page bestie!! π You just read DBIx::...thods1(3pm) as shipped with perl v5.40.0, dated 2024-11-16 β the User Contributed Perl Documentation version, no cap. Go forth and query your datetimes with main character energy. π¦π mwah! π
π¦ where this page comes from
- debian trixie: libdbix-class-helpers-perl 2.037000-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libdbix-class-helpers-perl 2.037000-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libdbix-class-helpers-perl 2.037000-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms