这几天在研究字符串与指定类型的转换,阴差阳错地研究起 java 的日期应用了,记录下来,希望你有帮助。

根据指定格式的字符串,转换为 Date(可研究根据指定格式的字符串,转化为其他指定的类型,如 json 转换为 javaBean)

需要使用到的特殊类:import java.text.ParsePosition;

/**

*

Parses a string representing a date by trying a variety of different parsers.

*

*

The parse will try each parse pattern in turn.

* A parse is only deemed successful if it parses the whole of the input string.

* If no parse patterns match, a ParseException is thrown.

*

* @param str  the date to parse, not null

* @param parsePatterns  the date format patterns to use, see SimpleDateFormat, not null

* @param lenient Specify whether or not date/time parsing is to be lenient.

* @return the parsed date

* @throws IllegalArgumentException if the date string or pattern array is null

* @throws ParseException if none of the date patterns were suitable

* @see java.util.Calender#isLenient()

*/

private static Date parseDateWithLeniency(

String str, String[] parsePatterns,boolean lenient)throws ParseException {

if (str ==null || parsePatterns ==null) {

throw new IllegalArgumentException("Date and Patterns must not be null");

}

SimpleDateFormat parser =new SimpleDateFormat();

parser.setLenient(lenient);

ParsePosition pos =new ParsePosition(0);

for (String parsePattern : parsePatterns) {

String pattern = parsePattern;

// LANG-530 - need to make sure 'ZZ' output doesn't get passed to SimpleDateFormat

if (parsePattern.endsWith("ZZ")) {

pattern = pattern.substring(0, pattern.length() -1);

}

parser.applyPattern(pattern);

pos.setIndex(0);

String str2 = str;

// LANG-530 - need to make sure 'ZZ' output doesn't hit SimpleDateFormat as it will ParseException

if (parsePattern.endsWith("ZZ")) {

str2 = str.replaceAll("([-+][0-9][0-9]):([0-9][0-9])$","$1$2");

}

Date date = parser.parse(str2, pos);

if (date !=null && pos.getIndex() == str2.length()) {

return date;

}

}

throw new ParseException("Unable to parse the date: " + str, -1);

}

在 java 日期格式里,"ZZ" 代表的是 时区。在java 里,格式化需要借助类 Formate,同时,parse 的时候一般需要借助类 parsePosition,ParsePosition 是 Format 及其子类所使用的简单类,用来在解析过程中跟踪当前位置。各种 Format 类中的 parseObject 方法要求将 ParsePosition对象作为一个变量。

日期解释的宽松性:

Calendar 有两种解释日历字段的模式,即 lenient 和 non-lenient。当 Calendar 处于 lenient 模式时,它可接受比它所生成的日历字段范围更大范围内的值。当 Calendar 重新计算日历字段值,以便由 get() 返回这些值时,所有日历字段都被标准化。例如,lenient 模式下的GregorianCalendar 将MONTH == JANUARY、DAY_OF_MONTH == 32 解释为 February 1。

当 Calendar 处于 non-lenient 模式时,如果其日历字段中存在任何不一致性,它都会抛出一个异常。例如,GregorianCalendar 总是在 1 与月份的长度之间生成 DAY_OF_MONTH 值。如果已经设置了任何超出范围的字段值,那么在计算时间或日历字段值时,处于 non-lenient 模式下的GregorianCalendar会抛出一个异常。(在 non-lenient状态下,可以用来检测用户输入的日期是否合法)

日期加减(Calendar 的 add && set && roll)

set(int field,int amount) 方法,并不会立刻就计算出新的日期的值,而是在调用 getXxx() , add(),roll() 方法才会计算出新的日期的值,即多次调用set 方法,也不会产生多余的计算。

add(int filed, int amount) 方法,调用 add 方法,会立刻计算出新的日期的值。

roll(int fielde,int amount) 方法,调用 roll 方法,也会立刻计算出新的日期的值,与 add 不同的是,在进行计算完之后,不更改更高字段的值。

举例如下:假设一个日期(Calendar类型)是date 20140831

