rails 3 group by date a datetime column - datetime

Foo.group(:start_at).count(:id)
How I can group this by date ? the "start_at" column is an datetime column

This should work (rails 3):
Foo.order(:start_at).group("DATE(start_at)").count
edit: if you're using PostgreSQL, the query should be
Foo.order("DATE(start_at)").group("DATE(start_at)").count
or you'll get an error
("PGError: ERROR: column "foos.start_at" must appear in the GROUP BY clause or be used in an aggregate function")
Based on
Graphing new users by date in a Rails app using Seer
and
http://www.pastbedti.me/2009/11/grouping-a-timestamp-field-by-date-in-ruby-on-rails-postgresql/

I created a gem for this. https://github.com/ankane/groupdate
Foo.group_by_day(:created_at).count
You can even specify a time zone.
Foo.group_by_day(:created_at, time_zone: "Pacific Time (US & Canada)").count

This is another way to solve this if you manage different time zones. The idea is to add or substract the hours of your timezone:
hours_diff = Time.zone.now.time_zone.utc_offset/(60*60) rescue 0
hours_diff = hours_diff.to_i
date_group = "DATE(form_answers.created_at)"
if hours_diff > 0
date_group = "DATE(DATE_ADD(form_answers.created_at, INTERVAL #{hours_diff} HOUR ))"
elsif hours_diff < 0
date_group = "DATE(DATE_SUB(form_answers.created_at, INTERVAL #{hours_diff.abs} HOUR ))"
end
Foo.group(date_group).count

Related

Is there any Oracle built-in function to convert date format and how to exclude weekends from the logic

The below code gives me the output of current review date and the next review date. Here the current review date is fixed to today's date.
I want to keep that as a user defined variable. I tried using the --> ReviewDate = &enter_date; but whichever format i put in the dialog box it gives me an error (i tried 08-06-2020, 06-08-2020, 08-Jun-2020, etc). Is there any built-in function in oracle which will convert the value I input to the correct system date which oracle will understand ?
Also, what should be the code if i want to exclude any weekends from my current logic ? Here the next review date is set to 6 months from current review date but i want my code to exclude the weekends from this.
Thanks!!
SET SERVEROUTPUT ON;
DECLARE
ReviewDate workforce.Jdate%TYPE;
BEGIN
ReviewDate := '08-06-2020';
ReviewDate_New := add_months(ReviewDate, 6);
dbms_output.put_line('Last Review Date: ' || '08-06-2020');
dbms_output.put_line('Next Review Date: ' || ReviewDate_New);
END;
The ANSI format for a date literal is DATE 'YYYY-NN-DD' so:
ReviewDate := DATE '2020-06-08';
To avoid weekends you would have to check the day of the week returned by the add_months function and then increment the date accordingly. to_char with the 'D' format returns you a number 1-7 for the day of the week, so something like:
CASE TO_CHAR(ReviewDate_New, 'D')
WHEN 6 THEN
ReviewDate_New := ReviewDate_New + 2;
WHEN 7 THEN
ReviewDate_New := ReviewDate_New + 1;
ELSE
NULL; -- Do nothing
END CASE;
This assumes that Saturdays and Sundays are day 6 and 7 in your database (it depends on NLS settings).

NIFI Executescript UTC Error for unsupported operand type "+" in java.sql.Timestamp and timedelta

I am trying to split a flowfile into multiple flow files on the basis of adding a month to a date which i am getting in the coming flowfile.
eg.
{"to":"2019-12-31T00:00:00Z","from":"2019-03-19T15:36:48Z"}
be the dates i am getting in a flowfile . so i have to split this single flow file into 11 flowfiles with date ranges like
{"to":"2019-04-19","from":"2019-03-19"}
{"to":"2019-05-19","from":"2019-04-19"}
{"to":"2019-06-19","from":"2019-05-19"}
....... and so till
{"to":"2019-12-31","from":"2019-12-19"} .
i have been trying with example inputs to split files with this into day wise flowfiles:
`
begin = '2018-02-15'
end = '2018-04-23'
dt_start = datetime.strptime(begin, '%Y-%m-%d')
dt_end = datetime.strptime(end, '%Y-%m-%d')
one_day = timedelta(days = 1)
start_dates = [dt_start]
end_dates = []
today = dt_start
while today <= dt_end:
tomorrow = today + one_day
print(tomorrow)
`
but i get a error in my Execute script processor. nifi flow screenshot
Since you're using Jython, you may have to cast today to some Jython/Python time variable or call today.getTime() in order to do arithmetic operations on it.

