MySQL時間類型及獲取、展示處理


MySQL時間格式

  mysql所支持的日期時間類型有:DATETIME、 TIMESTAMP、DATE、TIME、YEAR。

  幾種類型比較如下:

日期時間類型 占用空間 日期格式 最小值 最大值 零值表示
 DATETIME  8 bytes  YYYY-MM-DD HH:MM:SS  1000-01-01 00:00:00 9999-12-31 23:59:59  0000-00-00 00:00:00
 TIMESTAMP  4 bytes  YYYY-MM-DD HH:MM:SS  19700101080001 2038 年的某個時刻 00000000000000
 DATE  4 bytes  YYYY-MM-DD 1000-01-01  9999-12-31  0000-00-00
 TIME  3 bytes  HH:MM:SS  -838:59:59 838:59:59  00:00:00
 YEAR  1 bytes  YYYY 1901  2155  0000

 

 

 

 

 

  DATETIME

  DATETIME 用於表示 年月日 時分秒,是 DATE 和 TIME 的組合,並且記錄的年份(見上表)比較長久。如果實際應用中有這樣的需求,就可以使用 DATETIME 類型。

  TIMESTAMP

  • TIMESTAMP 用於表示 年月日 時分秒,但是記錄的年份(見上表)比較短暫。
  • TIMESTAMP 和時區相關,更能反映當前時間。當插入日期時,會先轉換為本地時區后再存放;當查詢日期時,會將日期轉換為本地時區后再顯示。所以不同時區的人看到的同一時間是  不一樣的。
  • 表中的第一個 TIMESTAMP 列自動設置為系統時間(CURRENT_TIMESTAMP)。當插入或更新一行,但沒有明確給 TIMESTAMP 列賦值,也會自動設置為當前系統時間。如果表中有第二個 TIMESTAMP 列,則默認值設置為0000-00-00 00:00:00。
  • TIMESTAMP 的屬性受 Mysql 版本和服務器 SQLMode 的影響較大。

  如果記錄的日期需要讓不同時區的人使用,最好使用 TIMESTAMP。

  DATE

  DATE 用於表示 年月日,如果實際應用值需要保存 年月日 就可以使用 DATE。

  TIME

  TIME 用於表示 時分秒,如果實際應用值需要保存 時分秒 就可以使用 TIME。

  YEAR

  YEAR 用於表示 年份,YEAR 有 2 位(最好使用4位)和 4 位格式的年。 默認是4位。如果實際應用只保存年份,那么用 1 bytes 保存 YEAR 類型完全可以。不但能夠節約存儲空間,還能提高表的操作效率。

不嚴格語法的時間格式

  每種日期時間類型都有一個有效值范圍,如果超出這個范圍,在默認的SQLMode下會報錯,並以零值(見上表)存儲。

  插入或更新時,日期時間類型允許“不嚴格”語法,以DATETIME為例(其他日期時間類型雷同):

  • YYYY-MM-DD HH:MM:SS 或 YY-MM-DD HH:MM:SS 格式的字符串。任何符號都可以用作日期部分或時間部分的間隔符。例如:“14-06-18 14:54:10”、“14*06*18 14.54.10”、“14+06+18 14=54=10”是等價的。對於包含日期時間的字符串值,如果月、日、時、分、秒的值小於10,不需要指定兩位數。例如:“2014-2-3 2:3:6”、“2014-02-03 02:03:06”是等價的。
  • YYYYMMDDHHMMSS 或 YYMMDDHHMMSS 格式的字符串。如果字符串對於日期時間類型是合法的就可以解釋為日期時間類型。例如:“20140618145410” 和 “140618145410”將被解釋為 “2014-06-18 14:54:10” ,但是 “20140618145480” 是不合法的(秒數不合法),將被解釋為 “0000-00-00 00:00:00”。
  • YYYYMMDDHHMMSS 或 YYMMDDHHMMSS 格式的數字。如果該數字對日期時間類型是合法的就可以解釋為日期時間類型。例如:“20140618145410” 和 “140618145410” 將被解釋為 “2014-06-18 14:54:10” 。數值的長度應為6、8、12、14。如果數值長度是 8 或 14 位長,則假定為 YYYYMMDD 或 YYYYMMDDHHMMSS 格式。如果數值為 6 或 12 位長,則假定為 YYMMDD 或 YYMMDDHHMMSS 格式。