1)调用date.set(Calendar.Month,Calendar.September),在调用 set(Calendar.Data,1) ,c.getTime() 返回的时间是 20140901

2)调用date.add(Calendar.Month,1), c.getTime() 返回的日期是,20141001。(如果是设置了 c.setLeniency(true),返回的日期是 20141001,如果是设置了 c.setLeniency(false),返回的是 20140930)

3)调用date.roll(Calendar.Month,13),c.setLeniency(flase), c.getTime() 返回的日期是 20140930,请注意这里返回的不是 20141231

对于设置日期的值,可以这样编写代码:

private static Date set(Date date,int calendarField,int amount) {

if (date ==null) {

throw new IllegalArgumentException("The date must not be null");

}

// getInstance() returns a new object, so this method is thread safe.

Calendar c = Calendar.getInstance();

c.setLenient(false);// 这里使用严格模式,要求设置日期的值必须正确

c.setTime(date);

c.set(calendarField, amount);

return c.getTime();

}

加减日期,可以这样编写代码:

private static Date add(Date date,int calendarField,int amount) {

if (date ==null) {

throw new IllegalArgumentException("The date must not be null");

}

Calendar c = Calendar.getInstance();

c.setTime(date);

c.add(calendarField, amount);

return c.getTime();

}

roll 日期,可以这样编写代码:

private static Date roll(Date date,int calendarField,int amount) {

if (date ==null) {

throw new IllegalArgumentException("The date must not be null");

}

Calendar c = Calendar.getInstance();

c.setTime(date);

c.roll(calendarField, amount);

return c.getTime();

}

对应的设置年、月、日、时、分、秒,可以这样编写代码:(其他的可以仿写)

public static Date setMinutes(Date date,int amount) {

return set(date, Calendar.MINUTE, amount);

}

借助Calendar 提供的 api ,我们可以获取一些特殊的日期值。如下面这些日期值:

如:get(int fiele) 获取给定日历字段的值;getFirstDayOfWeek() 获取一星期的第一天的值(1~7)(在不同的地区,每周的第一天会有所不一样,在中是默认一星期的第一天是周日 1)。通过这两个 函数,我们可以获取任意一天其所在周的第一天的日期值,如 20140902 周二,我们可以获取到周日的日期值为 20140831。具体方法如下:

构造一个 20140902 的 Calendar,通过 getFirstDayOfWeek() ,获取本周第一天的值(返回1),通过  get(Calendar.day_of_week) 获取当前日期是本周的第几天,进而获取天数差,再将当前日期减去天数差,即可获取本周第一天的日期值。

函数如下:

public static Date getFirstDateOfWeek(Date date){

Calendar c = Calendar.getInstance();

c.setTime(date);

// 获取本周第一天的值

int firstDayOfWeek = c.getFirstDayOfWeek();

// 当前日期是本周的第几天

int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);

int day_diff =1;//天数差的绝对值,20140901~20140903 天数差为3

if (firstDayOfWeek < dayOfWeek) {

day_diff = Math.abs(dayOfWeek-firstDayOfWeek)  +1;

}

c.add(Calendar.DATE,1-day_diff);

return c.getTime();

}

为了本地化,我们可以用 GregorianCalendar 构造 Calendar,

GregorianCalendar calendar = new GregorianCalendar(Local.getDefault());

类似地,我们可以得到本周最后一天的日期:

public static Date getLastDateOfWeek(Date date){

Calendar c = Calendar.getInstance();

c.setTime(date);

// 获取本周第一天的值

int firstDayOfWeek = c.getFirstDayOfWeek();

// 当前日期是本周的第几天

int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);

int day_diff =1;//天数差的绝对值

if (firstDayOfWeek < dayOfWeek) {

day_diff =Math.abs(dayOfWeek - firstDayOfWeek) +1;

}

c.add(Calendar.DATE,7-day_diff);

return c.getTime();

}

再借助 Calendar 的时间值,返回指定日历字段可能拥有的最大值。Calendar 的时间值,返回指定日历字段可能拥有的最小值。借助这两个函数,我们可以获取一天所在月的第一天/最后一天的日期。方法如下:

