I am trying to iterate all dates in twig
I have tried using this:
{% for x in range(startDate|date('U'), endDate|date('U'), 86400 ) %}
{{ x|date('m/d') }}
{% endfor %}
It worked in some dates.
but if my startDate is 10/01/2015 and endDate is 10/31/2015
10/25 is displayed twice.
the scenario can be replicated on octobers of any year on 4th sundays
I don't know if it's only me that can replicate this.
Is there any other way to iterate all dates in range in twig?
The \DatePeriod class was created for exactly this purpose, and it's available since php5.3.
$start = DateTime::createFromFormat("Y-m-d", "2015-10-01");
$end = DateTime::createFromFormat("Y-m-d", "2015-11-01");
$interval = new DateInterval("P1D");
$range = new DatePeriod($start, $interval, $end);
foreach ($range as $date) {
var_dump($date->format("Y-m-d"));
}
You can try it at: https://3v4l.org/vFsb6
Related
I am trying to build a WTForm to add elements into a SQLite Table. The table has only two cols (id and name)
routes.py:
#app.route('/systems', methods=['GET', 'POST'])
def systems():
form = SystemForm()
if form.validate_on_submit():
system = Systems(name=form.systemname.data)
db.session.add(system)
db.session.commit()
return redirect(url_for('systems'))
return render_template('systems.html', title='Systems', form=form)
forms.py:
class SystemForm(FlaskForm):
systemname = StringField('System', validators=[DataRequired()])
submit = SubmitField('Add')
But before the form I want to display all the rows already present in table:
system 1
system 2
....
textfield / submit button
How can I accomplish this supposed I can grab the rows by the following:
database = "mydb.db"
conn = create_connection(database)
cur = conn.cursor()
cur.execute("SELECT * FROM systems")
data = cur.fetchall()
Will have the list to be part of the form definition? Or can be put before the form tag like the following (being data the returned rows from the sqlite query):
{% for item in data %}
<table>
<tr>
<td>{{item[1]}}</td>
</tr>
</table>
{% endfor %}
How can i pass data to the html template?
It seems that you have already done everything, the only thing to do is;
#app.route('/systems', methods=['GET', 'POST'])
def systems():
form = SystemForm()
if form.validate_on_submit():
system = Systems(name=form.systemname.data)
db.session.add(system)
db.session.commit()
return redirect(url_for('systems'))
# perform your database lookup to get `data`
return render_template('systems.html', title='Systems', form=form, data=data)
#app.route('/systems', methods=['GET', 'POST'])
def systems():
if request.method == 'POST':
if request.form.get('submit') == 'Add':
form = SystemForm()
if form.validate_on_submit():
system = Systems(name=form.systemname.data)
db.session.add(system)
db.session.commit()
return redirect(url_for('systems'))
else:
delete_ids = request.form.getlist('delete_id')
for delete_id in delete_ids:
db.session.query(Systems).filter(Systems.id==delete_id).delete()
db.session.commit()
data = db.session.query(Systems)
form = SystemForm()
return render_template('systems.html', title='Systems', form=form, data=data)
There is a Datetime object as following and I want to get the date value
Array
(
[0] => Array
(
[value] => Drupal\Core\Datetime\DrupalDateTime Object
(
[formatTranslationCache:protected] =>
[inputTimeRaw:protected] =>
[inputTimeAdjusted:protected] =>
[inputTimeZoneRaw:protected] =>
[inputTimeZoneAdjusted:protected] =>
[inputFormatRaw:protected] =>
[inputFormatAdjusted:protected] =>
[langcode:protected] => en
[errors:protected] => Array
(
)
[dateTimeObject:protected] => DateTime Object
(
[date] => 2018-01-05 01:30:00.000000
[timezone_type] => 3
[timezone] => UTC
)
[stringTranslation:protected] =>
)
)
)
I don't want to get this value by $node->get("field_id")->value;
Because I need dynamic value that means the value should change after I changed date field.
Is it possible?
Figured it out
$date = $form_state->getValue('field_id')[0]['value']->format('Y-m-d H:i:s')
it returns string !!
The point is locate the Object.
The values in the array are of type Drupal\Core\Datetime\DrupalDateTime, check the API on Drupal.org DrupalDateTime Doc.
In order to get value from the object you must use the __toString method as mentioned.
Proceed as :
$dateTime = YourArray[0]['value'];
$date = $dateTime->_toString();
Else
$date = $dateTime->format('Y-m-d h::i::s');
For more date formats check the PHP doc PHP DATE
Edit 1:
The following Code works correctly :
$temp = new \Drupal\Core\Datetime\DrupalDateTime();
echo $temp->__toString();
echo $temp->format('Y-m-d h::i'); die;
I found that in browsers that do no support
<input type="time">
(i.e. Safari) the value is not of type "Drupal\Core\Datetime\DrupalDateTime" but array.
Here is what i did inside a drupal 8 module to get formatted date from DrupalDateTime
I. If you have a date and want format it, just pass it to the static method of the class (DrupalDateTime) as follows. You can replace the string with your date variables.
Below shows both using the static version and non static version of DrupalDateTime
$date = DrupalDateTime::createFromFormat('j-M-Y', '20-Jul-2019');
// Using the static method prints out: 20-Jul-2019:11:am
$date = new DrupalDateTime('now'); // grab current dateTime using NON static
$date->format('l, F j, Y - H:i'); // format it
// prints out nicely formatted version: Tue, Jul 16, 2019 - 11:34:am
// you can remove H:i and what's after it if you don't want hours or am pm
$date = new DrupalDateTime('now'); // grab current dateTime
// Or print $date->format('d-m-Y: H:i A');
// prints out: 16-07-2019: 11:43 AM
More examples:
$date = new DrupalDateTime();
$date->setTimezone(new \DateTimeZone('America/Chicago'));
print $date->format('m/d/Y g:i a');
// The above prints current time for given Timezone
// prints : 07/16/2019 10:59 am
// Another variations of the above except it takes specific date and UTC zone
$date = new DrupalDateTime('2019-07-31 11:30:00', 'UTC');
$date->setTimezone(new \DateTimeZone('America/Chicago'));
print $date->format('m/d/Y g:i a');
// prints 07/31/2019 6:30 am
To use these in your module/code you need to include the following at the top of your file;
use Drupal\Core\Datetime\DrupalDateTime;
Also note that the DrupalDateTime extends DateTimePlus() which it self "wraps the PHP DateTime class with more flexible initialization parameters.... as per docs..."
How to test it with Drush.
Save the above code in a php script, then let drush run the srcipt after it bootstraps drupal like:
drush -r /path-to-your-drupal-documentRoot -l example.com scr ~/path-to your-script
For multisites make sure you use ... drush -l http.... like above
Note:
I posted similar answer to: https://drupal.stackexchange.com/questions/252333/how-to-get-formatted-date-string-from-a-datetimeitem-object/283529#283529
in my case I use date range with duration
in your case you need the bold one
date('Y-m-d\TH:i:s', strtotime($date->get('field')->getValue()[0]['value']))
date('Y-m-d\TH:i:s', strtotime($date->get('field')->getValue()[0]['end_value']))
The method that I am trying to run is as below where I try iterate through the sub contracts in a GBP and then I have an inner loop to iterate through the coverages in each sub contract.
forEach curSubscribedSubContract in theSubContracts
; Avoid building empty contract node
if subOptions.count > 0
new(ParamProduct)
new(ParamSubscribedProduct)
forEach curOption in subOptions downTo
theProduct = curOption.GetProduct
new(ListOfCoverages)
if Motor.AreSameThings(theProduct, curSubscribedSubContract.GetProduct)
ParamSubscribedProduct.InitParamFromObjectAtDate(curSubscribedSubContract,
AtDate)
ParamProduct.Product = ParamSubscribedProduct
;Set Context for PlanDesign options
AFCI_SLI.CoverageInContext = curOption
covData = self._GetCoverageData(curOption, AtDate)
;Reset coverage context
AFCI_SLI.CoverageInContext = Nil
ListOfCoverages.AppendObject(covData)
if subOptions.RemoveObject(curOption)
endIf
endIf
forEach curCoverageData in ListOfCoverages
ParamProduct.Coverages[-1] = curCoverageData
endFor
dispose(ListOfCoverages)
endFor
_Result[-1] = ParamProduct
endIf
endFor
are items missing from the subcontracts or suboptions?
I think the following line of code has something to do with it:
if subOptions.RemoveObject(curOption)
endIf
I am not sure if it is a good practice to remove objects from a list which is being iterated..
also
try removing the 'down to" from the foreach loop of suboptions
I want to quickly change the ouput format of web2py´s datepicker used in datetime or date fields in forms - or completely disable it. Where can I do this?
Look for the file ´web2py_ajax.html´
<script type="text/javascript"><!--
// These variables are used by the web2py_ajax_init function in web2py_ajax.js (which is loaded below).
var w2p_ajax_confirm_message = "{{=T('Are you sure you want to delete this object?')}}";
var w2p_ajax_disable_with_message = "{{=T('Working...')}}";
var w2p_ajax_date_format = "{{=T('%d.%m.%Y')}}";
var w2p_ajax_datetime_format = "{{=T('%Y-%m-%d %H:%M:%S')}}";
var ajax_error_500 = '{{=T.M('An error occured, please [[reload %s]] the page') % URL(args=request.args, vars=request.get_vars) }}'
//--></script>
{{
response.files.insert(0,URL('static','js/jquery.js'))
response.files.insert(1,URL('static','css/calendar.css'))
response.files.insert(2,URL('static','js/calendar.js'))
response.files.insert(3,URL('static','js/web2py.js'))
response.include_meta()
response.include_files()
}}
Change var w2p_ajax_date_format for a different date format or edit the response.files-lines.
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.