TIMSTAMP返回值格式化:

  通常日期格式都是以時間戳的形式存放在數據庫里,當前端頁面通過接口查詢時,我們會將一個對象的某些屬性查出來返回給頁面。例如,某個類里面有個屬性

  Timestamp create_time

  給這個對象實體類中的get方法加注解:@JsonFormat 來實現格式的自動轉換:

  依賴的jar包:jackson-annotations-2.8.5.jar

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")  
public Timestamp getCreate_time() {  
        return create_time;  
} 

  加注解前的返回值是一個時間戳,加了之后則按照注解的格式自動格式化,其余類型同理。

Timestamp類的使用

  我們可以這樣聲明 Timestamp ts=new Timestamp(new Date().getTime());這樣我們就可以得到時間比較具體的一個類型轉換。在開發web應用中,針對不同的數據庫日期類型,我們需要在我們的程序中對日期類型做各種不同的轉換。若對應數據庫數據是oracle的Date類型,即只需要年月日的,可以選擇使用java.sql.Date類型,若對應的是MSsqlserver數據庫的DateTime類型,即需要年月日時分秒的,選擇java.sql.Timestamp類型;
  你可以使用dateFormat定義時間日期的格式,然后進行轉換:

import java.util.Date; 
import java.util.Calendar; 
import java.sql.Timestamp; 
import java.text.DateFormat; 
import java.text.SimpleDateFormat; 
import java.util.Locale; 
class Datetest{ 
/** 
  *method 將字符串類型的日期轉換為一個timestamp(時間戳記java.sql.Timestamp) 
   dateString 需要轉換為timestamp的字符串 
   dataTime timestamp 
  */ 
public final static java.sql.Timestamp string2Time(String dateString) 
  throws java.text.ParseException { 
   DateFormat dateFormat; 
  dateFormat = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss.SSS", Locale.ENGLISH);//設定格式 
  //dateFormat = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss", Locale.ENGLISH); 
  dateFormat.setLenient(false); 
  java.util.Date timeDate = dateFormat.parse(dateString);//util類型 
  java.sql.Timestamp dateTime = new java.sql.Timestamp(timeDate.getTime());//Timestamp類型,timeDate.getTime()返回一個long型 
  return dateTime; 
} 
/** 
  *method 將字符串類型的日期轉換為一個Date(java.sql.Date) 
   dateString 需要轉換為Date的字符串 
   dataTime Date 
  */ 
public final static java.sql.Date string2Date(String dateString) 
  throws java.lang.Exception { 
  DateFormat dateFormat; 
  dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH); 
  dateFormat.setLenient(false); 
  java.util.Date timeDate = dateFormat.parse(dateString);//util類型 
  java.sql.Date dateTime = new java.sql.Date(timeDate.getTime());//sql類型 
  return dateTime; 
} 