public static Date getFirstDateOfMonth(Date date){

if (date ==null) {

throw new IllegalArgumentException("the date must not be null");

}

Calendar c = Calendar.getInstance();

c.setTime(date);

// get the min date in this month

int min_day = c.getActualMinimum(Calendar.DATE);

c.set(Calendar.DATE, min_day);

return c.getTime();

}

public static Date getLastDateOfMonth(Date date){

if (date ==null) {

throw new IllegalArgumentException("the date must not be null");

}

Calendar c = Calendar.getInstance();

c.setTime(date);

//get the max date in the month

int max_day = c.getActualMaximum(Calendar.DATE);

c.set(Calendar.DATE, max_day);

return c.getTime();

}

聪明的我们,是否马上就会想到,能否通过 getActualMaximum 和 getActualMininum 来获取一周 day_of_week 的最大/小值呢??是的,通过这两个方法,我们可以减少一定的计算量,如下:

public static Date getFirstDateOfWeek(Date date){

Calendar c = Calendar.getInstance();

c.setTime(date);

//      // 获取本周第一天的值

//      int firstDayOfWeek = c.getFirstDayOfWeek();

//      // 当前日期是本周的第几天

//      int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);

//

//      int day_diff = 1;//天数差的绝对值,20140901~20140903 天数差为3

//

//      if (firstDayOfWeek < dayOfWeek) {

//          day_diff = Math.abs(dayOfWeek-firstDayOfWeek)  + 1;

//      }

//

//      c.add(Calendar.DATE,1-day_diff);

int min_day = c.getActualMinimum(Calendar.DAY_OF_WEEK);

c.set(Calendar.DAY_OF_WEEK,min_day);

return c.getTime();

}

借助 getActualMaxinum 和 getActualMininum 可以获得很多最大/小值,如可以获取月、日、时、分、秒的最后/最初一刻,自然就可以获取一年的起始/结束日期,一天的起始/结束时刻等等,发挥想象了,灵活应用 api,就可以很多我们所需要的函数,组织起来就可以是一个 工具类了。

在这里再谈一下,如果获取季度的起始/结束日期,方法如下:

对于给定的日期,如果我们可以获取到其所在季度的起始月份和结束月份,自然就可以获取到季度的起始日期和结束日期。函数如下:

在这里我们初始化静态数组,用来存储每个月所在季度第一个和最后一个月份的值,注意在 java 里,月份的范围是[0,11]

private static final int[] seasonFirstMonth =new int[] {0,0,0,3,3,3,

6,6,6,9,9,9 };

private static final int[] seasonLastMonth =new int[] {2,2,2,5,5,5,

8,8,8,11,11,11 };

public static Date getFirstDateOfSeason(Date date){

if (date ==null) {

throw new IllegalArgumentException("the date must not be null");

}

Calendar c = Calendar.getInstance();

c.setTime(date);

c.set(Calendar.MONTH, seasonFirstMonth[c.get(Calendar.MONTH)]);

c.set(Calendar.DATE, c.getActualMinimum(Calendar.DATE));

return c.getTime();

}

public static Date getLastDateOfSeason(Date date){

if (date ==null) {

throw new IllegalArgumentException("the date must not be null");

}

Calendar c = Calendar.getInstance();

c.setTime(date);

c.set(Calendar.MONTH, seasonLastMonth[c.get(Calendar.MONTH)]);

c.set(Calendar.DATE, c.getActualMaximum(Calendar.DATE));

return c.getTime();

}

最后谈一下,如何去计算两个日期之间的天数差(规定如下,20140901~20140903,天数差为3),函数如下:

public static long getDaysBetweenTwoDate(Date date1,Date date2){

if (date1 ==null || date2 ==null) {

throw new IllegalArgumentException("date1 and date2 must not be null");

}

Calendar c1 = Calendar.getInstance();

c1.setTime(date1);

Calendar c2 = Calendar.getInstance();

c2.setTime(date2);

long mills_one_day =60 *60 *24 *1000;

return Math.abs(c1.getTimeInMillis() - c2.getTimeInMillis())/mills_one_day +1;

}