AgeCalendar Datetime Field Issue

For my AgingCalendar field, I have 3 conditions using CASE WHEN:
CASE WHEN A.[END_DTTM] > A.[STRT_DTTM] THEN C2.[DY_OF_CAL_NUM] - C1.[DY_OF_CAL_NUM]
WHEN A.[END_DTTM] IS NULL and A.[STRT_DTTM] IS NOT NULL THEN C3.[DY_OF_CAL_NUM] - C1.[DY_OF_CAL_NUM]
WHEN A.[END_DTTM] = A.[STRT_DTTM] THEN 1
END AS AgeCalendar
For my third condition, I'm trying to basically say when the End Datetime = Start Datetime, the age in Calendar days should be set to 1 calendar day.
However, in some of the records I'm bringing in, the start date equals the end date, but the times associated with each datetime are different. When this happens, those records are receiving a NULL in the AgeCalendar field.(For example I could have 6/6/2014 0:00:00 = 6/6/2014 0:00:00, and that will give me 1...but if I had 6/6/2014 0:00:00 = 6/6/2014 0:03:59 (or something like that)...it'll give me a NULL value because it's not matching.
How can I update the code above so that I'm basically saying when End Date = Start Date, then 1...regardless of not having matching times?
CASTor CONVERT them as dates to ignore the time.
WHEN CONVERT(DATE, A.[END_DTTM]) = CONVERT(DATE, A.[STRT_DTTM]) THEN 1
OR
WHEN CAST(A.[END_DTTM] AS DATE) = CAST(A.[STRT_DTTM] AS DATE) THEN 1

SQLite ISO (ie European style) week numbers

I want to return ISO standard week numbers (ie week 1-52/53) from a date.
I have tried using the built in function strftime, but with no success.
Can anyone suggest a way without having to write a custom C or other function.
I know this is an old question, but recently I was looking for an efficient solution for the same problem, and this is what I came up with:
SELECT
my_date,
(strftime('%j', date(my_date, '-3 days', 'weekday 4')) - 1) / 7 + 1 as iso_week
FROM my_table;
The basic idea is to calculate the ISO week number by simply performing integer division of the day of year of the Thursday of the date being looked up (my_date) by 7, giving a result between 0 and 52, and then adding 1 to it. And the subtraction by 1 just before the division is there just for the alignment of the division: Thursday of week 1, for example, can have a day of year between 1 and 7, and we want the result of the division to be 0 in all cases, so we need to subtract 1 from the day of year before dividing it by 7.
What specifically did you try?
This works for me (using built-in SQLite from Python REPL):
import sqlite3
c = sqlite3.connect(':memory:')
c.execute('''create table t (c);''')
c.execute('''insert into t values ('2012-01-01');''')
c.execute('''select c, strftime('%W',c) from t;''').fetchone()
# -> (u'2012-01-01', u'00')
OK, so I managed to answer my own question. For anyone who might need a similar solution, this is what I came up with. Please note, I do not have an IT background and my SQL is self taught.
General process
Get the Thursday of the week the date belongs too.
Get the 4th of January of the year of that Thursday.
Get the Thursday of the week the 4th January date belongs too.
Subtract Step 2 with Step 3, divide by 7 and add 1.
Translated into SQLite....
SELECT
date,
CASE CAST (strftime('%w', wknumjanfourth) AS INTEGER)
WHEN 0 THEN ((JULIANDAY(datesThur) - JULIANDAY(strftime("%s", wknumjanfourth) - 259200, 'unixepoch')) / 7) + 1
ELSE ((JULIANDAY(datesThur) - JULIANDAY(DATE(strftime("%s", wknumjanfourth) - (86400 * (strftime('%w', wknumjanfourth) - 1)), 'unixepoch'), '+3 day')) / 7) + 1
END AS weeknum
FROM
(
SELECT
date,
datesThur,
DATE(datesThur,'start of year','+3 day') AS wknumjanfourth
FROM
(SELECT
date,
CASE CAST (strftime('%w', date) AS INTEGER)
WHEN 0 THEN DATE(strftime("%s", date) - 259200, 'unixepoch')
ELSE DATE(DATE(strftime("%s", date) - (86400 * (strftime('%w', date) - 1)), 'unixepoch'), '+3 day')
END AS datesThur
FROM TEST
))
If anyone can improve this SQL, I would appreciate the feedback.