public static void main(String[] args){ 
  Date da = new Date(); 
  //注意:這個地方da.getTime()得到的是一個long型的值 
  System.out.println(da.getTime()); 

  //由日期date轉換為timestamp 

  //第一種方法:使用new Timestamp(long) 
  Timestamp t = new Timestamp(new Date().getTime()); 
  System.out.println(t); 

  //第二種方法:使用Timestamp(int year,int month,int date,int hour,int minute,int second,int nano) 
  Timestamp tt = new Timestamp(Calendar.getInstance().get( 
      Calendar.YEAR) - 1900, Calendar.getInstance().get( 
      Calendar.MONTH), Calendar.getInstance().get( 
      Calendar.DATE), Calendar.getInstance().get( 
      Calendar.HOUR), Calendar.getInstance().get( 
      Calendar.MINUTE), Calendar.getInstance().get( 
      Calendar.SECOND), 0); 
  System.out.println(tt); 

  try { 
     String sToDate = "2005-8-18";//用於轉換成java.sql.Date的字符串 
      String sToTimestamp = "2005-8-18 14:21:12.123";//用於轉換成java.sql.Timestamp的字符串 
      Date date1 = string2Date(sToDate); 
      Timestamp date2 = string2Time(sToTimestamp); 
   System.out.println("Date:"+date1.toString());//結果顯示 
   System.out.println("Timestamp:"+date2.toString());//結果顯示 
  }catch(Exception e) { 
   e.printStackTrace(); 
  } 
} 
}

   注意:Mybatis返回值設置jdbctype是沒有這個DATETIME類型的(如下圖報錯),如果數據庫存儲的是DATETIME的類型,並且准確顯示到年月日時分秒,所以用timestamp。

數據庫日期大小比較操作

  mysql官網也是不承認時間直接相加減的(如CURDATE()+1),雖然會將當前時間轉換為20160802,這時候就是比較這一串字符,mysql官網是不承認用這種方式比較時間大小的,因此正確的sql語句:

SELECT COUNT(*) FROM USER WHERE registerDate >= CURDATE() AND registerDate < DATE_SUB(CURDATE(),INTERVAL -1 DAY);

  此時,就用到了DATE_SUB()這個函數,用法舉例:

--今天是2016年08月01日。
date_sub('2016-08-01',interval 1 day) --表示 2016-07-31
date_sub('2016-08-01',interval 0 day) --表示 2016-08-01
date_sub('2016-08-01',interval -1 day) --表示 2016-08-02

date_sub(curdate(),interval 1 day) --表示 2016-07-31
date_sub(curdate(),interval -1 day) --表示2016-08-02
date_sub(curdate(),interval 1 month) --表示 2016-07-01
date_sub(curdate(),interval -1 month) --表示 2016-09-01
date_sub(curdate(),interval 1 year) --表示 2015-08-01
date_sub(curdate(),interval -1 year) --表示 2017-08-01

  注意:SELECT NOW(),CURDATE(),CURTIME()

  結果類似:

NOW() CURDATE() CURTIME()
2016-08-01 16:25:46 2016-08-01 16:25:46

SQL語句日期格式化

  案例:mybatis中查詢時間范圍處理:例如2018-05-22 ~2018-05-23,則查出來的數據僅能查到2018-05-22的,查不到2018-05-23的數據。時間字段在spring MVC中已經處理了,已經沒有2018-05-23 00:00:00.0,已經獲取到了日期,去掉了時分秒,為什么傳入mybatis進行sql查詢的時候依舊會變成這樣?

<if test="saleDateStart != null">
  and DATE_FORMAT(info.sale_date,'%Y-%m-%d') &gt;= #{saleDateStart} </if>
<if test="saleDateEnd != null">
  and DATE_FORMAT(info.sale_date,'%Y-%m-%d') &lt;= #{saleDateStart} </if>

  原因:問題就出在   #{時間字段} 這個地方,雖然這個時候查詢的時候傳入的時間字段值 是  年月日格式  沒有時分秒  但是mybatis在生成sql的時候 ,依舊將 年月日進行格式化 成了 年月日 時分秒類型。

  解決辦法:對傳入到Mybatis的具體值進行格式化后再比較