附:通过阅读 Java API,借助一些基础的推算逻辑,我们可以合成很多很有用工具类,让我们彼此一起努力。在这一次学习当中,本人更感兴趣的,如何通过指定的字符串格式构造指定的对象(如通过字符串构造日期),又如何通过指定格式输出制定对象(如根据 yyyyMMdd 格式输出 日期对象)。

MYSQL中的获取:

#当年第一天:SELECT DATE_SUB(CURDATE(),INTERVAL dayofyear(now())-1 DAY);

#当年最后一天:SELECT concat(YEAR(now()),'-12-31');

#当前week的第一天:select date_sub(curdate(),INTERVAL WEEKDAY(curdate()) + 1 DAY);

#当前week的最后一天:select date_sub(curdate(),INTERVAL WEEKDAY(curdate()) - 5 DAY);

#前一week的第一天:select date_sub(curdate(),INTERVAL WEEKDAY(curdate()) + 8 DAY);

#前一week的最后一天:select date_sub(curdate(),INTERVAL WEEKDAY(curdate()) + 1 DAY);

#前两week的第一天:select date_sub(curdate(),INTERVAL WEEKDAY(curdate()) + 15 DAY);

#前两week的最后一天:select date_sub(curdate(),INTERVAL WEEKDAY(curdate()) + 9 DAY);

#当前month的第一天:SELECT concat(date_format(LAST_DAY(now()),'%Y-%m-'),'01');

#当前month的最后一天:SELECTLAST_DAY(now());

#前一month的第一天:SELECT concat(date_format(LAST_DAY(now() - interval 1 month),'%Y-%m-'),'01');

#前一month的最后一天:SELECT LAST_DAY(now() - interval 1 month);

#前两month的第一天:SELECT concat(date_format(LAST_DAY(now() - interval 2 month),'%Y-%m-'),'01');

#前两month的最后一天:SELECT LAST_DAY(now() - interval 2 month);

#当前quarter的第一天:select concat(date_format(LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM CURDATE()),1) + interval QUARTER(CURDATE())*3-3 month),'%Y-%m-'),'01');

#当前quarter的最后一天:select LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM CURDATE()),1) + interval QUARTER(CURDATE())*3-1 month);

#前一quarter的第一天:select concat(date_format(LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM CURDATE()),1) + interval QUARTER(CURDATE())*3-6 month),'%Y-%m-'),'01');

#前一quarter的最后一天:select LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM CURDATE()),1) + interval QUARTER(CURDATE())*3-4 month);

#前两quarter的第一天:select concat(date_format(LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM CURDATE()),1) + interval QUARTER(CURDATE())*3-9 month),'%Y-%m-'),'01');

#前两quarter的最后一天:select LAST_DAY(MAKEDATE(EXTRACT(YEAR FROM CURDATE()),1) + interval QUARTER(CURDATE())*3-7 month);

