Drupal 7.8 install
Site Timezone set to America/New_York in the region settings
I have this code in a page callback
Problem happens on multiple servers
format_date() is not adjusting for the timezone offset by either the default site timezone, or even when I add the timezone string as an argument.
Below is the code, and at the bottom of the code is the output commented out. There are 2 examples using format_date, and the last example is what I had to do to get the correct time to display.
Any ideas on how to get format_date() working with the timezone?
header('content-type: text/plain');
// utc_str as it would come from the db of a date field
$utc_str = '2011-09-01 14:00:00';
// converting to a unix timestamp
$timestamp = strtotime($utc_str);
// first print with format_date, note default site timezone is America/New_York
print 'format_date($timestamp, "custom", "Y-m-d h:s:i"): '. format_date($timestamp, 'custom', 'Y-m-d h:s:i') ."\n";
// next print date by actually setting the timezone string in the argument
// Result:
$tz_str = 'America/New_York';
print 'format_date($timestamp, "custom", "Y-m-d h:s:i", "America/NewYork"): '. format_date($timestamp, 'custom', 'Y-m-d h:s:i', $tz_str) ."\n";
// this is the only way i could get it working
$date = new DateTime($product->field_class_date['und'][0]['value'], new DateTimeZone(date_default_timezone_get()));
$offset = $date->getOffset();
$formatted = date('Y-m-d h:s:i', ($timestamp + $offset));
print $formatted;
/** This is the output
format_date($timestamp, "custom", "Y-m-d h:s:i"): 2011-09-01 02:00:00
format_date($timestamp, "custom", "Y-m-d h:s:i", "America/NewYork"): 2011-09-01 02:00:00
2011-09-01 10:00:00
*/
The way you have solved it is correct. If you use PHP 5.3 or higher you can use the DateTime::add method and simply add the offset, without making a timestamp from it like i did below.
$utcTimezone = new DateTimeZone('UTC');
$timezone = new DateTimeZone('America/New_York');
$dateTime = new DateTime('2011-09-01 14:00:00', $timezone);
$offset = $timezone->getOffset($dateTime);
print date('Y-m-d H:i:s', $dateTime->format('U') + $offset);
Related
I need to extract the date part from a file in unix and add +1 day to the date and rename the file with the new date in it.
for ex:
sample file name: sample_file_name_01_31_2022_14_01_45_loadid.csv
I tried to extract the timestamp using substr which gives 01_31_2022_14_01_45. Now, the new date should be 02_01_2022_14_01_45 and the new file name should be sample_file_name_02_01_2022_14_01_45_loadid.csv
Given the AIX operating environment, which doesn't have GNU date installed by default (for the handy date -d ... functionality), I'd approach this problem with a perl script. The script below uses fairly common modules that should be available on an AIX system.
The basic idea behind the script is to loop over every given argument (one or more filenames) and:
extract the date/time fields from the filename
convert those fields into seconds-since-the epoch
add one day's worth of seconds
convert that new timestamp into the desired string format
rename the file
I encountered a slight complication while adding error-checking: the timelocal() function will croak (exit the script) if any of the given date/time fields are out of range. Because I wanted to be able to loop over any remaining arguments, I had to wrap that call in a Try-Catch block.
#!/usr/bin/perl -w
use strict;
use POSIX qw(strftime);
use Time::Local qw(timelocal);
use Try::Tiny;
sub rename_a_file {
my $filename = shift;
# extract date from filename
my ($prefix, $month, $day, $year, $hour, $minute, $second, $suffix);
unless (
($prefix, $month, $day, $year, $hour, $minute, $second, $suffix) =
$filename =~ /^(.*)_(\d{2})_(\d{2})_(\d{4})_(\d{2})_(\d{2})_(\d{2})_(.*)$/
) {
warn "Could not determine a timestamp from ${filename}; skipping\n";
return undef;
}
# local time in seconds-since-the-epoch
my $t;
# timelocal will die if any inputs are out of range; catch it
my $flag = 0;
try {
$t = timelocal($second, $minute, $hour, $day, $month - 1, $year - 1900);
} catch {
warn "Unable to convert time specification: $_";
$flag = 1;
};
return undef if $flag;
# add one day's worth of seconds
$t += 24 * 60 * 60;
# new timestamp in string format
my $newdate;
unless ($newdate = strftime("%m_%d_%Y_%H_%M_%S", localtime $t)) {
warn "Unable to convert new date to a string format: $!";
return undef;
}
# rename file using new date
unless (rename $filename, "${prefix}_${newdate}_${suffix}") {
warn "Unable to rename $filename: $!";
return undef;
}
return 1;
}
my $errors = 0;
for (#ARGV) {
unless (rename_a_file($_)) {
warn "Unable to rename: $_\n";
++$errors;
}
}
$errors = 255 if $errors > 255;
exit $errors;
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
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']))
$client = $this->solr->getClient();
$query = $client->createSelect();
$facetSet = $query->getFacetSet();
$facetSet->createFacetField('id')->setField('publication_year');
$facet = $facetSet->createFacetRange('yearsranges');
$facet->setField('publication_year');
$facet->setStart( --MIN DATE VALUE-- );
$facet->setGap( --I NEED TO MAKE RANGE OF 10 YEARS-- );
$facet->setEnd( --NOW DATE TIME-- );
$solrQuery = '*:*';
$query->setQuery($solrQuery);
$query->setRows(0);
$data = $client->select($query)->getFacetSet()->getFacet('yearsranges');
dump($data);
die;
Let first ask you, if it is valid to make ranges of dates in solr facets
"publication_year" field in solr collection. This date is actually a string in this format.
"2009-10-29T23:00:00Z"
Yes it's valid or just use a query filter:
$createQuery->createFilterQuery('range')->setQuery('createdate:[1995-12-31T23:59:59.999Z TO 2007-03-06T00:00:00Z]');
For a facet:
$facet->createQuery('createdate:[1995-12-31T23:59:59.999Z TO 2007-03-06T00:00:00Z]');
I'm using FullCalendar to load events from custom post types on WP, through a JSON feed. It's working, but it's taking some time to load. Please check here: http://cea3.iscte.pt/en/agenda-3/ (june or august). Do any of you have a clue what can be causing it?
This is the full code for the JSON feed:
<?php
// - standalone json feed -
header('Content-Type:application/json');
// - grab wp load, wherever it's hiding -
if(file_exists('../../../../wp-load.php')) :
include '../../../../wp-load.php';
else:
include '../../../../../wp-load.php';
endif;
global $wpdb;
// - grab date barrier -
$oneyear = strtotime('-1 year') + ( get_option( 'gmt_offset' ) * 3600 );
// - query -
global $wpdb;
$querystr = "
SELECT *
FROM $wpdb->posts wposts, $wpdb->postmeta metastart, $wpdb->postmeta metaend
WHERE (wposts.ID = metastart.post_id AND wposts.ID = metaend.post_id)
AND (metaend.meta_key = 'tf_events_enddate' AND metaend.meta_value > $oneyear )
AND metastart.meta_key = 'tf_events_enddate'
AND wposts.post_type = 'tf_events'
AND wposts.post_status = 'publish'
ORDER BY metastart.meta_value ASC LIMIT 500
";
$events = $wpdb->get_results($querystr, OBJECT);
$jsonevents = array();
// - loop -
if ($events):
global $post;
foreach ($events as $post):
setup_postdata($post);
// - custom variables -
$custom = get_post_custom(get_the_ID());
$sd = $custom["tf_events_startdate"][0];
$ed = $custom["tf_events_enddate"][0];
// - grab gmt for start -
$gmts = date('Y-m-d H:i:s', $sd);
$gmts = get_gmt_from_date($gmts); // this function requires Y-m-d H:i:s
$gmts = strtotime($gmts);
// - grab gmt for end -
$gmte = date('Y-m-d H:i:s', $ed);
$gmte = get_gmt_from_date($gmte); // this function requires Y-m-d H:i:s
$gmte = strtotime($gmte);
// - set to ISO 8601 date format -
$stime = date('c', $gmts);
$etime = date('c', $gmte);
$thetitle = $post->post_title;
$short_title = substr($thetitle,0,50);
$eventpostid = $post->ID;
$eventslug = wp_get_post_terms( $eventpostid, 'tf_eventcategory' );
$eventvenueslug = $eventslug[0]->slug;
$tf_events_link = get_post_meta($post->ID, 'tf_events_link', true);
$tf_events_permalink = get_permalink($post->ID);
if ($tf_events_link) { $url_event = $tf_events_link ; }
else { $url_event = $tf_events_permalink; };
// - json items -
$jsonevents[]= array(
'title' => $short_title . '...',
'allDay' => false, // <- true by default with FullCalendar
'start' => $stime,
'end' => $etime,
'url' => $url_event,
'className' => $eventvenueslug
);
endforeach;
else :
endif;
// - fire away -
echo json_encode($jsonevents);
?>
Thank you.
It does seem like it takes a few seconds to load.
I use this calendar and it takes about 2-6 seconds to load- The longest was 6 seconds but i had about 3 sources and ~40 events.
Now I am not sure if that for you is a long time because you did not specify how long it actaully takes.
It looks like the call is on the same server so the only problem can be the SQL that takes long to reply. Is it dedicated or shared server?
Your PHP looks fine and should execute quickly. I have similar logic using .NET and SQL Server.
This is the time it takes to load your calendar from my side of the world.
The only other way to speed it up is to use Caching
http://arshaw.com/fullcalendar/docs/event_data/events_json_feed/#options
and manage it to reload the source somehow with a clever check of the date? or something.
I am sure the times would be reduced to ms once the feed has been loaded before.
You would have to do something clever like load the current month quickly - and in the background load 1 year or 2 years and cache it. Then when you change months it will be instant because its in memory.