<if test="saleDateStart != null">
    and DATE_FORMAT(info.sale_date,'%Y-%m-%d') &gt;= DATE_FORMAT(#{saleDateStart},'%Y-%m-%d') </if>
<if test="saleDateEnd != null">
    and DATE_FORMAT(info.sale_date,'%Y-%m-%d') &lt;= DATE_FORMAT(#{saleDateStart},'%Y-%m-%d') </if>

  其余類似比較SQL語句:

--特定時間秒查詢
SELECT
    id,
    date_0
FROM
    worksheet_data_30 
WHERE
    DATE_FORMAT( date_0, '%Y-%m-%d %H:%i:%S' ) = DATE_FORMAT( '2019-06-05 09:35:06', '%Y-%m-%d %H:%i:%S' ) --特定分鍾查詢
SELECT
    id,
    date_0
FROM
    worksheet_data_30 
WHERE
    DATE_FORMAT( date_0, '%Y-%m-%d %H:%i' ) = DATE_FORMAT( '2019-06-05 09:35:06', '%Y-%m-%d %H:%i' ) --特定小時查詢
SELECT
    id,
    date_0
FROM
    worksheet_data_30 
WHERE
    DATE_FORMAT( date_0, '%Y-%m-%d %H' ) = DATE_FORMAT( '2019-06-05 09:35:06', '%Y-%m-%d %H' ) --當天數據查詢
select * from security_code_config  where DATE_FORMAT(create_date,'%Y-%m-%d') = DATE_FORMAT(NOW(),'%Y-%m-%d') --本月數據查詢
select * from security_code_config  where DATE_FORMAT(create_date,'%Y-%m') = DATE_FORMAT(NOW(),'%Y-%m') --本年數據查詢
select * from security_code_config  where DATE_FORMAT(create_date,'%Y') = DATE_FORMAT(NOW(),'%Y') --查詢最近7天 按天分組統計數據
SELECT
create_date,
IFNULL(sum(security_code_total), 0) createSCNum,
IFNULL(sum(print_num), 0) printNum
FROM
security_code_config
WHERE
tid = 'ten_pisen'
AND 
DATE_FORMAT(create_date,'%Y-%m-%d') <= DATE_FORMAT('2019-03-12','%Y-%m-%d')
AND
DATE_FORMAT(create_date,'%Y-%m-%d') >= DATE_FORMAT('2019-03-01','%Y-%m-%d')
GROUP BY DATE_FORMAT(create_date,'%Y-%m-%d') --查詢最近6個月 按月分組統計數據
SELECT
create_date,
IFNULL(sum(security_code_total), 0) createSCNum,
IFNULL(sum(print_num), 0) printNum
FROM
security_code_config
WHERE
tid = 'ten_pisen'
AND 
DATE_FORMAT(create_date,'%Y-%m-%d') <= DATE_FORMAT('2019-03-12','%Y-%m-%d')
AND
DATE_FORMAT(create_date,'%Y-%m-%d') >= DATE_FORMAT('2018-10-01','%Y-%m-%d')
GROUP BY DATE_FORMAT(create_date,'%Y-%m') 

===============================附錄,mysql格式化方法以及時間符號========================

 

  date_format(date,'%Y-%m-%d %H:%i:%s')    -------------->oracle中的to_char();

 

  str_to_date(date,'%Y-%m-%d %H:%i:%s')     -------------->oracle中的to_date();
  format參數的格式有

%a 縮寫星期名
%b 縮寫月名
%c 月,數值
%D 帶有英文前綴的月中的天
%d 月的天,數值(00-31)
%e 月的天,數值(0-31)
%f 微秒
%H 小時 (00-23)
%h 小時 (01-12)
%I 小時 (01-12)
%i 分鍾,數值(00-59)
%j 年的天 (001-366)
%k 小時 (0-23)
%l 小時 (1-12)
%M 月名
%m 月,數值(00-12)
%p AM 或 PM
%r 時間,12-小時(hh:mm:ss AM 或 PM)
%S 秒(00-59)
%s 秒(00-59)
%T 時間, 24-小時 (hh:mm:ss)
%U 周 (00-53) 星期日是一周的第一天
%u 周 (00-53) 星期一是一周的第一天
%V 周 (01-53) 星期日是一周的第一天,與 %X 使用
%v 周 (01-53) 星期一是一周的第一天,與 %x 使用
%W 星期名
%w 周的天 (0=星期日, 6=星期六)
%X 年,其中的星期日是周的第一天,4 位,與 %V 使用
%x 年,其中的星期一是周的第一天,4 位,與 %v 使用
%Y 年,4 位
%y 年,2 位


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM