I need to change timestamp column in my compact ce 4.0 which currently is a string and formated:
"06.01.2016 22.18.47.977". To a column of type Long which holds DateTime.Ticks instead.
The DbMigration scripts proposal is obviously not what i want:
AlterColumn("dbo.LogRecords", "Timestamp",c => c.Long(nullable: false));
My initial thought was to use DATEDIFF to calculate number of millisecond*10.
DATEDIFF ( datepart , startdate , enddate ) *10=ticks
Unfortunatly it seems as if this function can only return int which fails with overflow.
Is there a way to do these kind of migrations in the migration script?
Ideally something like:
AlterColumn("dbo.LogRecords", "Timestamp",c => c.Long(nullable: false,
(p =>DateTime.ParseExact(p.Timestamp, "MM.dd.yyyy HH:mm:ss.fff", culture).Ticks));
Related
I have a datetime field in my model. In a query I want to select all rows created on a specific day/date (the time doesn't matter). What is the simplest way of doing that in CakePHP 3.8 ?
Per other answers, use of a custom function to cast the column with MySQL DATE() may slow your query down at scale. Besides, there's probably nothing simpler than plain arrays to build conditions:
$query = $this->YourTable->find()
->where([
'date_field >=' => '2020-01-01 00:00:0', // Or pass a Time() object..
'date_field <' => '2020-01-02 00:00:00',
]);
This kind of stuff is covered in the Query Builder docs.
I have model I created on the fly for peewee. Something like this:
class TestTable(PeeweeBaseModel):
whencreated_dt = DateTimeField(null=True)
whenchanged = CharField(max_length=50, null=True)
I load data from a text file to a table using peewee, the column "whenchanged" contains all dates in a format of '%Y-%m-%d %H:%M:%S' as varchar column. Now I want to convert the text field "whenchanged" into a datetime format in "whencreated_dt".
I tried several things... I ended up with this:
# Initialize table to TestTable
to_execute = "table.update({table.%s : datetime.strptime(table.%s, '%%Y-%%m-%%d %%H:%%M:%%S')}).execute()" % ('whencreated_dt', 'whencreated')
which fails with a "TypeError: strptime() argument 1 must be str, not CharField": I'm trying to convert "whencreated" to datetime and then assign it to "whencreated_dt".
I tried a variation... following e.g. works without a hitch:
# Initialize table to TestTable
to_execute = "table.update({table.%s : datetime.now()}).execute()" % (self.name)
exec(to_execute)
But this is of course just the current datetime, and not another field.
Anyone knows a solution to this?
Edit... I did find a workaround eventually... but I'm still looking for a better solution... The workaround:
all_objects = table.select()
for o in all_objects:
datetime_str = getattr( o, 'whencreated' )
setattr(o, 'whencreated_dt', datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S'))
o.save()
Loop over all rows in the table, get the "whencreated". Convert "whencreated" to a datetime, put it in "whencreated_dt", and save each row.
Regards,
Sven
Your example:
to_execute = "table.update({table.%s : datetime.strptime(table.%s, '%%Y-%%m-%%d %%H:%%M:%%S')}).execute()" % ('whencreated_dt', 'whencreated')
Will not work. Why? Because datetime.strptime is a Python function and operates in Python. An UPDATE query works in database-land. How the hell is the database going to magically pass row values into "datetime.strptime"? How would the db even know how to call such a function?
Instead you need to use a SQL function -- a function that is executed by the database. For example, Postgres:
TestTable.update(whencreated_dt=whenchanged.cast('timestamp')).execute()
This is the equivalent SQL:
UPDATE test_table SET whencreated_dt = CAST(whenchanged AS timestamp);
That should populate the column for you using the correct data type. For other databases, consult their manuals. Note that SQLite does not have a dedicated date/time data type, and the datetime functionality uses strings in the Y-m-d H:M:S format.
I've been searching but haven't found my answer so forgive me if this question is a duplicate.
I've got a .Net C# application that is using entity framework (EF) to communicate with a SQL Server database. I'm converting a large amount of data and I need to make sure my dates are valid SQL Server datetime types. My POCO classes use a datetime2 type for the dates so a date '0201-04-11 13:00:00 PM' is valid until the insert is actually attempted in the SQL Server database. I was attempting to use DateTime.TryParseExact with something like this...
if (DateTime.TryParseExact(legacyRecord.date_paid.ToString(), "M/d/yyyy hh:mm:ss tt", new CultureInfo("en-us"), DateTimeStyles.None, out datePaid))
{
// Load record into lease payment table table
LoadLeasePayment loadLeasePayment = new LoadLeasePayment();
Decimal LeasePaymentId = loadLeasePayment.AddRecord(prodLeaseId, legacyRecord.amount_paid, datePaid, prodContext, loadDate);
}
I'm sure the solution is obvious but I cannot see the forest for the trees. Any help is much appreciated.
After parsing the string DateTime value, you'll need to verify it is within the range of the target SQL data type. The SqlDateTime structure includes static MinValue and MaxValue fields to facilitate this.
if (DateTime.TryParseExact(legacyRecord.date_paid.ToString(), "M/d/yyyy hh:mm:ss tt", new CultureInfo("en-us"), DateTimeStyles.None, out datePaid))
{
if((datePaid >= SqlDateTime.MinValue) && (datePaid <= SqlDateTime.MaxValue))
{
// Load record into lease payment table table
LoadLeasePayment loadLeasePayment = new LoadLeasePayment();
Decimal LeasePaymentId = loadLeasePayment.AddRecord(prodLeaseId, legacyRecord.amount_paid, datePaid, prodContext, loadDate);
}
}
I need to count the users, but my condition is only if their account have been created today. I have a users table with a created field (datetime) for each rows. How can i do it in Cakephp, i didn't find the answer in the documentation.
$usersNewCount = Number::format($this->Users->find()->where(['created' => 'CURDATE()'])->count());
I tried with CURDATE, and of course it's not working, i guess Cakephp has a specific function for te datetime field ?
What you are doing there won't work for various reasons.
You cannot pass SQL snippets in the value part of the conditions array, it will be escaped and you'll end up with a string comparison like created = 'CURDATE()', you'd either have to pass the whole condition as a string, or use raw expressions.
Even when properly passing CURDATE(), the comparison won't work as the created column has a time part.
While it is possible to circumvent the former problem by transforming the column, you should try to avoid that whenever possible! Comparing to calculated columns like DATE(created) = CURDATE() will make using indices impossible, and thus massively degrade performance!
So unless you have an extra column that holds just the date part, your best bet is a BETWEEN comparison which is the equivalent to a >= x AND a <= y, and in order to stay cross DBMS compatible, this is best to be done by passing dates from PHP, ie not using DBMS specific date and time functions like CURDATE().
$this->Users
->find()
->where(function (\Cake\Database\Expression\QueryExpression $exp, \Cake\ORM\Query $query) {
$from = (new \DateTime())->setTime(0, 0, 0);
$to = (new \DateTime())->setTime(23, 59, 59);
return $exp->between('Users.created', $from, $to, 'datetime');
})
->count()
This will create a query similar to
SELECT
(COUNT(*)) AS `count`
FROM
users Users
WHERE
Users.created BETWEEN '2015-05-26 00:00:00' AND '2015-05-26 23:59:59'
See also
API > \Cake\Database\Expression\QueryExpression::between()
You can do it this way
$usersNewCount = Number::format($this->Users->find()->where([
'DATE(created) = CURDATE()'
])->count());
Note that passing it in form where(['DATE(created)' => 'CURDATE()']) will not work, since CURDATE() will be interpreted as a string.
When doing 'created' => 'CURDATE()' you are checking for a complete match, getting '2015-05-26', without a time. You need to check for a time interval:
$usersNewCount = Number::format(
$this->Users->find()->where([
'created >=' => date('Y-m-d').' 00:00:00',
'created <=' => date('Y-m-d').' 23:59:59'
])->count());
In my application I need to get database date(sysdate in case of Oracle DB) and compare it with user input date (String converted to java.util.Date). From this forum I got the following code which helps in the case of Oracle dialect.
public Date getDate() {
Session session = getHibernateTemplate().getSessionFactory().openSession();
SQLQuery query = session.createSQLQuery("select sysdate as mydate from dual");
query.addScalar("mydate", Hibernate.TIMESTAMP);
return (Date) query.uniqueResult();
}
And from this link got the following method which uses mapping file with formula.
<property name="currentDate" formula="(select sysdate from dual)"/>
Again this is specific to Oracle. I think using later method is more performance friendly, because we can get it from the same session, i.e no need of opening another session just for getting date.
I am looking for a generic solution to get date, time and timestamp from any DBMS using Hibernate. Using HQL is the preferred. Hope such a solution is available.
For those who are looking for .NET /C# solution, here is what worked for me:
// this works only with Oracle
public DateTime DbTimeStamp(ISession session)
{
// Sample returned value = "12-OCT-11 01.05.54.365134000 AM -07:00"
string sql = "SELECT SYSTIMESTAMP FROM DUAL";
ISQLQuery query = session.CreateSQLQuery(sql)
.AddScalar("SYSTIMESTAMP", NHibernate.NHibernateUtil.DateTime);
return query.UniqueResult<DateTime>();
}