How do I correct the year in the date? - sql

There is a date field for users.birth_date.
This field contains a date, for example, Mon, 18 Dec 1989.
How to take this date into account in the current year, for example, Mon, 18 Dec 2021
I do this so that I know the exact day of the week (1-Monday, 2-Tuesday,...) in the current year.
To find the day of the week in the date from the users.birth_date field, I do this:
extract(dow from users.birth_date::timestamp) IN (1,2,3)
how can I convert the date to find out what day of the week the user's birthday is in the current year?

I think you just need to get the birth date in the current year based on the birth date with the year saved in your database.
This should do the trick for you:
select extract(dow from format('%s-%s-%s', extract(year from now()), extract(month from users.birth_date), extract(day from users.birth_date))::date) from users;

I would use make_date() for this:
select birth_date,
make_date(extract(year from current_date)::int,
extract(month from birth_date)::int,
extract(day from birth_date)::int) as this_years_date
from users;
A view that does this for you would probably be helpful if you need this a lot. Then you can use extract(dow from this_years_date) while selecting from the view.

Using a combination of to_char and to_date might do the trick. See the following examples:
WITH users (birth_date) AS (
VALUES (to_date('Mon, 18 Dec 1989','Dy, DD Mon YYYY'))
)
SELECT
birth_date,
to_char(birth_date,'Dy, DD Mon YYYY'),
extract(dow from birth_date) dow_1,
to_date(extract(year from current_date)||
to_char(birth_date,'-mm-dd'),'yyyy-mm-dd'),
to_char((extract(year from current_date)||
to_char(birth_date,'-mm-dd'))::date,'Dy, DD Mon YYYY'),
extract(dow from to_date(extract(year from current_date)||
to_char(birth_date,'-mm-dd'),'yyyy-mm-dd')) dow_2
FROM users;
birth_date | to_char | dow_1 | to_date | to_char | dow_2
------------+------------------+-------+------------+------------------+-------
1989-12-18 | Mon, 18 Dec 1989 | 1 | 2021-12-18 | Sat, 18 Dec 2021 | 6
(1 row)

select EXTRACT(DOW FROM cast(to_date(to_char(now(),'yyyy')||to_char(users.birth_date,'-MM-dd')||' 00:00:00','YYYY-MM-DD HH24:MI:SS') as TIMESTAMP));
1.string contact current year and users.birth_date
2.string convert to date

If you are changing the year fields into current year.
You can calculate the year difference, then add it back to the original date.
SELECT (
TO_DATE('1989-02-24', 'YYYY-MM-DD') + (
INTERVAL '1 year' * (
EXTRACT(YEAR FROM CURRENT_DATE) -
EXTRACT(YEAR FROM TO_DATE('1989-02-24', 'YYYY-MM-DD'))
)
)
)
It is still a date, so you can do anything that you can apply on date.
Such as EXTRACT(dow, [date]);
Use + INTERVAL X * '1 YEAR' can prevent you generateing invalid date in leap years.

Related

How to get year interval between two date in postgresql?

i want the year intervals like this
fromdate = 15-09-2019, todate=21-09-2021
15-09-2019 - 31-12-2019 //for the year 2019
01-01-2020 - 31-12-2020 //for the year 2020
01-01-2021 - 21-12-2021 //for the year 2021
so that i can able to get data from those intervals
In this table i have values only for 2021 but not for 2019 and 2020
If any there is no data in the range of 2019 and 2020.It should prdouce 0 for the parameter Traincount and tonnage.
Simply subtract them:
SELECT ('2015-01-12'::date - '2015-01-01'::date) AS days;
The result:
days
------
11
There is a brute force approach to getting a yearly summary, which is to break the data out by days and then aggregate:
select min(dte), max(dte)
from generate_series('2019-09-15'::date, '2021-09-21'::date, interval '1 day') gs(dte)
group by date_trunc('year', dte);
However, more efficient method would avoid aggregation:
select greatest(gs.dte, v.fromdate),
least(gs.dte + interval '1 year - 1 day', v.todate)
from (values ('2019-09-15'::date, '2021-09-21'::date)) v(fromdate, todate) cross join lateral
generate_series(date_trunc('year', v.fromdate), date_trunc('year', v.todate), interval '1 year') gs(dte);
Here is a db<>fiddle.
You can try
select extract('year' from now()) - extract('year' from now());

Does date_trunc on current_date automatically pick date of current year in postgres?

