We are using the Easy Booking plugin for a client’s project and they want the ability to make the dates recurring. I.E they use the calendar to book Mon, Tues and Wed and want to have it recurring for the next 3 weeks.
We added some JS functionality, with a few form fields, that modifys the data-booking_price so that it is the price * recurring modifier. The order flow works fine while the quantity is one, but if we increase the quantity, the whole thing breaks apart. After we add the item to the cart and then go to View Cart, the price is set to the original booking price, sans the modifier.
You can view it in action here: http://bethpark.dev.ksand.com/product/meter-bags
My question is how does how does the plugin pass the total of the product along to the cart? From what I can see, it’s not updating Woo Sessions with the total that is getting generated. Is that not accurate? I realize we are modifying how the plugin inherenly works, but any sort of pointing in the right direction would be much appreciated!
-Anthony
I've updated WC()->cart->total on both the cart page and the checkout page, but it keeps getting overwritten. I've also manually set the total in WC()->sessions but that also get's overwritten (I've since commented these out since this felt extremely hacky.)
//function to detect if PHP session is started
function is_session_started()
{
if ( php_sapi_name() !== 'cli' ) {
if ( version_compare(phpversion(), '5.4.0', '>=') ) {
return session_status() === PHP_SESSION_ACTIVE ? TRUE : FALSE;
} else {
return session_id() === '' ? FALSE : TRUE;
}
}
return FALSE;
}
add_action( 'woocommerce_before_add_to_cart_button' , 'bpa_custom_add_checkout_fields', 50, 0 );
function save_recursion(){
//if the user is getting the bags with recursive dates set, we will attempt to save them so that they can be used at a later time.
if( isset($_POST['recursive_weeks']) ){
$id = 0;
if( is_user_logged_in() ){
$id = get_current_user_id();
}
// if user is not logged in or if WP couldn't get user ID
if($id > 0){
update_user_meta($id, 'bpa_meter_bag_recursion', $_POST['recursive_weeks']);
} else {
if ( is_session_started() === FALSE ) session_start();
$_SESSION['bpa_meter_bag_recursion'] = $_POST['recursive_weeks'];
}
}
}
add_action('woocommerce_add_to_cart', 'save_recursion');
function custom_add_to_cart( $item_data, $cart_item) {
//this adds the custom recursion dates to the items data
//if this is the meter bag product
if($cart_item['product_id'] == '2476'){
//check if user is logged in, get recursion from user meta. if not try to get sessions
if( is_user_logged_in() ){
$id = get_current_user_id();
$recursion = get_user_meta($id, 'bpa_meter_bag_recursion');
$_POST['recursive_weeks'];
} else {
session_start();
$recursion = $_SESSION['bpa_meter_bag_recursion'] ;
}
// change the message to reflect that this is going to be multiple dates
$item_data[0]['name'] = "First Day of First Week";
$item_data[1]['name'] = "Last Day of First Week";
//get that first week dates in the correct format
$start_date = new DateTime($item_data[0]['value']);
$end_date = new DateTime($item_data[1]['value']);
$first_start_date = $start_date->format('Y-m-d');
$first_end_date =$end_date->format('Y-m-d');
//iterate over the recursive weeks and add these as products to the cart
$week = 1;
$quantity = $cart_item['quantity'];
for($i = 1; $i <= ($recursion[0] * 2) - 2; $i++ ){
if( ($i % 2) != 0){
$item_data[$i + 1]['name'] = "First Day of the Next Week ";
$startDate = strtotime( $first_start_date . " +" . $week ." week" );
$item_data[$i + 1]['value'] = date('F jS Y', $startDate);
} else {
$item_data[$i + 1]['name'] = "Last Day of the Next Week ";
$endDate = strtotime( $first_end_date . " +" . $week ." week");
$item_data[$i + 1]['value'] = date('F jS Y', $endDate);
$week++;
}
}
if ( is_session_started() === FALSE ) session_start();
$_SESSION['recursive_dates'] = serialize($item_data);
if( isset($_SESSION['recursive_dates']) ){
//var_dump($_SESSION['recursive_dates']);
}
return $item_data;
}
}
add_filter('woocommerce_get_item_data', 'custom_add_to_cart', 10, 2);
What I am expecting to have happen is that on the product screen, the updated product total would get added to the cart total, and viewable from the cart and checkout. This works until the quantity is increased. Not sure why this is an issue since I would presume that the total would be prod_total * quantity, but that doesn't appear to be how this works. I'm not sure if this is a woo thing or an Easy Bookings thing (I'm tending to lean towards a woo thing, but my hours of research hasn't found anything, or I'm googling the wrong stuff. )
Any help in pointing me in the right direction is mucho appreciated.
I wrote a simple piece of code to validate the format of a date.
The format of the date in my case is d/m/y
List of tests that I run successfully
10/12/2019 DATE OK
aa/12/2019 DATE KO
10-12-2019 DATE KO
But there is this case that surprises me:
32/12/2019 DATE OK
Why does this happen?
Do I need to add controls on the range of days and months?
$value = '32-12-2019';
$checkDate = \DateTime::createFromFormat('d/m/Y', $value);
if ($checkDate) {
print("DATE OK");
} else {
print("DATE KO");
}
I'm using
public static function validateDate($date, $format = 'Y-m-d')
{
$d = DateTime::createFromFormat($format, $date);
return $d && $d->format($format) === $date;
}
It validates correctness of date and required format
I'm using FullCalendar Beta2, and I set the AllDay flag to True.
The calendar still treats End Date as exclusive!
How can I make the End date inclusive?
Many thanks.
#ZooZ - According to the Beta 2 Upgrade docs, the end date is now exclusive:
all end dates are now exclusive. For example, if an all-day event ends
on a Thursday, the end date will be 00:00:00 on Friday. The 1.x
versions had some strange rules in regards to this. Things should be
much simpler now that exclusive end dates are used consistently
throughout the API. In addition, this behavior is more consistent with
other API's and formats, such as iCalendar.
Reference: http://arshaw.com/fullcalendar/wiki/Upgrading-to-2/
I would just add one to your end date calculation to work around this :)
You can hook into eventAfterAllRender and update a copy of the events and force the calendar to refresh.
In my example the modification only applies to events marked as allDay events (allDay:true). I only modifies a copy/clone of the events data so it only changes the displaying, not the actual data (I think - I need to test it better). I added the clone function but you can use something else if you like. I added the forceRendererToDisplay flag make it run only once.
Here is a fiddle: https://jsfiddle.net/a3q9c5tr/15/
function clone(obj) {
if (null == obj || "object" != typeof obj) return obj;
var copy = obj.constructor();
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
}
return copy;
}
$('#calendar1').fullCalendar({
forceRerenderToDisplay: true,
eventAfterAllRender: function(){
var startdatestr = this.options.events[0].start;
var enddatestr = this.options.events[0].end;
if(this.options.forceRerenderToDisplay == true){
var endDisplayDate = new Date(enddatestr);
endDisplayDate.setDate(endDisplayDate.getDate() + 1);
this.options.forceRerenderToDisplay = false;
var evs = clone(this.options.events);
for(var i in evs){
if(evs[i].allDay){
evs[0].end = new Date(endDisplayDate).toISOString().slice(0,10);
}
}
this.calendar.removeEvents();
this.calendar.addEventSource(evs);
this.calendar.rerenderEvents();
}
},
events:[
{start:'2016-04-03',end:'2016-04-05',title:'my event', allDay:true}
],
header: {
left: 'prev,next,today',
center: 'title',
right: 'month,agendaWeek,agendaDay',
allDay:true
}
});
I know this is kind of old now but with end dates being exclusive I found this workaround without having to add additional days.
first up is set display time to false this will make it so that the time is not shown on the events.
displayEventTime: false,
Then remove the allDay tag from your event and I used a foreach loop for my events which I pulled from DB.
$events=[
"start_date"=>"2020-01-01 00:00:00",
"end_date"=>"2020-01-04 00:00:00",
"title"=>"My Event",
]
events:[
<?php foreach ($events as $event):?>
<?php echo "{start:'".$event["start_date"]."',end:'".$event["end_date"]."',title:'".$event["title"]."'}},";?>
<?php endforeach;?>
],
Within the events part is where I have a foreach loop for the events. I will add
<?php $date = DateTime::createFromFormat("Y-m-d H:i:s", $event["end_date"]);
$date->setTime(0, 0);
// Add 23 hours
$date->add(new DateInterval('PT23H'));?>
so my final foreach loop looks like
events:[
<?php foreach ($events as $event):?>
<?php $date = DateTime::createFromFormat("Y-m-d H:i:s", $event["end_date"]);
$date->setTime(0, 0);
// Add 23 hours
$date->add(new DateInterval('PT23H'));?>
<?php echo "
{start:'".$event["start_date"]."',end:'".$date->format('Y-m-d H:i:s')."',
title:'".$event["title"]."'}},";?>
<?php endforeach;?>
],
so this has the foreach loop within the events. Then I create the date in a easy format to work with where I add the 23 hours and then echo out the date formatted within the event itself.
This then displays the end date as inclusive without having to adjust nextDayThreshold or having to add days before adding a date to your Database.
I am trying to use momentjs to check if a given date is today or in the future.
This is what I have so far:
<script type="text/javascript" src="http://momentjs.com/downloads/moment.min.js"></script>
<script type="text/javascript">
var SpecialToDate = '31/01/2014'; // DD/MM/YYYY
var SpecialTo = moment(SpecialToDate, "DD/MM/YYYY");
if (moment().diff(SpecialTo) > 0) {
alert('date is today or in future');
} else {
alert('date is in the past');
}
</script>
The code is evaluating my date (31st of Jan 2014) as a date in past.
Any idea what I am doing wrong?
You can use the isSame function:
var iscurrentDate = startTime.isSame(new Date(), "day");
if(iscurrentDate) {
}
After reading the documentation: http://momentjs.com/docs/#/displaying/difference/, you have to consider the diff function like a minus operator.
// today < future (31/01/2014)
today.diff(future) // today - future < 0
future.diff(today) // future - today > 0
Therefore, you have to reverse your condition.
If you want to check that all is fine, you can add an extra parameter to the function:
moment().diff(SpecialTo, 'days') // -8 (days)
Since no one seems to have mentioned it yet, the simplest way to check if a Moment date object is in the past:
momentObj.isBefore()
Or in the future:
momentObj.isAfter()
Just leave the args blank -- that'll default to now.
There's also isSameOrAfter and isSameOrBefore.
N.B. this factors in time. If you only care about the day, see Dipendu's answer.
// Returns true if it is today or false if it's not
moment(SpecialToDate).isSame(moment(), 'day');
You can use the isAfter() query function of momentjs:
Check if a moment is after another moment.
moment('2010-10-20').isAfter('2010-10-19'); // true
If you want to limit the granularity to a unit other than milliseconds, pass the units as the second parameter.
moment('2010-10-20').isAfter('2010-01-01', 'year'); // false
moment('2010-10-20').isAfter('2009-12-31', 'year'); // true
http://momentjs.com/docs/#/query/is-after/
Update
moment().isSame('2010-02-01', 'day'); // Return true if we are the 2010-02-01
I have since found the isSame function, which in I believe is the correct function to use for figuring out if a date is today.
Original answer
Just in case someone else needs this, just do this:
const isToday = moment(0, "HH").diff(date, "days") == 0;
or if you want a function:
isToday = date => moment(0,"HH").diff(date, "days") == 0;
Where date is the date you want to check for.
Explanation
moment(0, "HH") returns today's day at midnight.
date1.diff(date2, "days") returns the number of days between the date1 and date2.
invert isBefore method of moment to check if a date is same as today or in future like this:
!moment(yourDate).isBefore(moment(), "day");
To check if it is today:
If we compare two dates which contain also the time information isSame will obviously fail. diff will fail in case that the two dates span over the new day:
var date1 = moment("01.01.2016 23:59:00", "DD.MM.YYYY HH.mm.ss");
var date2 = moment("02.01.2016 00:01:00", "DD.MM.YYYY HH.mm.ss");
var diff = date2.diff(date1); // 2seconds
I think the best way, even if it is not quick and short, is the following:
var isSame = date1.date() == date2.date() && date1.month() == date2.month() && date1.year() == date2.year()
To check if it is in the future:
As suggested also by other users, the diff method works.
var isFuture = now.diff(anotherDate) < 0
If you only need to know which one is bigger, you can also compare them directly:
var SpecialToDate = '31/01/2014'; // DD/MM/YYYY
var SpecialTo = moment(SpecialToDate, "DD/MM/YYYY");
if (moment() > SpecialTo) {
alert('date is today or in future');
} else {
alert('date is in the past');
}
Hope this helps!
Use the simplest one to check for future date
if(moment().diff(yourDate) >= 0)
alert ("Past or current date");
else
alert("It is a future date");
if firstDate is same or after(future) secondDate return true else return false. Toda is firstDate = new Date();
static isFirstDateSameOrAfterSecondDate(firstDate: Date, secondDate: Date): boolean {
var date1 = moment(firstDate);
var date2 = moment(secondDate);
if(date1 && date2){
return date1.isSameOrBefore(date2,'day');
}
return false;
}
There is isSame, isBefore and isAfter for day compare moment example;
static isFirstDateSameSecondDate(firstDate: Date, secondDate: Date): boolean {
var date1 = moment(firstDate);
var date2 = moment(secondDate);
if (date1 && date2) {
return date1.isSame(date2,'day');
}
return false;
}
static isFirstDateAfterSecondDate(firstDate: Date, secondDate: Date): boolean {
var date1 = moment(firstDate);
var date2 = moment(secondDate);
if(date1 && date2){
return date1.isAfter(date2,'day');
}
return false;
}
static isFirstDateBeforeSecondDate(firstDate: Date, secondDate: Date): boolean {
var date1 = moment(firstDate);
var date2 = moment(secondDate);
if(date1 && date2){
return date1.isBefore(date2,'day');
}
return false;
}
I wrote functions that check if a date of Moment type is a Day that Passed or not, as functional and self-descriptive functions.
Maybe it is could to help someone.
function isItBeforeToday(MomentDate: Moment) {
return MomentDate.diff(moment(0, 'HH')) < 0;
}
function isItAfterToday(MomentDate: Moment) {
return MomentDate.diff(moment(0, 'HH')) > 0;
}
Select yesterday to check past days or not with help of moment().subtract(1, "day");
Reference:- http://momentjs.com/docs/#/manipulating/subtract/
function myFunction() {
var yesterday = moment().subtract(1, "day").format("YYYY-MM-DD");
var SpecialToDate = document.getElementById("theDate").value;
if (moment(SpecialToDate, "YYYY-MM-DD", true).isAfter(yesterday)) {
alert("date is today or in future");
console.log("date is today or in future");
} else {
alert("date is in the past");
console.log("date is in the past");
}
}
<script src="http://momentjs.com/downloads/moment.js"></script>
<input type="date" id="theDate" onchange="myFunction()">
function isTodayOrFuture(date){
date = stripTime(date);
return date.diff(stripTime(moment.now())) >= 0;
}
function stripTime(date){
date = moment(date);
date.hours(0);
date.minutes(0);
date.seconds(0);
date.milliseconds(0);
return date;
}
And then just use it line this :
isTodayOrFuture(YOUR_TEST_DATE_HERE)
If we want difference without the time you can get the date different (only date without time) like below, using moment's format.
As, I was facing issue with the difference while doing ;
moment().diff([YOUR DATE])
So, came up with following;
const dateValidate = moment(moment().format('YYYY-MM-DD')).diff(moment([YOUR SELECTED DATE HERE]).format('YYYY-MM-DD'))
IF dateValidate > 0
//it's past day
else
//it's current or future
Please feel free to comment if there's anything to improve on.
Thanks,
i wanted it for something else but eventually found a trick which you can try
somedate.calendar(compareDate, { sameDay: '[Today]'})=='Today'
var d = moment();
var today = moment();
console.log("Usign today's date, is Date is Today? ",d.calendar(today, {
sameDay: '[Today]'})=='Today');
var someRondomDate = moment("2012/07/13","YYYY/MM/DD");
console.log("Usign Some Random Date, is Today ?",someRondomDate.calendar(today, {
sameDay: '[Today]'})=='Today');
var anotherRandomDate = moment("2012/07/13","YYYY/MM/DD");
console.log("Two Random Date are same date ? ",someRondomDate.calendar(anotherRandomDate, {
sameDay: '[Today]'})=='Today');
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
check with following:
let isContinue = moment().diff('2020-04-04T20:06:11+05:30')/1000
it is returning in seconds..
If will check as 2 mins condition then
if (isContinue < 120) {
..To check otp details or further logic
} else {
// otp is getting invalid
}
Simplest answer will be:
const firstDate = moment('2020/10/14'); // the date to be checked
const secondDate = moment('2020/10/15'); // the date to be checked
firstDate.startOf('day').diff(secondDate.startOf('day'), 'days'); // result = -1
secondDate.startOf('day').diff(firstDate.startOf('day'), 'days'); // result = 1
It will check with the midnight value and will return an accurate result. It will work also when time diff between two dates is less than 24 hours also.
I want to use fullcalendar with custom date range for ex. it should display view for particular date range like from 15th April to 4th May(Spans between two months).
Any suggestions?.
you can call this function to gt events in date range. but this will bring you only 30 days evnt. if you pass dates like '01-may-2013' to 15-June-2013' then it will show data from 01-may2013 to 30st may 2013. Lt me know if you can find any clue for this issue.
function GetAgendaEvents(datefrom, dateTo) {
var fromDate = new Date($("#from").val());
var toDate = new Date($("#to").val());
if (fromDate.getTime() <= toDate.getTime()) {
$('#fullcal').fullCalendar('removeEvents').fullCalendar('addEventSource', events);
$('#fullcal').fullCalendar('refetchEvents');
var filteredEvent = $('#fullcal').fullCalendar('clientEvents', function (event) {
return event.start >= fromDate && event.start <= toDate;
});
$('#fullcal').fullCalendar('gotoDate', fromDate.getFullYear(), fromDate.getMonth(), fromDate.getDate());
$('#fullcal').fullCalendar('changeView', 'agenda'/* or 'basicDay' */);
$('#fullcal').fullCalendar('removeEvents').fullCalendar('addEventSource', filteredEvent);
$('#fullcal').fullCalendar('refetchEvents');
}
}