Is there a way of converting a time, say 17:00 to 5:00pm using Zend Locale?
I've tried the method in the docs as it is (which has a typo), but it doesn't work. It gives the error 'Unable to parse date '13:44:42' using 'dd.MM.yyyy' (M <> y)'
$locale = new Zend_Locale('de_AT');
if (Zend_Locale_Format::getTime('13:44:42',
array('date_format' =>
Zend_Locale_Format::STANDARD,
'locale' => $locale))) {
print "time";
} else {
print "not a time";
}
I then tried a 2 step method, getting the time format of the current locale first, and then using that in the getTime function.
$locale = new Zend_Locale('en_US');
$tf = Zend_Locale_Format::getTimeFormat($locale);
$test = Zend_Locale_Format::getTime('17:00', array('date_format' => $tf, 'locale' => $locale));
This returns a result but just gives me back what I had
array('date_format'=>'h:mm:ss a', 'locale'=>'en_US', 'hour'=>'17', 'minute'=>'00')
Is there something that will convert the time to the actual locale I'm trying to parse it to?
You need to be using Zend_Date with the locale to get the date in the format you want.
$date = new Zend_Date(); // Default ISO format type & en_US
// Set the time and pass the format I am using to set the time
$date->setTime('17:00:00', 'HH:mm:ss');
echo $date; // Jul 15, 2011 5:00:00 PM
EDIT
More on how you can use Zend_Locale with Zend_Date
$locale = new Zend_Locale('de_AT');
echo $date->toString(Zend_Locale_Format::getTimeFormat($locale)) ; // 17:00:00
$locale = new Zend_Locale('en_US');
echo $date->toString(Zend_Locale_Format::getTimeFormat($locale)) ; // 5:00:00 PM
Related
I am having trouble comparing DateTime objects in my Catalylst. I have an end_date column which is being inflated by DBIx::Class::InflateColumn::DateTime, and I am inflating it with my timezone:
__PACKAGE__->add_columns(
end_date => { data_type => 'datetime', time_zone => 'America/Chicago' },
);
I have a function that is supposed to tell me if my event has closed or not, this is defined in my Schema for this class:
sub closed {
my ($self) = #_;
my $now = DateTime->now(time_zone => 'America/Chicago');
warn DateTime->compare($now, $self->end_date);
warn $now;
warn $self->end_date;
return DateTime->compare($now, $self->end_date) == 1;
}
However, it is not working properly. It is telling me that events have closed before they actually have. Here is an example output from the warns:
1
2014-06-29T12:20:48
2014-06-29T12:20:50
As you can see, it is saying that the first date is greater than end_date, even though it is not. I haven't been able to figure out why this is. However, whenever I convert them and create new DateTime objects:
sub closed {
my ($self) = #_;
my $now = DateTime::Format::ISO8601->parse_datetime(DateTime->now(time_zone => 'America/Chicago'));
my $end_date = DateTime::Format::ISO8601->parse_datetime($self->end_date);
return DateTime->compare($now, $end_date) == 1;
}
Then they compare correctly, and compare returns -1. Does anyone know why this could be?
Your debugging information is useless since you didn't include the time zone offsets (e.g. by using ->strftime('%FT%T%z')). If you did, I bet you'll find the first date is indeed greater than the end date, and I bet it's using UTC for your inflated column.
Looking at the docs, the time zone is to be provided by the timezone attribute, but you used time_zone.
{ data_type => 'datetime', timezone => "America/Chicago", locale => "de_DE" }
(That was a poor, confusing choice on D::C::IC::DT's behalf.)
I'm trying to generate an ICal feed using Data:ICal but some events are printed without a time. I've read that the time is not required if it's 000000 but Google Calendar does not handle those events without a time properly.
Here is an example script and output. I need the output to to be in the UTC timezone.
#!/usr/bin/perl -w
use strict;
use Date::ICal;
use Data::ICal;
use Data::ICal::Entry::Event;
use DateTime;
use Data::Dumper;
sub get_utc_offset($) {
my ($orig_tz_str) = #_;
# Using a set winter date to avoid problems with daylight savings time
my $utc_compare_datetime = DateTime->new(
year => 2012,
month => 1,
day => 1,
hour => 1,
minute => 1,
time_zone => 'UTC'
);
my $tz = DateTime::TimeZone->new(name => $orig_tz_str);
my $utc_offset = $tz->offset_for_datetime($utc_compare_datetime);
my $utc_offset_str = DateTime::TimeZone->offset_as_string($utc_offset);
return $utc_offset_str;
}
sub add_ical_event($$$$$$) {
my ($calendar, $start, $end, $summary, $description, $timezone) = #_;
my $offset = get_utc_offset($timezone);
$description = 'none' if (!$description);
my $event = Data::ICal::Entry::Event->new();
$event->add_properties(
summary => $summary,
description => $description,
dtstart => Date::ICal->new( ical => $start, offset => $offset )->ical,
dtend => Date::ICal->new( ical => $end, offset => $offset )->ical,
dtstamp => Date::ICal->new( epoch => time )->ical
);
$calendar->add_entry($event);
}
# Tests
# ----------------------------------------------------------------------------
my $timezone = 'America/New_York';
my $calendar = Data::ICal->new();
$calendar->add_properties(
method => "PUBLISH",
prodid => "-//Test Cal//NONSGML Calendar//EN",
'X-WR-CALNAME' => 'Test Cal'
);
my (%events) = (
1 => {
summary => 'Test Shift Tool - Testing Shift',
description => '',
start => '20130828T160000',
end => '20130828T190000',
timezone => $timezone
},
2 => {
summary => 'New Member Meeting',
description => '',
start => '20130722T190000',
end => '20130722T210000',
timezone => $timezone
},
3 => {
summary => 'public',
description => '',
start => '20130630T130000',
end => '20130630T140000',
timezone => $timezone
}
);
foreach my $key (sort keys %events) {
my $e = $events{$key};
add_ical_event(
$calendar,
$e->{start},
$e->{end},
$e->{summary},
$e->{description},
$e->{timezone}
);
}
print $calendar->as_string;
Notice that some events have start or end dates without a time. When I manually add T000000Z, those events are imported properly to Google Calendar. Any suggestions on how to force all events to have a time?
BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
PRODID:-//Digital Cheetah//NONSGML Calendar//EN
X-WR-CALNAME:Digital Cheetah
BEGIN:VEVENT
DESCRIPTION:none
DTEND:20130829Z
DTSTAMP:20130823T214317Z
DTSTART:20130828T210000Z
SUMMARY:Test Shift Tool - Testing Shift
END:VEVENT
BEGIN:VEVENT
DESCRIPTION:none
DTEND:20130723T020000Z
DTSTAMP:20130823T214317Z
DTSTART:20130723Z
SUMMARY:New Member Meeting
END:VEVENT
BEGIN:VEVENT
DESCRIPTION:none
DTEND:20130630T190000Z
DTSTAMP:20130823T214317Z
DTSTART:20130630T180000Z
SUMMARY:public
END:VEVENT
END:VCALENDAR
I've read that the time is not required if it's 000000
That's not what the RFC says. Let's refer to the following sections:
4.3.4 Date
4.3.5 Date-Time
4.8.7.2 Date/Time
I'll quote the relevant format specifications, here:
date = date-value
date-value = date-fullyear date-month date-mday
date-fullyear = 4DIGIT
date-time = date "T" time ;As specified in the date and time
;value definitions
dtstamp = "DTSTAMP" stmparam ":" date-time CRLF
When your output includes a DTSTAMP, the ICal specification expects a date-time following it.
Which brings us to Date::ICal and its ical method. Does it return an iCal date or a date-time? As it turns out, it tries to guess which format you want by checking whether your timestamp has a time of 000000. See for yourself at line 286 of ICal.pm.
It could be that we expect Data::ICal::Entry to handle this scenario. I could be missing validation code on that end, but at the moment I'm not seeing anything that's obviously relevant. It looks like it accepts the property values without checking them.
Depending on your perspective, this sounds like a bug or a limitation of the libraries.
So... how should you fix this? Ideally, one of these libraries should probably check for and handle this scenario. In the meantime, though, you need to get back on your feet:
Quick and dirty fix: if your time is zero, bump it by one second; ical will now return a valid but slightly inaccurate date-time string.
A little better: check the return value from ical; if it's a date, reformat it as a date-time.
Test this before using it, but maybe something like this:
dtstart => $ical =~ s/(\d{8})Z/$1T000000Z/r;
I have two problems in my little script. I am trying to create an application that use Zend Framework 1.12.1, Doctrine, Zend_locale, Zend_Currency and Zend_Date.
Dates:
The database needs a date in this format Y-m-d H:i:s but each user set their locale preferences in the custom control panel. So when I get a date from the database I have to convert it in the locale choosen.
This is my code:
<?php
$dboutdata = "4/3/13 12:00 AM"; // 4 March 2013 12:00 AM
$date = new Zend_Date($dboutdata, null, "en_US");
echo $date . "<br/>";
$date = new Zend_Date($dboutdata, null, "it_IT");
echo $date . "<br/>";
?>
this is the result:
Apr 3, 13 12:00:00 AM
04/mar/13 12.00.00
As you can see the result is wrong. Zend_Date confuses the month with the day. How have I to solve this problem?
updates:
/**
* Convert a date from yyyy/mm/dd formatted by the locale setting
*
* #param date $dbindata
* #return date formatted by the locale setting
*/
static public function formatDateOut($dbindata) {
if (empty ( $dbindata ))
return false;
$locale = Zend_Registry::get('Zend_Locale');
$date = new Zend_Date($dbindata, "yyyy-MM-dd HH:mm:ss", $locale);
return $date->toString(Zend_Date::DATETIME_SHORT, $locale);
}
/**
* Convert a date from Zend Locale selected to yyyy/mm/dd H:i:s
*
* #param string $dboutdata
* #return string Y-m-d H:i:s
*/
static public function formatDateIn($dboutdata) {
if (empty ( $dboutdata ))
return null;
$InDb = null;
$locale = Zend_Registry::get('Zend_Locale');
$date = new Zend_Date($dboutdata);
return $date->toString('yyyy-MM-dd HH:mm:ss');
}
Furthermore, If I need to save this date how can I normalize it in order to save it in the database?
Best Regards
By passing the locale into the Zend_Date constructor, you're telling it what format the date is in. The US date format has the month first, where as the European date format has the day, so that's why you get different results.
You probably just want to set the locale when outputting the date, e.g.:
$dboutdata = "4/3/13 12:00 AM";
$date = new Zend_Date($dboutdata, null, "en_US");
echo $date->toString(null, 'en_US') . '<br>'; // outputs Apr 3, 13 12:00:00 AM
echo $date->toString(null, 'it_IT') . '<br>'; // outputs 03/apr/13 00.00.00
I am using the Zend Framework Gdata for the Google Calendar API and the datetime outputs in RFC3339 (which looks like this: 2012-01-19T22:00:00.000-08:00). What php code do I need to add in order to convert that to UTC so that it looks like this: January 19, 2012 8pm-11pm ? I have found php code that converts RFC dates to string, but I don't know enough about php to be able to alter the code to work with the Zend Gdata formulas... as you will see in my code below, the "date" is referred to as "when"... so any code will have to connect those two somehow... any help is appreciated!
<?php
$path = '/home/ZendGdata/library';
$oldPath = set_include_path(get_include_path() . PATH_SEPARATOR . $path);
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Calendar');
// User whose calendars you want to access
$user = 'my#email.com';
$pass = 'mypassword';
$service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME; // predefined service name for calendar
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$service = new Zend_Gdata_Calendar($client);
$query = $service->newEventQuery();
// Set different query parameters
$query->setUser('mycalendarID');
$query->setVisibility('private');
$query->setProjection('full');
$query->setOrderby('starttime');
// Start date from where to get the events
$query->setStartMin('2012-01-01');
// End date
$query->setStartMax('2050-03-15');
// Get the event list
try {
$eventFeed = $service->getCalendarEventFeed($query);
} catch (Zend_Gdata_App_Exception $e) {
echo "Error: " . $e->getMessage();
}
echo "<ul>";
foreach ($eventFeed as $event) {
echo "<tr>";
foreach ($event->when as $when) {
echo "<td>" . $when->startTime . "</td>";
}
echo "<td>" . $event->content . " </td>";
$where=$event->Where;
foreach($where as $eventplace)
{
echo "<td>" . $eventplace . " </td>";
}
}
echo "</tr>";
echo "</ul>";
?>
Thank you for this information #vascowhite.
Two issues:
The output turned out like this:
string(23) "20 January 2012: 06:00"
I am pulling this info from my google calendar, and it is outputting into my html page...I am not not creating new events through this php...so this code simply converted the date that you wrote, it didn't convert my google calendar event date which is pulled from this code:
foreach ($event->when as $when) {
echo "<td>" . $when->startTime . "</td>";
}
Do you know how to do that?
Thank you,
Susan
You can use PHP's DateTime class to do this quite easily.
First create a DateTime object from your time string:-
$timestr = '2012-01-19T22:00:00.000-08:00';
$date = new DateTime($timestr);
That object is in the correct time zone because of the '-08:00' part of the string.
Now decide which time zone you want to convert to and create a DateTimeZone object (I have chosen UTC as you specifically mention it):-
$tz = new DateTimeZone('UTC');
$date->setTimezone($tz);
Your DateTime object has now been converted to the UTC time zone.
You can get it into your desired format by using the DateTime::format() method:-
var_dump($date->format('d F Y: H:i'));
Output:
20 January 2012: 06:00
To fit into your code:-
foreach ($event->when as $when) {
$date = new DateTime($when->startTime);
echo "<td>" . $date->format('d F Y: H:i') . "</td>";
}
I'd like to use Zend_Date to print out the previous 2 months and year as a string e.g.:
July 2009
June 2009
I need it to be locale aware so that if the code runs with the locale set to, say, German, the month names will print in German.
$date = new Zend_Date();
$date->subMonth(1);
echo $date->get(Zend_date::MONTH_NAME).' '.$date->get(Zend_Date::YEAR);
$date->subMonth(1);
echo $date->get(Zend_date::MONTH_NAME).' '.$date->get(Zend_Date::YEAR);
Is this all I need to do?
thanks
You can just use the optional locale parameter in the get method:
$date = new Zend_Date();
echo $date->get(Zend_Date::MONTH_NAME,'de_DE');
echo $date->get(Zend_Date::MONTH_NAME,'en_UK');
Specify the locale when creating the Zend_Date object. Like this:
$date = new Zend_Date(new Zend_Locale('de_AT'));
$date->subMonth(1);
echo $date->get(Zend_date::MONTH_NAME).' '.$date->get(Zend_Date::YEAR);
$date->subMonth(1);
echo $date->get(Zend_date::MONTH_NAME).' '.$date->get(Zend_Date::YEAR);