SELECT *
FROM public.business_calendar;
Above query gives me all data including year 2020 and 2021.
SELECT *
FROM public.business_calendar
WHERE date_trunc('month', business_date) = date_trunc('month', CURRENT_DATE) order by business_date
Above query gives me data of Jan 2021 and not Jan 2020. Does date_trunc automatically work on current year when used with CURRENT_DATE?
Does date_trunc automatically work on current year when used with CURRENT_DATE?
Yes, date_trunc('month', CURRENT_DATE) will truncate the current date.
You may be misunderstanding what date_trunc does. date_trunc('month', CURRENT_DATE) does not return the month, it returns a complete timestamp at the start of the month. On January 17th, 2021 it will return 2021-01-01 00:00:00.
If you want just the month use extract.
test=> select current_date;
current_date
--------------
2021-01-17
(1 row)
test=> select date_trunc('month', current_date);
date_trunc
------------------------
2021-01-01 00:00:00-08
(1 row)
test=> select extract(month from current_date);
date_part
-----------
1
(1 row)
If you want to match dates in the current month ignoring the year...
select *
from public.business_calendar
where extract(month from business_date) = extract(month from current_date)
order by business_date

Extraxcting date using datepart function, but have it returned in text

I'm currently trying to find a way to extract the month from a timestamp field, set up as: yyyy-mm-dd but return the value in either 3 letters (Feb) or the full month (February). It is currently being returned numerically.
Any help would be appreciated!
In PostreSQL, there are several formats to choose from:
select
to_char(current_timestamp, 'MONTH') as "MONTH",
to_char(current_timestamp, 'Month') as "Month",
to_char(current_timestamp, 'MON') as "MON",
to_char(current_timestamp, 'Mon') as "Mon",
to_char(current_timestamp, 'mon') as "mon",
to_char(current_timestamp, 'MM') as "MM";
Result:
MONTH Month MON Mon mon MM
------- ------- ------- ------- ------- -------
JULY July JUL Jul jul 07
datepart() is a SQL Server function. If that is the database you are using, then you can use datename():
select datename(month, getdate())
If its SQL Server:
SELECT FORMAT(GETDATE(), 'MMM')
https://learn.microsoft.com/en-us/sql/t-sql/functions/format-transact-sql?view=sql-server-2017

How to get number of days in month based on date?

Is there a way to use extract from date in format YYYY-MM-DD how many days were in this month?
example:
for 2016-02-05 it will give 29 (Feb 2016 has 29 days)
for 2016-03-12 it will give 31
for 2015-02-05 it will give 28 (Feb 2015 had 28 days)
I'm using PostgreSQL
EDIT:
LAST_DAY function in postgres is not what i'm looking for. it returns DATE while I expect an Integer
One way to achieve this would be to subtract the beginning of the following month from the beginning of the current month:
db=> SELECT DATE_TRUNC('MONTH', '2016-02-05'::DATE + INTERVAL '1 MONTH') -
DATE_TRUNC('MONTH', '2016-02-05'::DATE);
?column?
----------
29 days
(1 row)
Just needed this today and seems that I came up with pretty much the same as Mureinik, just that I needed it numeric. (PostgreSQL couldn't convert from interval to number directly)
previous month:
select CAST(to_char(date_trunc('month', current_date) - (date_trunc('month', current_date) - interval '1 month'),'dd') as integer)
current month:
select CAST(to_char(date_trunc('month', current_date) + interval '1 month' - date_trunc('month', current_date), 'dd') as integer)
You can try next:
SELECT
DATE_PART('days',
DATE_TRUNC('month', TO_DATE('2016-02-05', 'YYYY-MM-DD'))
+ '1 MONTH'::INTERVAL
- DATE_TRUNC('month', TO_DATE('2016-02-05', 'YYYY-MM-DD'))
);
Note: there date is used twice. And used convert function TO_DATE

PostgreSQL Select every fifteen day of month

Hello i have some record:
date Money
1/6/2014 100
12/6/2014 2200
13/6/2014 500
1/3/2014 100
2/5/2014 2200
30/5/2014 500
30/6/2014 100
23/6/2014 2200
31/6/2014 500
Well, i have one param, its date for example i need all record of 30 of july but i need the sum of record if very easy that
select sum(money) from info where date <= param
group by month
But now i need all record group by day of month but i need every fifteen for every month to lower the parameter in my result i need for example
param = 30/6/2014
The result I hope to get:
15/6/2014 sum(money)
15/5/2014 sum(money)
15/4/2014 sum(money)
I need the record for every fifteen of month
The question is how to arrange it to days up to the 15th are in one month and days from the 16th onward are in the next month. You can do this by subtracting 15 days. This puts all days from 1-15 in the previous month. Then, add a month. Here is an approach in Postgres:
select to_char(date - 15 * interval '1 day' + interval '1 month', 'YYYY-MM') as mon,
sum(money)
from info
where date <= param
group by to_char(date - 15 * interval '1 day' + interval '1 month', 'YYYY-MM')
order by 1;
EDIT:
If you want month-to-the-15th, then you can do:
select to_char(date, 'YYYY-MM') as mon,
sum(money)
from info
where extract(day from date) <= param
group by to_char(date, 'YYYY-MM')
order by 1;
Or, if it is only for one month:
select sum(money)
from info
where to_char(date, 'YYYY-MM') = to_char(param, 'YYYY-MM') and
date <= param;