How to convert string to datetime format classic asp

I have one variable
Dim tt="2008-10-20 10:00:00.0000000"
I want to change it into date,
Try CDATE(tt) see http://www.w3schools.com/vbscript/func_cdate.asp. I used
vbscript cdate
as keywords at Google. There were more results.
Edit: Based on the comment below (I'm sorry for mixing up), using
FormatDateTime(date,format)
Format contains following constants:
0 = vbGeneralDate - Default. Returns date: mm/dd/yy and time if
specified: hh:mm:ss PM/AM.
1 = vbLongDate - Returns date: weekday, monthname, year
2 = vbShortDate - Returns date: mm/dd/yy
3 = vbLongTime - Returns time: hh:mm:ss PM/AM
4 = vbShortTime - Return time: hh:mm
(copied from http://www.w3schools.com/vbscript/func_formatdatetime.asp)
This link, (MS CDate page), explains that:
adate = CDate(astring)
converts a string into a date object. For there, you can format it with the FormatDateTime function
str = FormatDateTime(Date)
the FormatDateTime function is "smart" -- it will format as date and time if both are present, otherwise it will format with whichever of date or time is present.
I propose a safe solution which returns the result only if the conversion is successful:
s="2008-10-20 10:00:00.0000000"
On Error Resume Next
d=CDate(Left(s,19))
On Error Goto 0
if not IsEmpty(d) then MsgBox d
Try it for a non-valid date or non-valid format. The result will be empty.
s="2008-02-31 10:00:00"
In same contexts, it is necessary to initialize the variable collecting result of CData. I recommend to initialize it as Empty. Example below shows such case - counting valid dates in a string array:
Lines = array("2008-10-20 10:00:00.0000000", "2008-10-20 10:00:00", "", "2008-02-31", "Today", "2017-02-7")
On Error Resume Next
Count=0
for each Line in Lines
d=Empty
d=CDate(Line)
if not IsEmpty(d) then Count=Count+1
next
On Error Goto 0
MsgBox "Number of valid dates is "&Count
The correct answer is 2. Without initialization we get 5 as the CDate does not do anything on error so variable keeps the value from a recent iteration in the loop.
If do not need your milliseconds, your could use the following:
<script type="text/vbscript">
s="2008-10-20 10:00:00.0000000"
arr= Split(s, ".")
d=CDate(arr(0))
document.write(d)
</script>
I believe cdate is dependent on local settings to parse the string. This is no good in many situations.
To avoid this you need to use
DateSerial()
and if needed add any time components to the result separately.
The date literal in classic asp is unreliable. If the first or second part is greater than 12, it takes that value for day, the other as month. If both parts are less than 12, the interpretation is unpredictable: sometimes american and sometimes british.
A work-around is to force the entry of dates into separate fields or use a date entry module which can set the date into british or american style.
A date literal should be treated as american and use a function to convert that into a date variable using Dateserial().
function amerdate(str)
'str 3/5/2023 form: in american format: use for calculations including date
Dim d
d = Split(str, "/")
amerdate = Dateserial(d(2), d(0), d(1))
end function
Use only american date in calculations like Dateadd() etc.
someday = "3/5/2023" '5th march, american date literal
nextday = Dateadd("d", 1, amerdate(someday))
Whenever a date display is required, convert to british date and show it.
function britdate(str)
'str: 3/5/2023 form: display in british form. not for calculations
Dim d
d= Split(str, "/")
britdate = d(1) & "/" & d(0) & "/" & d(2)
end function

Resources