不是很好的头衔,所以我道歉。
出于某种原因,(我不是那个人,我离题了)我们有一个表结构,其中日期的字段类型是varchar。 (奇数)。
我们有一些日期,例如:
1932-04-01 00:00:00 and 1929-07-04 00:00:00
我需要进行一个查询,将这些日期字符串转换为unix时间戳,但是,如果你转换1970年之前的日期,它会返回0。
有什么想法吗?
非常感谢!
编辑:错误的日期格式。哎呀。
答案 0 :(得分:17)
啊哈!我们找到了解决方案!
执行此操作的SQL:
SELECT DATEDIFF( STR_TO_DATE('04-07-1988','%d-%m-%Y'),FROM_UNIXTIME(0))*24*3600 -> 583977600
SELECT DATEDIFF( STR_TO_DATE('04-07-1968','%d-%m-%Y'),FROM_UNIXTIME(0))*24*3600 -> -47174400
这可能对将来参考有用。
答案 1 :(得分:4)
我已经改编了DATEDIFF的解决方法,也包括时间而不仅仅是几天。我把它包装成一个存储函数,但如果你不想使用函数,你可以解析SELECT部分。
DELIMITER |
CREATE FUNCTION SIGNED_UNIX_TIMESTAMP (d DATETIME)
RETURNS BIGINT
DETERMINISTIC
BEGIN
DECLARE tz VARCHAR(100);
DECLARE ts BIGINT;
SET tz = @@time_zone;
SET time_zone = '+00:00';
SELECT DATEDIFF(d, FROM_UNIXTIME(0)) * 86400 +
TIME_TO_SEC(
TIMEDIFF(
d,
DATE_ADD(MAKEDATE(YEAR(d), DAYOFYEAR(d)), INTERVAL 0 HOUR)
)
) INTO ts;
SET time_zone = tz;
return ts;
END|
DELIMITER ;
-- SELECT UNIX_TIMESTAMP('1900-01-02 03:45:00');
-- will return 0
-- SELECT SIGNED_UNIX_TIMESTAMP('1900-01-02 03:45:00');
-- will return -2208888900
答案 2 :(得分:2)
将这些日期字符串转换为 unix时间戳
传统的Unix时间戳是自1970年1月1日以来的无符号整数计数,因此无法表示此之前的任何日期。
答案 3 :(得分:2)
根据您用来表示时间戳的系统,您最多会得到混合结果。
最初存在一些争议 关于Unix time_t是否应该 签名或未签名。如果未签名, 它的未来范围将是 加倍,推迟32位 溢出(68年)。但是,它 然后将无能为力 代表1970年以前的时间。 当被问及此事时,丹尼斯里奇 问题,说他没有想到 非常深刻的,但它是 认为能够代表的能力 在他一生中的所有时间都是 不错。 (里奇的出生,在1941年,是 在Unix时间-893 400 000.) 达成共识是为了签署时间表, 这是通常的做法。该 软件开发平台 QNX操作系统的第6版 但是有一个无符号的32位time_t 旧版本使用签名类型。
似乎MySQL将时间戳视为无符号整数,这意味着Epoc之前的时间都将解析为0。
在这种情况下,您始终可以选择实现自己的无符号时间戳类型,并将其用于计算。
答案 4 :(得分:2)
如果它可以解决您的问题,您可以将所有mysql时间换算,比如100年,然后使用这些调整后的时间戳或重新计算负时间戳值。
正如一些人所说,确保你的系统使用64位代表时间戳,否则你将遇到2038年的问题。
答案 5 :(得分:1)
我没有尝试过上述解决方案,但如果您无法以时间戳的形式从MySQL数据库中检索日期值,那么也可以尝试此操作
SELECT TIMESTAMPDIFF(second,FROM_UNIXTIME(0),'1960-01-01 00:00:00');
答案 6 :(得分:0)
获得最大值范围+/-明智地在您的生日字段上使用此查询,在我的情况下" yyyy-mm-dd"但你可以根据自己的需要改变它
select name, (@bday:=STR_TO_DATE(birthday,"%Y-%m-%d")),if(year(@bday)<1970,UNIX_TIMESTAMP(adddate(@bday, interval 68 year))-2145916800,UNIX_TIMESTAMP(@bday)) from people
答案 7 :(得分:0)
我觉得我们让这件事变得太困难了...
使用下面的函数,您可以将任何内容与 unix 时间戳相互转换,就像在浏览器中所做的一样。
像这样调用函数:
select to_unix_time('1776-07-04 10:02:00'),
from_unix_time(-6106024680000);
通过编译这些:
delimiter $$
create function to_unix_time (
p_datetime datetime
) returns bigint
deterministic
begin
declare v_ret bigint;
select round(timestampdiff(
microsecond,
'1970-01-01 00:00:00',
p_datetime
) / 1000, 0)
into v_ret;
return v_ret;
end$$
create function from_unix_time (
p_time bigint
) returns datetime(6)
deterministic
begin
declare v_ret datetime(6);
select '1970-01-01 00:00:00' +
interval (p_time * 1000) microsecond
into v_ret;
return v_ret;
end$$
答案 8 :(得分:-2)
使用日期而不是时间戳。日期将解决您的问题。 检查此link