Lambda表達式(也稱爲閉包)是Java 8中最大和最使人期待的語言改變。它容許咱們將函數當成參數傳遞給某個方法,或者把代碼自己看成數據處理:函數式開發者很是熟悉這些概念。php
不少JVM平臺上的語言(Groovy、Scala等)從誕生之日就支持Lambda表達式,可是Java開發者沒有選擇,只能使用匿名內部類代替Lambda表達式。html
Lambda的設計耗費了不少時間和很大的社區力量,最終找到一種折中的實現方案,能夠實現簡潔而緊湊的語言結構。java
最簡單的Lambda表達式可由逗號分隔的參數列表、->符號和語句塊組成,例如:sql
Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );
在上面這個代碼中的參數e的類型是由編譯器推理得出的,你也能夠顯式指定該參數的類型,例如:express
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的),例以下列兩個代碼塊的效果徹底相同:swift
String separator = ","; Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.print( e + separator ) );
和api
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表達式的細節,能夠參考官方文檔。
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!
@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根據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<Plantinfo> plantinfos = plantDao.selectList(qo);
Set<String> plantnoSet = plantinfos.stream().map(Plantinfo::getPlantno).collect(Collectors.toSet());
List<Userinfo> userinfos = userService.selectByPlantnoIn();
Map<String, String> map = userinfos.stream().collect(Collectors.toMap(Userinfo::getPlantno, Userinfo::getUsername, (k1, k2) -> k2)); //若是有重複的鍵,後一個替換前一個
//skip就是捨棄stream前多少個元素,那麼limit就是返回流前面多少個元素(若是流裏元素少於該值,則返回所有)。而後開啓並行處理。經過循環咱們的分割list的目標就達到了,每次取到的sendList就是100,100這樣子的。
List<BigScreenRankingResponse> responsesPart = list.stream().skip(page * perpage).limit(perpage).parallel().collect(Collectors.toList());
四、返回特定的結果集合(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
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.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的日曆上。
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.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; } 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); }}