java mysql 周_java 和 mysql 获取周 星期 的第一天 最后一天 或者 月的 日期(字符串转日期,日期转字符串,日期加减)...相关推荐

  1. java 和 mysql 获取周 星期 的第一天 最后一天 或者 月的 日期(字符串转日期,日期转字符串,日期加减)...

    获取周的第一天,最后一天 System.out.println(getStartEndDate("2016-05-01", 1)); 获取星期的第一天和最后一天 System.ou ...

  2. java mysql 配置_Java连接MySQL数据库详细分析

    一:工具 eclipse MySQL5.7 MySQL连接驱动:mysql-connector-java-5.1.44-bin.jar下载地址 二:加载驱动 2.1 在工程目录中创建lib文件夹,将下 ...

  3. java mysql 查询_java连接mysql数据库达成数据查询详细教程

    前言:本篇文章适用于所有前后端开发者 众所周知,只要是编程,那肯定是需要存储数据的,无论是c语言还是java,都离不开数据的读写,数据之间传输不止,这也就形成了现代互联网的一种相互存在关系! 而读写存 ...

  4. java 和mysql 时间_java和mysql之间的时间日期类型传递

    mysql(版本:5.1.50)的时间日期类型如下: datetime 8bytes xxxx-xx-xx xx:xx:xx 1000-01-01 00:00:00到9999-12-31 23:59: ...

  5. java连接mysql乱码_java链接mysql 中文乱码

    {转!} 背景: 由于最近在开发一个APP的后台程序,需要Java连接远程的MySQL数据库进行数据的更新和查询操作,并且插入的数据里有中文,在插入到数据库后发现中文都是乱码.网上查了很多教程,最后都 ...

  6. mysql java中文乱码_java连接mysql添加中文乱码_MySQL

    bitsCN.com java添加中文数据到mysql中, 包含中文就乱码 最初是想应该是由于字符编码不一致,所以查看数据库的属性跟表的属性 查看表的字符集也是utf8,不是的改成自己想要设置的,我这 ...

  7. java 查看文件属性_java File类获取文件属性详解

    你知道java File类获取文件属性方法吗?下面的文章要给大家讲解的就是这个方面的内容,希望下面的内容可以对你有所帮助哦. 在Java中获取文件属性信息的第一步是先创建一个File类对象并指向一个已 ...

  8. java date加一天_Java日期时间API系列15-----Jdk8中API类,java日期计算2,年月日时分秒的加减等...

    通过Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析 ,可以看出java8设计非常好,实现接口Temporal, Tempora ...

  9. java 获取mysql链接_Java中如何获取mysql连接的3种方法总结

    前言 本文主要来说说三种 Java 中获取 mysql 连接的方式,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: 第一种:传统的连接方式: 第二种:读取配置文件方式: 第三种:数据库 ...

  10. java swing mysql项目_java swing mysql 实现的家庭收支管理系统项目源码

    大家好,今天给大家演示一下一款由Java swing mysql实现的简单的家庭收支情况管理系统,也可以叫个人消费情况记录软件,功能比较紧凑简单,数据库采用的是mysql,非常适合Java初学者和学生 ...

最新文章

  1. 使用 mysql workbench 建议
  2. USACO 2.1 健康的好斯坦奶牛 (DFS)
  3. SQL-left(right,inner) join
  4. android 倒计时的控件,以动画的形式平滑的完成数字的过度
  5. leetcode 208. Implement Trie (Prefix Tree) | 208. 实现 Trie 前缀树(Java)
  6. 分布式系统测试那些事儿——信心的毁灭与重建
  7. PowerShell 扩展工具第四波!
  8. 修改oracle 安裝參數,oracle 安裝相關參數設定
  9. RTOS原理与实现12:性能测量
  10. 数据结构笔记(十三)-- 串的堆分配存储表示
  11. 子div撑不开父div的几种解决方法
  12. 设置eclipse主题风格
  13. 深入解析Windows操作系统(笔记2)
  14. Unreal Engine UE4虚幻引擎,创建Sky天空球,球天材质,自制天空球(HDR高动态范围贴图)
  15. 编译开源路由下iNode客户端njit8021xclient
  16. 计算机网络复习训练题
  17. lof基金溢价率php源码,一文读懂LOF基金套利策略 LOF是球友们很喜欢的一类基金,这类基金不仅可以在场内进行高效买卖,而且还可以进行折溢价套利。不过这里面牵扯到很多细节,... - 雪球...
  18. 走进AI时代的文档识别技术 之文档重建
  19. 支付系统--清结算概括介绍
  20. Jquery 里的节点遍历(next(),perv(),nextAll(),prevAll())

热门文章

  1. MySQL MVCC(多版本并发控制)
  2. CountDownLatch分析(AQS共享锁)
  3. 【Spring-AOP】自动代理类AnnotationAwareAspectJAutoProxyCreator
  4. shell脚本基础和grep使用
  5. AIX下内存泄漏的监控
  6. plsql developer 无法登录Oracle
  7. 设计模式学习笔记(四)之工厂模式(Factory)
  8. Linux下挂载NTFS
  9. android如何获取系统开机时间
  10. php用putty安装吗,为什么通过Putty的SSH命令与PHP的phpseclib不同?