I am trying to pull data (some transaction related data) from DB. To pull the data, I am passing start date and end date as an argument to the query.
Here I need to pull the data of last 2 months. i.e., Start time would be Jun 01, 2022 and End time would be Aug 01, 2022.
Below is the script:
#!/usr/bin/perl
use strict;
use warnings;
use DateTime;
use Date::Format;
use Date::Parse;
my $nowdate = DateTime->now(time_zone => 'local');
my ($month, $year) = ($nowdate->month, $nowdate->year);
my $date = DateTime->new(
year => $year,
month => $month,
day => 1,
);
my $end_time = str2time($date);
print "END:$end_time\n";
print time2str("%d-%m-%Y %T", $end_time)."\n"; #printing just to see in human readable format
my $start_time = $date->clone;
$start_time->add( months => 1 )->subtract( days => 92 );
$start_time = str2time($start_time);
print "START:$start_time\n";
print time2str("%d-%m-%Y %T", $start_time)."\n"; #printing just to see in human readable format
I have two issues over here:
I am using DateTime object two times to get end time. Can it be done in one shot?
$start_time->add( months => 1 )->subtract( days => 92 ); In this line of code, I have to explicitly mention subtract 92 days, which wouldn't be right always. Since some months have 30 days or 31 days or even 29 days. How can I get 2 month's beginning day date?
Another example: Lets assume if we are in September 2022, then Start time and End time would be Jul 01, 2022 and Sep 01, 2022 respectively.
Note: Perl version is 5.16.3
It would be good If I can do it with Core modules which comes with 5.16.3
You could simplify it by using truncate(to => 'month') to get to the first in the current month:
my $end = DateTime->now(time_zone => 'local')
->truncate(to => 'month');
This may however fail on a day without a midnight so this may be an option:
my $end = DateTime->now(time_zone => 'local')
->set_time_zone('floating')
->truncate(to => 'month');
Then subtract the number of months to get the start date:
my $start = $end->clone->subtract( months => 2 );
Then:
my $start_time = str2time($start);
my $end_time = str2time($end);
print "START:$start_time\n";
print time2str("%d-%m-%Y %T", $start_time)."\n";
print "END:$end_time\n";
print time2str("%d-%m-%Y %T", $end_time)."\n";
Possible output:
START:1654034400
01-06-2022 00:00:00
END:1659304800
01-08-2022 00:00:00
Related
As we all know, date parsing in Go has it's quirks*.
However, I have now come up against needing to parse a datetime string in CCYY-MM-DDThh:mm:ss[.sss...] to a valid date in Go.
This CCYY format is a format that seems to be ubiquitous in astronomy, essentially the CC is the current century, so although we're in 2022, the century is the 21st century, meaning the date in CCYY format would be 2122.
How do I parse a date string in this format, when we can't specify a coded layout?
Should I just parse in that format, and subtract one "century" e.g., 2106 becomes 2006 in the parsed datetime...?
Has anyone come up against this niche problem before?
*(I for one would never have been able to remember January 2nd, 3:04:05 PM of 2006, UTC-0700 if it wasn't the exact time of my birth! I got lucky)
The time package does not support parsing centuries. You have to handle it yourself.
Also note that a simple subtraction is not enough, as e.g. the 21st century takes place between January 1, 2001 and December 31, 2100 (the year may start with 20 or 21). If the year ends with 00, you do not have to subtract 100 years.
I would write a helper function to parse such dates:
func parse(s string) (t time.Time, err error) {
t, err = time.Parse("2006-01-02T15:04:05[.000]", s)
if err == nil && t.Year()%100 != 0 {
t = t.AddDate(-100, 0, 0)
}
return
}
Testing it:
fmt.Println(parse("2101-12-31T12:13:14[.123]"))
fmt.Println(parse("2122-10-29T12:13:14[.123]"))
fmt.Println(parse("2100-12-31T12:13:14[.123]"))
fmt.Println(parse("2201-12-31T12:13:14[.123]"))
Which outputs (try it on the Go Playground):
2001-12-31 12:13:14.123 +0000 UTC <nil>
2022-10-29 12:13:14.123 +0000 UTC <nil>
2100-12-31 12:13:14.123 +0000 UTC <nil>
2101-12-31 12:13:14.123 +0000 UTC <nil>
As for remembering the layout's time:
January 2, 15:04:05, 2006 (zone: -0700) is a common order in the US, and in this representation parts are in increasing numerical order: January is month 1, 15 hour is 3PM, year 2006 is 6. So the ordinals are 1, 2, 3, 4, 5, 6, 7.
I for one would never have been able to remember January 2nd, 3:04:05 PM of 2006, UTC-0700 if it wasn't the exact time of my birth! I got lucky.
The reason for the Go time package layout is that it is derived from the Unix (and Unix-like) date command format. For example, on Linux,
$ date
Fri Apr 15 08:20:43 AM EDT 2022
$
Now, count from left to right,
Month = 1
Day = 2
Hour = 3 (or 15 = 12 + 3)
Minute = 4
Second = 5
Year = 6
Note: Rob Pike is an author of The Unix Programming Environment
I'm supposed to do a program that handles the dates of a year. I'm having a problem with handling the leap year in a good way. I'm not going to post the entire code because it'll be too much. My program runs but I don't like how my last if statement looks.
Information about months and leap years:
Month: Jan Feb Mar Apr May Jun Jul Aug Sep Okt Nov Dec
Days : 31 28/29 31 30 31 30 31 31 30 31 30 30
A year is a leap year if it's evenly dividable by 4, but not even when divided by 100. Years are also evenly dividable by 400 leap years. If it's a leap year, February has 29 days instead of 28.
This is my code (only the part I need help with):
Get(Days);
if Days > 31 or Day < 1 then
raise Day_Error;
elsif Day = 31 and (Month = 2 or Month = 4 or Month = 6 or Month = 9 or Month = 11) then
raise Day_Error;
elsif Day = 30 and (Month = 1 or Month = 3 or Month = 5 or Month = 7 or
Month = 8 or Month = 10 or Month = 12) then
raise Day_Error;
end if;
if Day = 29 and Month = 2 then
if Year mod 400 = 0 or (Year mod 4 = 0 and Year mod 100 /= 0) then
null;
else
raise Day_Error;
end if;
end if;
exit;
end;
end loop;
end Day_Procedure;
My concern is the if statement where I put Day = 29 and Month = 2, can this be solved without having the need to put two if statements?
I think a lot can be gained by putting certain tests in subroutines, even if they are only called once. In the code below I have a routine GetMaxDayInMonth(Month, Year) that gives the maximum day for the given month in the given year. The year is necessary only in the case of February, where the maximum allowed day of the month depends on whether it is in a leap year.
For all other months the return value is constant, which I have recorded in a const array MaxDaysInMonth. Only days in February must be treated specially. That treatment has again been stowed away in its own little subroutine GetFebMaxDay(Day, Month), making everything neat and intelligible.
I have used the new Ada equivalent to the C ternary operator cond?a:b, (if cond then a else b):
function GetFebMaxDay(Year: YearT) return DayInMonthT is
begin
return (if IsLeapYear(Year) then 29 else 28);
end GetFebMaxDay;
The test for valid day then is thus reduced to a single function call
Date.Day <= GetMaxDayInMonth(Date.Month, Date.Year);
I have also created distinct types for year, month and day, imposing constraints where possible (max day in month is 31, after all). Many mistakes would have been avoided if programmers had put feet and meters in their own subtypes that need explicit conversion.
Here is the entire program that checks a few borderline dates:
with Ada.Text_IO; use Ada.Text_IO;
procedure DateCheck is
subtype DayInMonthT is Integer range 1..31;
type MonthT is (JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC);
subtype YearT is Integer;
type DateT is record Year: YearT; Month: MonthT; Day: DayInMonthT; end record;
function IsLeapYear(Y: YearT) return Boolean is
begin
return (Y mod 4 = 0 and Y mod 100 /= 0)
or Y mod 400 = 0;
end IsLeapYear;
function GetFebMaxDay(Year: YearT) return DayInMonthT is
begin
return (if IsLeapYear(Year) then 29 else 28);
end GetFebMaxDay;
function GetMaxDayInMonth(Month: MonthT; Year: YearT) return DayInMonthT is
MaxDaysInMonth: constant array(MonthT) of DayInMonthT :=
( JAN => 31,
FEB => 29,
MAR => 31,
APR => 30,
MAY => 31,
JUN => 30,
JUL => 31,
AUG => 31,
SEP => 30,
OCT => 31,
NOV => 30,
DEC => 31 );
begin return (if Month = FEB then GetFebMaxDay(Year) else MaxDaysInMonth(Month)); end;
function IsValidateDate(Date: DateT) return Boolean is
begin
return Date.Day <= GetMaxDayInMonth(Date.Month, Date.Year);
end;
Dates: array (1..6) of DateT := (others => (0, JAN, 1));
begin
Dates(1) := (2021, FEB, 28);
Dates(2) := (2021, FEB, 29);
Dates(3) := (2021, FEB, 30);
Dates(4) := (2000, FEB, 31);
-- Dates(4) := (2000, FEB, 32); -- raises warning, fails with constraint error
Dates(5) := (2000, FEB, 29);
Dates(6) := (1900, FEB, 29);
for i in Dates'Range loop
Put("Date ");
Put(Dates(i).Year'Image);
Put("-");
Put(Dates(i).Month'Image);
Put("-");
Put(Dates(i).Day'Image);
Put(": Valid date? ");
Put_Line(IsValidateDate(Dates(i))'Image);
end loop;
end DateCheck;
Sample session:
$ gnatmake -gnatwa datecheck.adb && ./datecheck.exe
gcc -c -gnatwa datecheck.adb
gnatbind -x datecheck.ali
gnatlink datecheck.ali
Date 2021-FEB- 28: Valid date? TRUE
Date 2021-FEB- 29: Valid date? FALSE
Date 2021-FEB- 30: Valid date? FALSE
Date 2000-FEB- 31: Valid date? FALSE
Date 2000-FEB- 29: Valid date? TRUE
Date 1900-FEB- 29: Valid date? FALSE
formatCalendarDate = function (dateTime) {
return moment.utc(dateTime).format('LLL');
};
It displays: "28 februari 2013 09:24"
But I would like to remove the time at the end. How can I do that?
I'm using Moment.js.
Sorry to jump in so late, but if you want to remove the time portion of a moment() rather than formatting it, then the code is:
.startOf('day')
Ref: http://momentjs.com/docs/#/manipulating/start-of/
Use format('LL')
Depending on what you're trying to do with it, format('LL') could do the trick. It produces something like this:
Moment().format('LL'); // => April 29, 2016
The correct way would be to specify the input as per your requirement which will give you more flexibility.
The present definition includes the following
LTS : 'h:mm:ss A',
LT : 'h:mm A',
L : 'MM/DD/YYYY',
LL : 'MMMM D, YYYY',
LLL : 'MMMM D, YYYY h:mm A',
LLLL : 'dddd, MMMM D, YYYY h:mm A'
You can use any of these or change the input passed into moment().format().
For example, for your case you can pass moment.utc(dateTime).format('MMMM D, YYYY').
Okay, so I know I'm way late to the party. Like 6 years late but this was something I needed to figure out and have it formatted YYYY-MM-DD.
moment().format(moment.HTML5_FMT.DATE); // 2019-11-08
You can also pass in a parameter like, 2019-11-08T17:44:56.144.
moment("2019-11-08T17:44:56.144").format(moment.HTML5_FMT.DATE); // 2019-11-08
https://momentjs.com/docs/#/parsing/special-formats/
You can also use this format:
moment().format('ddd, ll'); // Wed, Jan 4, 2017
formatCalendarDate = function (dateTime) {
return moment.utc(dateTime).format('LL')
}
Look at these Examples.
Format Dates
moment().format('MMMM Do YYYY, h:mm:ss a'); // December 7th 2020, 9:58:18 am
moment().format('dddd'); // Monday
moment().format("MMM Do YY"); // Dec 7th 20
moment().format('YYYY [escaped] YYYY'); // 2020 escaped 2020
moment().format(); // 2020-12-07T09:58:18+05:30
Relative Time
moment("20111031", "YYYYMMDD").fromNow(); // 9 years ago
moment("20120620", "YYYYMMDD").fromNow(); // 8 years ago
moment().startOf('day').fromNow(); // 10 hours ago
moment().endOf('day').fromNow(); // in 14 hours
moment().startOf('hour').fromNow(); // an hour ago
Calendar Time
moment().subtract(10, 'days').calendar(); // 11/27/2020
moment().subtract(6, 'days').calendar(); // Last Tuesday at 9:58 AM
moment().subtract(3, 'days').calendar(); // Last Friday at 9:58 AM
moment().subtract(1, 'days').calendar(); // Yesterday at 9:58 AM
moment().calendar(); // Today at 9:58 AM
moment().add(1, 'days').calendar(); // Tomorrow at 9:58 AM
moment().add(3, 'days').calendar(); // Thursday at 9:58 AM
moment().add(10, 'days').calendar(); // 12/17/2020
Multiple Locale Support
moment.locale(); // en
moment().format('LT'); // 9:58 AM
moment().format('LTS'); // 9:58:18 AM
moment().format('L'); // 12/07/2020
moment().format('l'); // 12/7/2020
moment().format('LL'); // December 7, 2020
moment().format('ll'); // Dec 7, 2020
moment().format('LLL'); // December 7, 2020 9:58 AM
moment().format('lll'); // Dec 7, 2020 9:58 AM
moment().format('LLLL'); // Monday, December 7, 2020 9:58 AM
moment().format('llll'); // Mon, Dec 7, 2020 9:58 AM
Whenever I use the moment.js library I specify the desired format this way:
moment(<your Date goes here>).format("DD-MMM-YYYY")
or
moment(<your Date goes here>).format("DD/MMM/YYYY")
... etc I hope you get the idea
Inside the format function, you put the desired format. The example above will get rid of all unwanted elements from the date such as minutes and seconds
With newer versions of moment.js you can also do this:
var dateTime = moment();
var dateValue = moment({
year: dateTime.year(),
month: dateTime.month(),
day: dateTime.date()
});
See: http://momentjs.com/docs/#/parsing/object/.
You can use this constructor
moment({h:0, m:0, s:0, ms:0})
http://momentjs.com/docs/#/parsing/object/
console.log( moment().format('YYYY-MM-DD HH:mm:ss') )
console.log( moment({h:0, m:0, s:0, ms:0}).format('YYYY-MM-DD HH:mm:ss') )
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
For people like me want the long date format (LLLL) but without the time of day, there's a GitHub issue for that: https://github.com/moment/moment/issues/2505. For now, there's a workaround:
var localeData = moment.localeData( moment.locale() ),
llll = localeData.longDateFormat( 'llll' ),
lll = localeData.longDateFormat( 'lll' ),
ll = localeData.longDateFormat( 'll' ),
longDateFormat = llll.replace( lll.replace( ll, '' ), '' );
var formattedDate = myMoment.format(longDateFormat);
Try this:
moment.format().split("T")[0]
The thing is - you can run into an issue with timezones. For example, if you parse date like this: '2022-02-26T00:36:21+01:00' it may turn into '25/02/2022' As a solution if your date is in ISO format you can just cut off the time portion from the string, like this:
moment('2022-02-26T00:36:21+01:00'.split('T')[0]).utc().format('DD/MM/YYYY')
This solution is quite blunt, so be careful with string format.
This format works pretty fine
const date = new Date();
const myFormat= 'YYYY-MM-DD';
const myDate = moment(date, 'YYYYMMDDTHHmmss').format(myFormat);
Try
new Date().toDateString()
Result - "Fri Jun 17 2022"
This worked perfectly for me:
moment().format('YYYY-MM-DD')
moment(date).format(DateFormat)
Here DateFormat should be DateFormat = 'YYYY-MM-DD'
I am trying to get week start as friday & end date as friday and I tried to use startOf/endOf week(week/isoweek) but failed. Is there any way that I can get friday as start of week and Friday as end of week using moment.
Moment(date).startOf('week'); // or isoweek
Output should be,
Date of friday
Request data:
First date= 05-09-2019
End date= 05-15-2019(current date)
Expected output:
[
{
Weekstart: 05-03-2019,
Weekend: 05-10-2019
},
{
Weekstart: 05-10-2019,
Weekend: 05-17-2019
}
]
There is no option for setting start day of week . But you can fetch last Friday date using
moment().weekday(-2).format("YYYY-DD-MM")
You can update the week start for a locale using something like:
moment.updateLocale(moment.locale(), { week: { dow: 5 } })
moment().startOf('week').toString(); // Fri May 10 2019 00:00:00 GMT+0100
You can do a short custom function to always give you start and end of the week based on a passed isoWeekDay:
let getCustomWeek = (dayOfWeek=7, date=new Date()) => {
let firstDay, lastDay, passedDay = moment(date).isoWeekday(dayOfWeek)
firstDay = moment(passedDay).subtract(1, 'week')
lastDay = moment(firstDay).add(1, 'week')
return { start: firstDay.format(), end: lastDay.format() }
}
let dateRange = ['05-09-2019', '05-15-2019']
console.log('Friday: ', dateRange.map(d => getCustomWeek(5, new Date(d))))
console.log('Wednesday: ', dateRange.map(d => getCustomWeek(3, new Date(d))))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.js"></script>
PayPal's IPN gives dates in this format 06:52:15 Apr 12, 2014 PDT which is not a valid recognised format. Also, the timezone is specified; I can't find a ColdFusion date class that can take a timezone. So, what's the shortest way to convert the format and translate the timezone to GMT (the timezone of my server). So far I have this...
arr3LA = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dev'];
arrDateParts = ListToArray( FORM.payment_date, ' ');
arrTimeParts = ListToArray( arrDateParts[1], ':' );
arrDateParts[3] = Replace(arrDateParts[3], ',', '', 'All');
objPayPalDateTime = CreateDateTime( arrDateParts[4], ArrayFind( arr3LA, arrDateParts[2]), arrDateParts[3], arrTimeParts[1], arrTimeParts[2], arrTimeParts[3] );
strLSFriendly = DateFormat( objPayPalDateTime, 'mmmm dd, yyyy' ) & ' ' & TimeFormat( objPayPalDateTime, 'h:mm:ss tt' ) & ' ' & arrDateParts[5];
objDateTime = LSParseDateTime( strLSFriendly );
strSQLFriendlyDateTime = DateFormat( objDateTime, 'yyyy-mm-dd hh:mm:ss' );
Can you improve on that?
I'd say forget using native CFML stuff here, and leverage java:
target = "06:52:15 Apr 12, 2014 PDT";
sdf = createObject("java", "java.text.SimpleDateFormat").init("hh:mm:ss MMM dd, yyyy zzz");
result = sdf.parse(target);
writeDump([{target=target},{result=result}]);
Does that do the trick?
(NB: inspired by this question: How to parse date string to Date?)