几天来,我一直在思考以下难题。
我基本上有以下复杂的 mySQL 表:
| ID | TITLE | DESCRIPTION | EVENT | DATE |
|----|--------------|-------------------|-------|-------------------------|
| 1 | Big painting | 3-day work | No | 03/10/2013 |
| 2 | Meeting | With reps. | Yes | 02/15/2013 09:00 -05:00 |
| 3 | Presentation | 5 paintings | Yes | 08/02/2013 22:00 +02:00 |
| 4 | Round paint. | One week | No | 04/05/2013 |
| 5 | Conference | On Picasso | Yes | 04/22/2013 18:00 -05:00 |
(编辑:也许我需要澄清 DATE 列未设置为 DATE 或 DATETIME [由于需要在数据中包含时区],而是设置为 VARCHAR,这就是组织从一开始就复杂的原因。)
如您所见,它是一个包含画家所有“最新消息”项目的表格。这个想法是,在这个画家的网站上,PHP 将调用值,以便将它们显示为“最新消息”新闻代码。
所有的基础知识都在那里,但我遇到了障碍。
最初,我想在 SELECT 阶段过滤和排序我的数据,但我在这样做时遇到了麻烦。如您所见,事件和非事件项都有日期,但非事件项只是将它们作为组织整体数据的一种方式。特定的日期和时间仅对事件很重要,因为这样用户将能够知道这些事情何时发生。所以基本的想法是从表中挑选出一定数量的最新项目。因此,将从表中读取所有项目,按 DATE 顺序放置,然后,例如,其中 20 个将被取出。
正如我所说,我最初想在 SELECT 阶段这样做,但我认为它可能太复杂了。所以我只是提取了所有项目并在它们之后设置了一个 PHP 代码以过滤它们。
因此,当我尝试订购日期时,就会出现障碍。我正在尝试将日期转换为订购过程的时间戳,然后返回显示日期。但是,我无法使日期时间戳或时间戳日期(或两者)转换工作。我总是以与我开始时不同的日期结束。
正如您所看到的,由于时区,整个事情变得更加复杂,这非常重要,因为用户必须能够知道这些事情发生在哪里,或者更确切地说,根据它们发生的时间,知道它们发生在什么时间。
我试过像这样简单地来回转换:
$timestamped = strtotime($date);
$datetimed = date('m/d/Y h:i P',$timestamped);
而且它不起作用,所以我猜它与我在表中使用的日期格式有关。
所以我尝试了这个:
$var = DateTime::createFromFormat('m/d/Y H:i P',$date)->getTimestamp();
无济于事,还是...
我在想也许我应该在流程开始时设置时间戳,即在插入数据项时。但是,在这里,我也需要将“人类”日期转换为时间戳,如果我不能正确管理它,那么什么都不会正常工作。
我知道这个问题很复杂,也许我的解释不是最清楚的!也许输出示例可能会有所帮助。我想要实现的是“最新消息”新闻行情,其中包括正在发生的事情的列表:其中一些只是信息(比如状态更新,比如说)没有可见的日期(这里的日期仅适用于内部组织; 这是 EVENT 列的用武之地,因为它过滤了哪些项目必须显示其日期,哪些不能)、其他、邀请用户参加的实际事件以及向用户显示其日期的事件。我什至有一个代码可以计算日期和时间是过去还是未来,以便在那些尚未过去的事件上显示“即将到来”标签。但是,我在处理日期和订购日期时遇到了麻烦。
这就是这个例子最后应该或多或少的样子:
任何和所有的帮助将不胜感激!(以及关于你们认为处理此数据检索/组织过程的最实用和最干净/优雅/专业的方式的反馈......如果在数据输入,如果在 mySQL SELECT 阶段,如果稍后等等。 )
PS我可能会在处理其他数据的同一张表中添加它。这个特定的“最新消息”数据由 SELECT 函数选择,该函数在将为此特定“最新消息”新闻代码检索的任何行中查找特定的 WHATSNEW 列以具有 TRUE 值。
解决方案(虽然没有回答)
因为问题是关于将时间和时区组织为一个字符串,所以可以这么说,那么我不确定我能否将这两个很好的答案中的任何一个标记为针对该特定问题的正确答案。我最终所做的是剥离时区并将它们放在单独的列中。然后我将日期列格式化为日期时间。所以我解决了这个问题,因为 mySQL Select 可以为我处理订单。现在,关于时区,我最终作弊了:我认为我们的“艺术家”不可能同时出现在两个不同时区的两个活动中,所以,真的,我们不太可能需要订购两个事件如此接近,以至于每个事件的时区都会产生真正的差异,而这首先发生。所以我只是让事情按日期排序,然后制作一个片段来处理时区并将它们变成“GMT+1”、“GMT-5”显示,这样用户就会知道那个位置在哪里当地时间。我最终使用DateTime::createFromFormat()->getOffset()
,我现在看到我的第二个回答者推荐了它,并说我走在正确的轨道上,所以我很高兴我把它放在那里 为了进一步澄清这一点,我添加了一个 Location 列,网站管理员可以在其中指定城市,说“巴黎”,说“伦敦”,等等。所以用户最终会得到与我的示例中显示的非常相似的东西,除了它会说... (Paris, GMT+1)
等等。
无论如何,对于那些遇到完全相同的问题并最终想到完全相同的事情并且这种方式更实用的人来说,这里是我最终得到的代码的核心。剩下的只是“填写”。享受!感谢两位亲爱的人,他们很友善地抽出时间来帮助我找到解决这个问题的方法!(我可能有一个额外的}
......对不起。将它粘贴到 SO 时重新格式化真的很乏味!我已经修改了两次代码,但找不到任何问题。)
if(isset($item) && $item['event'] == '1') {
$event = $item['event'];
$date = $item['date'];
$date_array = date_parse($date);
$minute = $date_array['minute'];
if($minute<10) {
$minute = '0'.$minute;
}
$timezone = $item['timezone'];
if($timezone!=='') {
$timezone = DateTime::createFromFormat('P',$timezone)->getOffset();
$timezone = $timezone/-3600;
if($timezone<0) {
$timezone = $timezone;
} else
if($timezone==0) {
$timezone = '-0';
} else {
$timezone = '+'.$timezone;
}
$timezone = 'Etc/GMT'.$timezone;
$timezone_real = $item['timezone'];
$timezone_real = DateTime::createFromFormat('P',$timezone)->getOffset();
$timezone_real = $timezone_real/-3600;
if($timezone_real<0) {
$timezone_real = str_replace('-','+',$timezone_real);//.':00';
} else
if($timezone_real==0) {
$timezone_real = '+0';//:00';
} else {
$timezone_real = '-'.$timezone_real;//.':00';
}
$timezone_real = 'GMT'.$timezone_real;
date_default_timezone_set($timezone);
}
$today = date('n/j/Y G:i', time());
$today = strtotime($today);
$event_date = $date_array['month'].'/'.$date_array['day'].'/'.$date_array['year'].' '.$date_array['hour'].':'.$minute;
$event_date_unformatted = strtotime($event_date);
if($date_array['hour'] == '0') {
$hour_convert = '12';
$hour_suffix = 'a.m.';
} else if($date_array['hour']<12) {
$hour_convert = $date_array['hour'];
$hour_suffix = 'a.m.';
} else if($date_array['hour'] == '12') {
$hour_convert = $date_array['hour'];
$hour_suffix = 'p.m.';
} else {
$hour_convert = $date_array['hour']-12;
$hour_suffix = 'p.m.';
}
$date_convert = array('1' => 'January', '2' => 'February', '3' => 'March', '4' => 'April', '5' => 'May', '6' => 'June', '7' => 'July', '8' => 'August', '9' => 'September', '10' => 'October', '11' => 'November', '12' => 'December');
$event_date = $date_convert[$date_array['month']].' '.$date_array['day'].', '.$date_array['year'].', '.$hour_convert.':'.$minute.' '.$hour_suffix;
if(($event_date_unformatted-$today)>0) {
echo '<h5>UPCOMING:</h5>';
echo '<h6>'.$item['location'].', '.$event_date.' <sup>('.$timezone_real.')</sup></h6>';
}
}