I tried to do the following query to subtract one day from the given date:
DATE(FROM_UNIXTIME(UNIX_TIMESTAMP('2013-04-01') - 86400))
which returns me 2013-03-30, but it should return 2013-03-31.
If i try to subtract one day of 2013-04-02, i get 2013-04-01 correctly returned.
Is this a date bug in mysql?
It's not a bug - what you have found is the missing hour in daylight saving time: a thing unixtime and your calculation is unaware of since you calculate with seconds and not days.
This is exactly why DBMS have special DATETIME datatypes - to handle all the specialities in timezones, leap years, leap seconds, daylight savings and calendars.
Let the database do the work for you - here is an easier and better way to get what you want:
SELECT DATE('2013-04-01') - INTERVAL 1 DAY
Your code makes the assumption that all days have 24 hours. Yesterday, 31st March, had 23 hours in most European countries. To subtract one day you need something like this:
SELECT NOW() - INTERVAL 1 DAY
Why not use the built in DATE_SUB() function?
SELECT DATE_SUB('2013-04-01', INTERVAL 1 DAY)
EDIT: No, This is NOT a date bug in MySQL.
Related
I am trying to query a MySQL database for all records for tomorrow (not the next 24 hours). All the dates are stored as a unixtimestamp.
Could I use the CURDATE() function in anyway?
Your help would be much appreciated!
Select those records whose epoch timestamp is
BETWEEN UNIX_TIMESTAMP(CURDATE() + INTERVAL 1 DAY)
AND
UNIX_TIMESTAMP(CURDATE() + INTERVAL 2 DAY - INTERVAL 1 SECOND)
The beginning of tomorrow is one day beyond today, taken with precision to the second.
The end of tomorrow is one second less than two days beyond today, again taken with second precision.
While it is tempting simply to add 86,399 seconds to the beginning of tomorrow to find its end, some days have more seconds and some have fewer. Better to let date arithmetic functions compute the end.
Specs: I'm using MySQL 5.6 with SQLWorkbench, SequelPro on OSX Yosemite
Query background: I'm trying to correct a set of TIMESTAMPDIFF durations for weekends and bank holidays. I have 2 stored procedures which are giving me the number of Saturdays, Sundays and Bank Holidays between two dates - these are working fine. To get the corrected TIMESTAMPDIFF, I therefore multiply the number of Saturdays, Sundays and holidays by 24 to get the number of hours to be subtracted, then subtract that number from the TIMESTAMPDIFF.
Example: As an example, if timestamp A is 14:00 on Friday and timestamp B is 14:01 on Tuesday, the raw TIMESTAMPDIFF is 96:01:00. Assuming Monday is holiday and the weekend is 48:00:00, I want to subtract 72:00:00 from 96:01:00, to get the 'business day difference' of 24:01:00.
The problem: When I do something like "96:01:00" - "72:00:00" as date_sub_test, I get 24. I have lost all formatting, including the 01 minute. Duration are not DATETIME, as they don't correspond to calendar dates, so I can't use DATE_ADD / DATE_SUB.
The question: How should I subtract time from a duration, retaining formatting and relevant base 60 system eg 60 minutes in an hour, not 100?
Thanks in advance!
As Jaydee mentions in a comment:
Have you tried the TIMEDIFF function? https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_timediff
TIMEDIFF was what I was looking for. I also added in ABS() to make negative time differences positive, and MAKETIME() to create a time from an integer.
Use SEC_TO_TIME and TIME_TO_SEC like
SELECT SEC_TO_TIME(TIME_TO_SEC('96:01:00')-TIME_TO_SEC('72:00:00'))
you can use ABS like this
SELECT SEC_TO_TIME(ABS(TIME_TO_SEC('96:01:00')-TIME_TO_SEC('172:00:00')))
I have a table that keeps the last few weeks worth of data.
The system goes offline around 3am daily for a few min.
I would like to run a cron job on Monday around 3am to pull last week's data.
How would I select last week's data (Monday 00:00:00 through Sunday 23:59:59)?
I realize one way would be to simply schedule the cron for 00:00:00 on Monday but I want to run this when the system is offline so I need to use MySQL to delimit the data.
Thanks in advance.
The difficulty is going to be your last second on Sunday - you often get into rounding errors there. One way to solve this is just to format or cast from DATETIME to DATE...
SELECT *
FROM logfile
WHERE DATE(logdate) BETWEEN DATE_ADD(CURDATE(), -1 INTERVAL day) AND DATE_ADD(CURDATE(), -8 INTERVAL day)
I have an interval of 0012-11-03 (year-month-day) and would like to convert it to number of days:
12 * ~365 + Num of days From 01-01 To 11-03 = answer.
Leap year must be accounted for. (answer + 12/4 ??)
The closest thing I could come up with is using TO_DAYS() MySQL 5.1 but that function "does not take into account the days that were lost when the calendar was changed"
Are you really working with dates of 0012-11-03? I.e. the year 12 AD?
The calendar was not changed recently. They're referring to the days lost in the conversion from the Julian calendar to the Gregorian calendar in 1582 AD.
This should work:
SELECT TO_DAYS('2012-11-03') - TO_DAYS('2012-01-01');
Returns 307.
I have a report that is driven by a sql query that looks like this:
SELECT batch_log.userid,
batches.operation_id,
SUM(TIME_TO_SEC(ramses.batch_log.time_elapsed)),
SUM(ramses.tasks.estimated_nonrecurring + ramses.tasks.estimated_recurring),
DATE(start_time)
FROM batch_log
JOIN batches ON batch_log.batch_id=batches.id
JOIN ramses.tasks ON ramses.batch_log.batch_id=ramses.tasks.batch_id
JOIN protocase.tblusers on ramses.batch_log.userid = protocase.tblusers.userid
WHERE DATE(ramses.batch_log.start_time) > "2011-02-01"
AND ramses.batch_log.time_elapsed > "00:03:00"
AND DATE(ramses.batch_log.start_time) < now()
AND protocase.tblusers.active = 1
AND protocase.tblusers.userid NOT in ("ksnow","smanning", "dstapleton")
GROUP BY userid, batches.operation_id, date(start_time)
ORDER BY start_time, userid ASC
Since this is to be compared with the time from the current payperiod it causes an error.
Our pay periods start on a Sunday, the first pay period was 2011-02-01 and our last pay period started the 4th of this month. How do I put that into my where statement to strip the most recent pay period out of the query?
EDIT: So now I'm using date_sub(now(), INTERVAL 2 WEEK) but I really need a particular day of the week(SUNDAY) since it is wednesday it's chopping it off at wednesday.
You want to use DATE_SUB, and as an example.
Specifically:
select DATE_SUB(curdate(), INTERVAL 2 WEEK)
gets you two weeks ago. Insert the DATE_SUB ... part into your sql and you're good to go.
Edit per your comment:
Check out DAYOFWEEK:
and you can do something along the lines of:
DATE_SUB(DATE_SUB(curdate(), INTERVAL 2 WEEK), INTERVAL 2 + DAYOFWEEK(curdate()) DAY)
(I don't have a MySql instance to test it on .. but essentially subtract the number of days after Monday.)
Question isn't quite clear, especially after the edit - it isn't clear now is the "pay period" two weeks long or do you want just last two weeks back from last sunday? I assume that the period is two weeks... then you first need to know how many days the latest period (which you want to ignore, as it isn't over yet) has been going on. To get that number of days you can use expression like
DATEDIFF(today, FirstPeriod) % 14
where FirstPeriod is 2011-02-01. And now you strip that number of days from the current date in the query using date_sub(). The exact expression depends on how the period is defined but you should get the idea...