Invision Community 4: SEO, prepare for v5 and dormant account notifications By Matt Monday at 02:04 PM
Midnight Modding Posted June 16, 2018 Posted June 16, 2018 I have 2 date inputs on a form, let's call them date_one and date_two. Each has 'time' => TRUE. What is wrong with this check in my second input's validation check? if( !\IPS\Request::i()->date_one or $val <= \IPS\DateTime::create( \IPS\Request::i()->date_one ) ) It's not giving desired results. When entering the same times, BUT different dates, and the second date being later than the first date, it's still coming up true instead of false... edit: oops I see one problem on another one is create() uses UTC. So I need to use ts(). But I think I have another issue... checking.
BomAle Posted June 16, 2018 Posted June 16, 2018 try to replace \IPS\DateTime::create( \IPS\Request::i()->date_one ) with \IPS\DateTime::ts( \IPS\Request::i()->date_one, TRUE )->getTimestamp()
Midnight Modding Posted June 16, 2018 Author Posted June 16, 2018 Got it all sorted. One issue was me using create() instead of ts() and the other issue was typo-related...... but me not noticing it because the typo was that I accidentally capitalized the first letter sometimes and not other times and it was a letter that isn't easily noticeable when it's capitalized. lol. (different than my example field name above). Now I think I'm finally all set on these annoying time bugs I kept having. And obviously the field I am checking the request value on has its own checks as well. 16 minutes ago, BomAle said: try to replace \IPS\DateTime::create( \IPS\Request::i()->date_one ) with \IPS\DateTime::ts( \IPS\Request::i()->date_one, TRUE )->getTimestamp() Thanks, I finally figured it out by var dumping my way through it. Except I just simply used the first parameter and didn't use getTimeStamp. I guess what happened is I was using create() to compare some fields to the current time and forgot I needed to use ts() in this case to put their value in the proper time zone. I thought surely I'd post about my fix before anyone posted in here, this time, but judging by my edit time, we posted right at the same time. haha.
Midnight Modding Posted June 16, 2018 Author Posted June 16, 2018 I think $bypassTimezone set to TRUE wouldn't have worked as intended, would it? Because $val would already be set to the user's time zone and that is what I was comparing to.
BomAle Posted June 16, 2018 Posted June 16, 2018 51 minutes ago, Midnight Modding said: and didn't use getTimeStamp. getTimestamp it is necessary as __toString returns a formatted date string not a timestamp, the comparison would not make sense. 42 minutes ago, Midnight Modding said: I think $bypassTimezone set to TRUE wouldn't have worked as intended, would it? I considered you would fetch data without timezone (declaring param TRUE in ts() is equal to \DateTime::createFromFormat('U',$timestamp) only if the $timestamp is a UNIX timestamp) You can use \IPS\DateTime::create( \IPS\Request::i()->date_one )->getTimestamp() //equal to (new \DateTime( \IPS\Request::i()->date_one ))->getTimestamp() //equal to \IPS\DateTime::ts( \IPS\Request::i()->date_one, TRUE )->getTimestamp() //equal to \IPS\Request::i()->date_one //diff to \IPS\DateTime::ts( \IPS\Request::i()->date_one )->getTimestamp() //I think ips have added this method to add timezone of navigator extending datetime object //because of limit of datetime on unix timestamp it will not consider timezone if first param is a unix timestamp.
Midnight Modding Posted June 17, 2018 Author Posted June 17, 2018 7 hours ago, BomAle said: getTimestamp it is necessary as __toString returns a formatted date string not a timestamp, the comparison would not make sense. I considered you would fetch data without timezone (declaring param TRUE in ts() is equal to \DateTime::createFromFormat('U',$timestamp) only if the $timestamp is a UNIX timestamp) You can use \IPS\DateTime::create( \IPS\Request::i()->date_one )->getTimestamp() //equal to (new \DateTime( \IPS\Request::i()->date_one ))->getTimestamp() //equal to \IPS\DateTime::ts( \IPS\Request::i()->date_one, TRUE )->getTimestamp() //equal to \IPS\Request::i()->date_one //diff to \IPS\DateTime::ts( \IPS\Request::i()->date_one )->getTimestamp() //I think ips have added this method to add timezone of navigator extending datetime object //because of limit of datetime on unix timestamp it will not consider timezone if first param is a unix timestamp. But you're forgetting that $val would already be a DateTime object with the user's time zone (IPS already has it as such). So creating a timestamp is just an unnecessary extra step. And you do need to account for the timezone in request data, because it was in the user's tz on the form and is only a string with no tz info when in request data.
Midnight Modding Posted June 22, 2018 Author Posted June 22, 2018 On 6/16/2018 at 5:00 PM, BomAle said: try to replace \IPS\DateTime::create( \IPS\Request::i()->date_one ) with \IPS\DateTime::ts( \IPS\Request::i()->date_one, TRUE )->getTimestamp() I see now why you said this. I was trying so many things to get this right, I forgot ts() was expecting a timestamp for parameter 1! This was not a timestamp. It was a string from the form's Date input. I'm in a real mess, now. First off, the request value leaves the time out. Second off, it's a string, not a timestamp or DateTime object, while it's in request data. Now I'll have to keep digging and may have to do the whole setup differently. Although, even if date_one had been a timestamp, why bother using ts()->getTimestamp() at all? It would have just been converting a timestamp to the same timestamp.
BomAle Posted June 23, 2018 Posted June 23, 2018 I have to test it but I was wrong about ts()->getTimestamp() because getTimestamp don't consider timezone. http://sandbox.onlinephpfunctions.com/code/4591472c67cd08602540e518178fc2720b3a0f61
Midnight Modding Posted June 23, 2018 Author Posted June 23, 2018 7 hours ago, BomAle said: I have to test it but I was wrong about ts()->getTimestamp() because getTimestamp don't consider timezone. http://sandbox.onlinephpfunctions.com/code/4591472c67cd08602540e518178fc2720b3a0f61 Thanks. I actually ended up in yet another mess. I was doing this from a form using the ip.suite form helper and didn't realize it splits up the date and time into 2 elements of the request array. And ts() is for when you have a timestamp, not strings. So I ended up in a mess on this. I'm leaning towards just doing my checks in the $values = $form->values checks where all dates will already be DateTime objects, from IPS converting. It would have been kind of nicer if I could do it in each date input's individual validation check, but then I'd be replicating the work IPS already does for us....
BomAle Posted June 24, 2018 Posted June 24, 2018 You can handle it inside $val = time(); if($values = $form->values()) { if(!isset($vales['date']) or $val <= $vales['date']->getTimestamp()) { throw new \InvalidArgumentException('form_date_bad'); } } //OR if($values = $form->values(TRUE)) { if(!isset($vales['date']) or $val <= $vales['date']) { throw new \InvalidArgumentException('form_date_bad'); } }
Midnight Modding Posted June 25, 2018 Author Posted June 25, 2018 13 hours ago, BomAle said: You can handle it inside $val = time(); if($values = $form->values()) { if(!isset($vales['date']) or $val <= $vales['date']->getTimestamp()) { throw new \InvalidArgumentException('form_date_bad'); } } //OR if($values = $form->values(TRUE)) { if(!isset($vales['date']) or $val <= $vales['date']) { throw new \InvalidArgumentException('form_date_bad'); } } By doing it in the if($values = $form->values()) area, the main problem is then it would not be listing the error beside the appropriate field on the form. I first thought you were saying to do that in every individual validation check, but that wouldn't work because then it would be an infinite loop, I think. So really my only options are do it in that area and have an error above the form or in each validation check I'd have to do all of the work IUPS normally does and do it an extra time.... taking the date, time, and get timezone and all that stuff. So, i think really I just have to do it in the if($values = $form->values()) check and put an error above form...
HeadStand Posted June 25, 2018 Posted June 25, 2018 12 hours ago, Midnight Modding said: By doing it in the if($values = $form->values()) area, the main problem is then it would not be listing the error beside the appropriate field on the form. That's what the customValidationCode is for. Set up your field as follows: $timeNow = time(); $form->add( new \IPS\Helpers\Form\Date( 'date_one', null, true, array(), function( $val ) use ( $timeNow ){ if( $val instanceof \IPS\DateTime && $timeNow <= $val->getTimestamp() ) { throw new \InvalidArgumentException( 'form_date_bad' ); } } ) ); The callback argument after the options array can be used to run special validation on your field. If an exception is thrown there, the error message is displayed directly below the input field. Edit: you don't need to check for an empty value if the field is marked required.
Midnight Modding Posted June 25, 2018 Author Posted June 25, 2018 12 minutes ago, HeadStand said: That's what the customValidationCode is for. Set up your field as follows: $timeNow = time(); $form->add( new \IPS\Helpers\Form\Date( 'date_one', null, true, array(), function( $val ) use ( $timeNow ){ if( $val instanceof \IPS\DateTime && $timeNow <= $val->getTimestamp() ) { throw new \InvalidArgumentException( 'form_date_bad' ); } } ) ); The callback argument after the options array can be used to run special validation on your field. If an exception is thrown there, the error message is displayed directly below the input field. Edit: you don't need to check for an empty value if the field is marked required. That's not the issue. I've done that many times, know about use(), know how to do the validation check, etc... What I am trying to do here is compare multiple Date inputs, not simply compare to time(). In that anonymous function, it does not have access to the other form inputs. I am trying to compare dateOne to dateTwo, for instance. But during these callback functions they only have access to that one field's value. Thus why I was trying to compare to request data to be able to compare multiple form inputs. That is very easy on most input types, but for Date ones, I'd have to do a lot more work and that work would be a waste, too, as it would be the same work already being done in the other validation checks by IPS. Thus why I am considering doing it in the $values = $form->values() where they are all there for me. If I did it with those individual validation checks, I'd have to take the request data date, the request data _time, get the user timezone, etc etc. Basically repeating what IPS will already be doing.
Recommended Posts
Archived
This topic is now archived and is closed to further replies.