.1 Lambda表達式和函數式接口
Lambda表達式(也稱為閉包)是Java 8中最大和最令人期待的語言改變。它允許我們將函數當成參數傳遞給某個方法,或者把代碼本身當作數據處理:函數式開發者非常熟悉這些概念。
很多JVM平台上的語言(Groovy、Scala等)從誕生之日就支持Lambda表達式,但是Java開發者沒有選擇,只能使用匿名內部類代替Lambda表達式。
Lambda的設計耗費了很多時間和很大的社區力量,最終找到一種折中的實現方案,可以實現簡潔而緊湊的語言結構。
最簡單的Lambda表達式可由逗號分隔的參數列表、->符號和語句塊組成,例如:
Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );
在上面這個代碼中的參數e的類型是由編譯器推理得出的,你也可以顯式指定該參數的類型,例如:
Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) );
如果Lambda表達式需要更復雜的語句塊,則可以使用花括號將該語句塊括起來,類似於Java中的函數體,例如:
Arrays.asList( "a", "b", "d" ).forEach( e -> { System.out.print( e ); System.out.print( e ); } );
Lambda表達式可以引用類成員和局部變量(會將這些變量隱式得轉換成final的),例如下列兩個代碼塊的效果完全相同:
String separator = ","; Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.print( e + separator ) );
和
final String separator = ","; Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.print( e + separator ) );
Lambda表達式有返回值,返回值的類型也由編譯器推理得出。如果Lambda表達式中的語句塊只有一行,則可以不用使用return語句,下列兩個代碼片段效果相同:
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );
和
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> { int result = e1.compareTo( e2 ); return result; } );
Lambda的設計者們為了讓現有的功能與Lambda表達式良好兼容,考慮了很多方法,於是產生了函數接口這個概念。函數接口指的是只有一個函數的接口,這樣的接口可以隱式轉換為Lambda表達式。java.lang.Runnable和java.util.concurrent.Callable是函數式接口的最佳例子。在實踐中,函數式接口非常脆弱:只要某個開發者在該接口中添加一個函數,則該接口就不再是函數式接口進而導致編譯失敗。為了克服這種代碼層面的脆弱性,並顯式說明某個接口是函數式接口,Java 8 提供了一個特殊的注解@FunctionalInterface(Java 庫中的所有相關接口都已經帶有這個注解了),舉個簡單的函數式接口的定義:
@FunctionalInterface public interface Functional { void method(); }
不過有一點需要注意,默認方法和靜態方法不會破壞函數式接口的定義,因此如下的代碼是合法的。
@FunctionalInterface public interface FunctionalDefaultMethods { void method(); default void defaultMethod() { } }
Lambda表達式作為Java 8的最大賣點,它有潛力吸引更多的開發者加入到JVM平台,並在純Java編程中使用函數式編程的概念。如果你需要了解更多Lambda表達式的細節,可以參考官方文檔。
2 Optional
Java應用中最常見的bug就是空值異常。在Java 8之前,Google Guava引入了Optionals類來解決NullPointerException,從而避免源碼被各種null檢查污染,以便開發者寫出更加整潔的代碼。Java 8也將Optional加入了官方庫。
Optional僅僅是一個容易:存放T類型的值或者null。它提供了一些有用的接口來避免顯式的null檢查,可以參考Java 8官方文檔了解更多細節。
接下來看一點使用Optional的例子:可能為空的值或者某個類型的值:
Optional< String > fullName = Optional.ofNullable( null ); System.out.println( "Full Name is set? " + fullName.isPresent() ); System.out.println( "Full Name: " + fullName.orElseGet( () -> "[none]" ) ); System.out.println( fullName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );
如果Optional實例持有一個非空值,則isPresent()方法返回true,否則返回false;orElseGet()方法,Optional實例持有null,則可以接受一個lambda表達式生成的默認值;map()方法可以將現有的Opetional實例的值轉換成新的值;orElse()方法與orElseGet()方法類似,但是在持有null的時候返回傳入的默認值。
上述代碼的輸出結果如下:
Full Name is set? false Full Name: [none] Hey Stranger!
再看下另一個簡單的例子:
Optional< String > firstName = Optional.of( "Tom" ); System.out.println( "First Name is set? " + firstName.isPresent() ); System.out.println( "First Name: " + firstName.orElseGet( () -> "[none]" ) ); System.out.println( firstName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) ); System.out.println();
這個例子的輸出是:
First Name is set? true First Name: Tom Hey Tom!
2,stream
例子:
@Before public void init() { random = new Random(); stuList = new ArrayList<Student>() { { for (int i = 0; i < 100; i++) { add(new Student("student" + i, random.nextInt(50) + 50)); } } }; } public class Student { private String name; private Integer score; //-----getters and setters----- } //1列出班上超過85分的學生姓名,並按照分數降序輸出用戶名字 @Test public void test1() { List<String> studentList = stuList.stream() .filter(x->x.getScore()>85) .sorted(Comparator.comparing(Student::getScore).reversed()) .map(Student::getName) .collect(Collectors.toList()); System.out.println(studentList); }
/** * map把一種類型的流轉換為另外一種類型的流 * 將String數組中字母轉換為大寫 */ @Test public void testMap() { String[] arr = new String[]{"yes", "YES", "no", "NO"}; Arrays.stream(arr).map(x -> x.toLowerCase()).forEach(System.out::println); }
filter:過濾流,過濾流中的元素
@Test public void testFilter(){ Integer[] arr = new Integer[]{1,2,3,4,5,6,7,8,9,10}; Arrays.stream(arr).filter(x->x>3&&x<8).forEach(System.out::println); }
/** * flapMap:拆解流 */ @Test public void testFlapMap1() { String[] arr1 = {"a", "b", "c", "d"}; String[] arr2 = {"e", "f", "c", "d"}; String[] arr3 = {"h", "j", "c", "d"}; // Stream.of(arr1, arr2, arr3).flatMap(x -> Arrays.stream(x)).forEach(System.out::println); Stream.of(arr1, arr2, arr3).flatMap(Arrays::stream).forEach(System.out::println); }
sorted:對流進行排序
String[] arr1 = {"abc","a","bc","abcd"}; /** * Comparator.comparing是一個鍵提取的功能 * 以下兩個語句表示相同意義 */ @Test public void testSorted1_(){ /** * 按照字符長度排序 */ Arrays.stream(arr1).sorted((x,y)->{ if (x.length()>y.length()) return 1; else if (x.length()<y.length()) return -1; else return 0; }).forEach(System.out::println); Arrays.stream(arr1).sorted(Comparator.comparing(String::length)).forEach(System.out::println); } /** * 倒序 * reversed(),java8泛型推導的問題,所以如果comparing里面是非方法引用的lambda表達式就沒辦法直接使用reversed() * Comparator.reverseOrder():也是用於翻轉順序,用於比較對象(Stream里面的類型必須是可比較的) * Comparator. naturalOrder():返回一個自然排序比較器,用於比較對象(Stream里面的類型必須是可比較的) */ @Test public void testSorted2_(){ Arrays.stream(arr1).sorted(Comparator.comparing(String::length).reversed()).forEach(System.out::println); Arrays.stream(arr1).sorted(Comparator.reverseOrder()).forEach(System.out::println); Arrays.stream(arr1).sorted(Comparator.naturalOrder()).forEach(System.out::println); } /** * thenComparing * 先按照首字母排序 * 之后按照String的長度排序 */ @Test public void testSorted3_(){ Arrays.stream(arr1).sorted(Comparator.comparing(this::com1).thenComparing(String::length)).forEach(System.out::println); } public char com1(String x){ return x.charAt(0); }
對map排序
map根據value值倒序排序,下面給出工具類:
public <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) { Map<K, V> result = new LinkedHashMap<>(); map.entrySet().stream() .sorted(Map.Entry.<K, V>comparingByValue() .reversed()).forEachOrdered(e -> result.put(e.getKey(), e.getValue())); return result; }
當然如果我們想根據map的key進行排序,需要對上面的工具類進行小小的修改,代碼如下:
public <K extends Comparable<? super K>, V > Map<K, V> sortByKey(Map<K, V> map) { Map<K, V> result = new LinkedHashMap<>(); map.entrySet().stream() .sorted(Map.Entry.<K, V>comparingByKey() .reversed()).forEachOrdered(e -> result.put(e.getKey(), e.getValue())); return result; }
我們可以看到,如果我們需要根據key排序,就需要讓key 繼承 Comparable ,也就說我們需要對待排序的字段繼承 Comparable接口。另一個問題就是,上面的這種寫法排序效果是 降序排序,如果我們需要升序排序的話,只需要將上面的.reversed()關鍵字限制去掉即可。
public <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) { Map<K, V> result = new LinkedHashMap<>(); map.entrySet().stream() .sorted(Map.Entry.<K, V>comparingByValue() ).forEachOrdered(e -> result.put(e.getKey(), e.getValue())); return result; }
list轉換為set( Collectors.toSet() )
List<Plantinfo> plantinfos = plantDao.selectList(qo);
Set<String> plantnoSet = plantinfos.stream().map(Plantinfo::getPlantno).collect(Collectors.toSet());
list轉換為map( Collectors.toMap() )
List<Userinfo> userinfos = userService.selectByPlantnoIn();
Map<String, String> map = userinfos.stream().collect(Collectors.toMap(Userinfo::getPlantno, Userinfo::getUsername, (k1, k2) -> k2)); //如果有重復的鍵,后一個替換前一個
list放入一個新的list中( Collectors.toList() )
//skip就是舍棄stream前多少個元素,那么limit就是返回流前面多少個元素(如果流里元素少於該值,則返回全部)。然后開啟並行處理。通過循環我們的分割list的目標就達到了,每次取到的sendList就是100,100這樣子的。
List<BigScreenRankingResponse> responsesPart = list.stream().skip(page * perpage).limit(perpage).parallel().collect(Collectors.toList());
4、返回特定的結果集合(limit/skip):
limit 返回 Stream 的前面 n 個元素;skip 則是扔掉前 n 個元素:
List<String> forEachLists = new ArrayList<>();
forEachLists.add("a");
forEachLists.add("b");
forEachLists.add("c");
forEachLists.add("d");
forEachLists.add("e");
forEachLists.add("f");
List<String> limitLists = forEachLists.stream().skip(2).limit(3).collect(Collectors.toList());
注意skip與limit是有順序關系的,比如使用skip(2)會跳過集合的前兩個,返回的為c、d、e、f,然后調用limit(3)會返回前3個,所以最后返回的c,d,e
Java8 Stream常用方法: https://blog.csdn.net/abcwywht/article/details/77991868
3、JDK8 新Date
3.1 jdk7 date 的缺點
3.1.1 所有的日期類都是可變的,因此他們都不是線程安全的,這是Java日期類最大的問題之一
3.1.2 Java的日期/時間類的定義並不一致,在java.util和java.sql的包中都有日期類,此外用於格式化和解析的類在java.text包中定義
3.1.3 java.util.Date同時包含日期和時間,而java.sql.Date僅包含日期,將其納入java.sql包並不合理。另外這兩個類都有相同的名字,這本身就是一個非常糟糕的設計。對於時間、時間戳、格式化以及解析,並沒有一些明確定義的類。對於格式化和解析的需求,我們有java.text.DateFormat抽象類,但通常情況下,SimpleDateFormat類被用於此類需求
3.1.4 日期類並不提供國際化,沒有時區支持,因此Java引入了java.util.Calendar和java.util.TimeZone類,但他們同樣存在上述所有的問題
3.2 jdk8 date 的優點
3.2.1 不變性:新的日期/時間API中,所有的類都是不可變的,這對多線程環境有好處。
3.2.2 關注點分離:新的API將人可讀的日期時間和機器時間(unix timestamp)明確分離,它為日期(Date)、時間(Time)、日期時間(DateTime)、時間戳(unix timestamp)以及時區定義了不同的類。
3.2.3 清晰:在所有的類中,方法都被明確定義用以完成相同的行為。舉個例子,要拿到當前實例我們可以使用now()方法,在所有的類中都定義了format()和parse()方法,而不是像以前那樣專門有一個獨立的類。為了更好的處理問題,所有的類都使用了工廠模式和策略模式,一旦你使用了其中某個類的方法,與其他類協同工作並不困難。
3.2.4 實用操作:所有新的日期/時間API類都實現了一系列方法用以完成通用的任務,如:加、減、格式化、解析、從日期/時間中提取單獨部分,等等。
3.2.5 可擴展性:新的日期/時間API是工作在ISO-8601日歷系統上的,但我們也可以將其應用在非IOS的日歷上。
3.3 jdk8 date 新增字段含義
Java.time包中的是類是不可變且線程安全的。新的時間及日期API位於java.time中,下面是一些關鍵類
java8 time包下關鍵字段解讀
屬性 | 含義 |
Instant | 代表的是時間戳 |
LocalDate | 代表日期,比如2020-01-14 |
LocalTime | 代表時刻,比如12:59:59 |
LocalDateTime | 代表具體時間 2020-01-12 12:22:26 |
ZonedDateTime | 代表一個包含時區的完整的日期時間,偏移量是以UTC/ 格林威治時間為基准的 |
Period | 代表時間段 |
ZoneOffset | 代表時區偏移量,比如:+8:00 |
Clock | 代表時鍾,比如獲取目前美國紐約的時間 |
3.4 使用jdk8 java.time下的date
3.4.1 獲取當前
Instant instant = Instant.now(); //獲取當前時間戳 LocalDate localDate = LocalDate.now(); //獲取當前日期 LocalTime localTime = LocalTime.now(); //獲取當前時刻 LocalDateTime localDateTime = LocalDateTime.now(); //獲取當前具體時間 ZonedDateTime zonedDateTime = ZonedDateTime.now(); //獲取帶有時區的時間
3.4.2 字符串轉換
jdk8: String str = "2019-01-11"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); LocalDate localDate = LocalDate.parse(str, formatter); jdk7: SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); try { Date date = simpleDateFormat.parse(str); } catch (ParseException e){ e.printStackTrace(); }
DateTimeFormatter
的包路徑是java.time.format
和LocalDate
一樣在java.time包
下面,而SimpleDateFormat
和Date
是不同的。所以當判斷引入路徑的時候更容易判斷。
當解析失敗的時候,兩個異常的拋出不一樣,DateTimeFormatter
拋出的是DateTimeParseException
,繼承自RuntimeException
,而ParseException
明顯繼承的是Exception
。
3.4.3 Date轉換LocalDate
import java.time.Instant; import java.time.LocalDate; import java.time.ZoneId; import java.util.Date; public class Test { public static void main(String[] args) { Date date = new Date(); Instant instant = date.toInstant(); ZoneId zoneId = ZoneId.systemDefault(); // atZone()方法返回在指定時區從此Instant生成的ZonedDateTime。 LocalDate localDate = instant.atZone(zoneId).toLocalDate(); System.out.println("Date = " + date); System.out.println("LocalDate = " + localDate); } }
3.4.5 LocalDate 轉 Date
import java.time.LocalDate; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Date; public class Test { public static void main(String[] args) { ZoneId zoneId = ZoneId.systemDefault(); LocalDate localDate = LocalDate.now(); ZonedDateTime zdt = localDate.atStartOfDay(zoneId); Date date = Date.from(zdt.toInstant()); System.out.println("LocalDate = " + localDate); System.out.println("Date = " + date); } }
3.4.5 時間戳轉LocalDateTime
long timestamp = System.currentTimeMillis(); Instant instant = Instant.ofEpochMilli(timestamp); LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
3.4.6 LocalDateTime轉時間戳
LocalDateTime dateTime = LocalDateTime.now(); dateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli(); dateTime.toInstant(ZoneOffset.of("+08:00")).toEpochMilli(); dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
3.4.7 LocalDate常用方法總結
getYear() int 獲取當前日期的年份 getMonth() Month 獲取當前日期的月份對象 getMonthValue() int 獲取當前日期是第幾月 getDayOfWeek() DayOfWeek 表示該對象表示的日期是星期幾 getDayOfMonth() int 表示該對象表示的日期是這個月第幾天 getDayOfYear() int 表示該對象表示的日期是今年第幾天 withYear(int year) LocalDate 修改當前對象的年份 withMonth(int month) LocalDate 修改當前對象的月份 withDayOfMonth(intdayOfMonth) LocalDate 修改當前對象在當月的日期 isLeapYear() boolean 是否是閏年 lengthOfMonth() int 這個月有多少天 lengthOfYear() int 該對象表示的年份有多少天(365或者366) plusYears(longyearsToAdd) LocalDate 當前對象增加指定的年份數 plusMonths(longmonthsToAdd) LocalDate 當前對象增加指定的月份數 plusWeeks(longweeksToAdd) LocalDate 當前對象增加指定的周數 plusDays(longdaysToAdd) LocalDate 當前對象增加指定的天數 minusYears(longyearsToSubtract) LocalDate 當前對象減去指定的年數 minusMonths(longmonthsToSubtract) LocalDate 當前對象減去注定的月數 minusWeeks(longweeksToSubtract) LocalDate 當前對象減去指定的周數 minusDays(longdaysToSubtract) LocalDate 當前對象減去指定的天數 compareTo(ChronoLocalDateother) int 比較當前對象和other對象在時間上的大小,返回值如果為正,則當前對象時間較晚, isBefore(ChronoLocalDateother) boolean 比較當前對象日期是否在other對象日期之前 isAfter(ChronoLocalDateother) boolean 比較當前對象日期是否在other對象日期之后 isEqual(ChronoLocalDateother) boolean 比較兩個日期對象是否相等
項目中的具體使用
package com.chitic.supplywater.common.api.util;
import com.chitic.supplywater.common.api.request.DataDevDayRequest;
import java.math.BigDecimal;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Stream;
/**
* @Description TODO 時間工具類
* @Author GX
* @Date 2019/7/1 9:45
* @Version V1.0
**/
public class DateUtil {
public static final LocalDate NOW = LocalDate.now();
/**
* 獲取當前時間的10位時間戳
* @return
*/
public static Long getDate(){
//方式1
//Long timestamp = Timestamp.valueOf(LocalDateTime.now()).getTime()/1000L;
//方式2
//Long timestamp = Instant.now().toEpochMilli()/1000L;
//方式3
Long timestamp = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
//方式4
//Long startTimestamp = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000L;
//方式5
//Long timestamp = System.currentTimeMillis()/1000;
return timestamp;
}
/**
* 獲取當前時間的前60秒的10位時間戳
* @return
*/
public static Long getMinusSeconds(){
LocalDateTime dataTime = LocalDateTime.now().minus(60, ChronoUnit.SECONDS);
// Long dateTimestamp = dataTime.toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000L;
Long dateTimestamp = dataTime.toEpochSecond(ZoneOffset.of("+8"));
return dateTimestamp;
}
/**
* 獲取當前月的開始10位時間戳
* @return
*/
public static Long getMonths(){
LocalDate localDate = LocalDate.now().plusMonths(0).with(TemporalAdjusters.firstDayOfMonth());
Long startsTimestamp = LocalDateTime.of(localDate, LocalTime.MIN).toEpochSecond(ZoneOffset.of("+8"));
return startsTimestamp;
}
/**
* 獲取N個月前的開始時間和10位時間戳
* @param n
* @return
*/
public static Map<String,Object> getMinusYears(int n){
Map<String,Object> map = new HashMap<>(2);
String date = LocalDate.now().minusMonths(n).format(DateTimeFormatter.ofPattern("yyyy-MM"));
map.put("date",date);
LocalDateTime today_start = LocalDateTime.of(LocalDate.now().minusMonths(11), LocalTime.MIN);
Long startTimestamp = today_start.toEpochSecond(ZoneOffset.of("+8"));
map.put("startTimestamp",startTimestamp);
return map;
}
/**
* 獲取N天前的開始時間和10位時間戳, 結束時間和時間戳
* n = 0 即為今天
* @param n
* @return
*/
public static Map<String,Object> getMinusDaysPar(int n){
Map<String,Object> map = new HashMap<>(3);
String date = LocalDate.now().minusDays(n).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
map.put("date",date);
LocalDateTime today_start = LocalDateTime.of(LocalDate.now().minusDays(n), LocalTime.MIN);
Long startTimestamp = today_start.toEpochSecond(ZoneOffset.of("+8"));
map.put("startTimestamp",startTimestamp);
LocalDateTime today_end = LocalDateTime.of(LocalDate.now().minusDays(n), LocalTime.MAX);
Long endTimestamp = today_end.toEpochSecond(ZoneOffset.of("+8"));
map.put("endTimestamp",endTimestamp);
return map;
}
/**
* 根據時間戳 獲取當天的時間
* @param timestamp
* @return
*/
public static Map<String,Object> getTimestampIsDate(Long timestamp){
Map<String,Object> map = new HashMap<>(3);
LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(timestamp, 0, ZoneOffset.ofHours(8));
LocalDate localDate = localDateTime.toLocalDate();
String date = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
map.put("date",date);
LocalDateTime today_start = LocalDateTime.of(localDate, LocalTime.MIN);
Long startTimestamp = today_start.toEpochSecond(ZoneOffset.of("+8"));
map.put("startTimestamp",startTimestamp);
LocalDateTime today_end = LocalDateTime.of(localDate, LocalTime.MAX);
Long endTimestamp = today_end.toEpochSecond(ZoneOffset.of("+8"));
map.put("endTimestamp",endTimestamp);
return map;
}
/**
* 當前時間戳和一個小時之前的時間戳
* @return
*/
public static Map<String,Long> getminusHours(){
LocalDateTime localDateTime = LocalDateTime.now().minusHours(1);
Long startTimestamp = localDateTime.toEpochSecond(ZoneOffset.of("+8"));
Long endTimestamp = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
Map<String,Long> map = new HashMap<>(2);
map.put("startTimestamp",startTimestamp);
map.put("endTimestamp",endTimestamp);
return map;
}
/**
* 根據時間yyyy-mm-dd返回此月的開始時間戳和結束時間戳
* @param date
* @return
*/
public static Map<String,Object> getToMonthTimeststamp(String date){
Map<String,Object> map = new HashMap<>(3);
LocalDate localDate = LocalDate.parse(date);
map.put("date",date);
LocalDate localDate1 = localDate.with(TemporalAdjusters.firstDayOfMonth());
Long startTimestamp = LocalDateTime.of(localDate1, LocalTime.MIN).toEpochSecond(ZoneOffset.of("+8"));
map.put("startTimestamp",startTimestamp);
LocalDate localDate2 = localDate.with(TemporalAdjusters.lastDayOfMonth());
Long endTimestamp = LocalDateTime.of(localDate2, LocalTime.MAX).toEpochSecond(ZoneOffset.of("+8"));
map.put("endTimestamp",endTimestamp);
return map;
}
/**
* //時間戳轉時間 LocalDateTime,格式化
* @return
*/
public static String getFormatDay(Long timestamp){
LocalDateTime dateTime =LocalDateTime.ofEpochSecond(timestamp,0, ZoneOffset.ofHours(8));
String format = dateTime.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
return format;
}
/**
* 獲取所傳日期的前N天
* @return
*/
public static String getMinusDaysDate(String d, int n){
LocalDate parse = LocalDate.parse(d);
String date = parse.minusDays(n).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
LocalDate.now().minusDays(n).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
return date;
}
/**
* 獲取當前日期的前N天 yyyyMMdd
* @return
*/
public static String getFormatDate(int n){
String date = LocalDate.now().minusDays(n).format(DateTimeFormatter.ofPattern("yyyyMMdd"));
return date;
}
/**
* 根據傳來的日期獲取n個月之前的yyyy-mm
* @param date
* @param n
* @return
*/
public static String getYearMonth(String date, int n){
LocalDate localDate = LocalDate.parse(date+"-01");
return localDate.minusMonths(n).format(DateTimeFormatter.ofPattern("yyyy-MM"));
}
/**
* 當前時間的前n個月
* @param n
* @return
*/
public static String getMinusMonths12(int n){
return LocalDate.now().minusMonths(n).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
/**
* 根據時間yyyy-mm-dd返回此天前一天的開始時間戳和當前時間戳
* @param date
* @return
*/
public static Map<String,Object> getToTimeststamp(String date,int n){
Map<String,Object> map = new HashMap<>(3);
LocalDate localDate = LocalDate.parse(date);
LocalDate date1 = LocalDate.parse(date).minusDays(n);
map.put("date",date1);
LocalDateTime today_start = LocalDateTime.of(localDate.minusDays(n), LocalTime.MIN);
Long startTimestamp = today_start.toEpochSecond(ZoneOffset.of("+8"));
map.put("startTimestamp",startTimestamp);
LocalDateTime now = LocalDateTime.now();
long between = ChronoUnit.DAYS.between(date1, now);
Long endTimestamp = now.minusDays(between).toEpochSecond(ZoneOffset.of("+8"));
map.put("endTimestamp",endTimestamp);
return map;
}
public static Map<String,Object> getTopToTimeststamp(String date, int n){
Map<String,Object> map = new HashMap<>(3);
LocalDate localDate = LocalDate.parse(date).minusDays(n);
map.put("date",localDate);
LocalDateTime today_start = LocalDateTime.of(localDate, LocalTime.MIN);
Long startTimestamp = today_start.toEpochSecond(ZoneOffset.of("+8"));
map.put("startTimestamp",startTimestamp);
LocalDateTime today_end = LocalDateTime.of(localDate, LocalTime.MAX);
Long endTimestamp = today_end.toEpochSecond(ZoneOffset.of("+8"));
map.put("endTimestamp",endTimestamp);
return map;
}
/**
* 獲取兩個時間段的所有的天數
* @param date
* @return
*/
public static List<String> getListDate(String date){
LocalDate start = LocalDate.parse(date+"-01");
LocalDate end = LocalDate.now().minusDays(1);
//如果不是當月,返回所選月的所有天, 是當月,返回已過的天
long between = ChronoUnit.DAYS.between(start, end);
List<String> list = new ArrayList<>();
Stream.iterate(start, a -> {
return a.plusDays(1);
}).limit(between + 1).forEach(f -> {
list.add(f.toString().replace("-","" ));
});
return list;
}
//判斷是否是當月
public static Boolean isToMonth(String date){
String yyyyMM = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
if(yyyyMM.equals(date)){
return true;
}
return false;
}
//判斷是否是當年
public static Boolean isToYear(String date){
String yyyy = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy"));
if(yyyy.equals(date)){
return true;
}
return false;
}
/**
* @Description TODO 獲取本周的第一天或最后一天
* @Param: [today, isFirst: true 表示開始時間,false表示結束時間]
* @return: java.lang.String
* @Exception:
*/
public static String getStartOrEndDayOfWeek(LocalDate today, Boolean isFirst){
LocalDate resDate = LocalDate.now();
if (today == null) {
today = resDate;
}
DayOfWeek week = today.getDayOfWeek();
int value = week.getValue();
if (isFirst) {
resDate = today.minusDays(value - 1);
} else {
resDate = today.plusDays(7 - value);
}
return resDate.toString();
}
/**
* @Description TODO 獲取本月的第一天或最后一天
* @Param: [today, isFirst: true 表示開始時間,false表示結束時間]
* @return: java.lang.String
* @Exception:
*/
public static String getStartOrEndDayOfMonth(LocalDate today, Boolean isFirst){
LocalDate resDate = LocalDate.now();
if (today == null) {
today = resDate;
}
Month month = today.getMonth();
int length = month.length(today.isLeapYear());
if (isFirst) {
resDate = LocalDate.of(today.getYear(), month, 1);
} else {
resDate = LocalDate.of(today.getYear(), month, length);
}
return resDate.toString();
}
/**
* @Description TODO 獲取本季度的第一天或最后一天
* @Param: [today, isFirst: true 表示開始時間,false表示結束時間]
* @return: java.lang.String
* @Exception:
*/
public static String getStartOrEndDayOfQuarter(LocalDate today, Boolean isFirst){
LocalDate resDate = LocalDate.now();
if (today == null) {
today = resDate;
}
Month month = today.getMonth();
Month firstMonthOfQuarter = month.firstMonthOfQuarter();
Month endMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2);
if (isFirst) {
resDate = LocalDate.of(today.getYear(), firstMonthOfQuarter, 1);
} else {
resDate = LocalDate.of(today.getYear(), endMonthOfQuarter, endMonthOfQuarter.length(today.isLeapYear()));
}
return resDate.toString();
}
/**
* @Description TODO 獲取本年的第一天或最后一天
* @Param: [today, isFirst: true 表示開始時間,false表示結束時間]
* @return: java.lang.String
* @Exception:
*/
public static String getStartOrEndDayOfYear(LocalDate today, Boolean isFirst){
LocalDate resDate = LocalDate.now();
if (today == null) {
today = resDate;
}
if (isFirst) {
resDate = LocalDate.of(today.getYear(), Month.JANUARY, 1);
} else {
resDate = LocalDate.of(today.getYear(), Month.DECEMBER, Month.DECEMBER.length(today.isLeapYear()));
}
return resDate.toString();
}
public static void main(String[] args) {
//System.getProperties().list(System.out);
//System.out.println(System.getProperty("user.name"));
//System.out.println(System.getProperty("java.library.path"));
int i = 2;
System.out.println("i : " + (i<<3));
System.out.println("當前時間戳:"+ getDate());
System.err.println("今天前的時間戳"+getMinusDaysPar(0));
System.err.println("1天前的時間戳"+getMinusDaysPar(1));
System.err.println("2天前的時間戳"+getMinusDaysPar(2));
System.err.println("3天前的時間戳"+getMinusDaysPar(3));
System.err.println("4天前的時間戳"+getMinusDaysPar(4));
System.err.println("5天前的時間戳"+getMinusDaysPar(5));
System.err.println("6天前的時間戳"+getMinusDaysPar(6));
System.err.println("7天前的時間戳"+getMinusDaysPar(7));
System.err.println("1個月前的時間戳"+getMinusYears(1));
System.err.println("2個月前的時間戳"+getMinusYears(2));
System.err.println("3個月前的時間戳"+getMinusYears(3));
System.err.println("4個月前的時間戳"+getMinusYears(4));
System.err.println("5個月前的時間戳"+getMinusYears(5));
}
public static Date getFromSeconds(Long seconds) {
if (null == seconds) {
return null;
}
return new Date(seconds * 1000L);
}
}