Merge pull request #7 from halo-dev/master

update to 1.3.1
pull/756/head
jinqilin721 2020-03-30 15:26:19 +08:00 committed by GitHub
commit de89b65837
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 889 additions and 125 deletions

View File

@ -1,5 +1,12 @@
# CHANGELOG
# 1.3.1
# Fixed
- 修复自定义页面设置中的地址预览出现 undefined 的问题。
- 升级 fastjson 版本为 `1.2.67`
# 1.3.0
## Feature

View File

@ -2,14 +2,48 @@
### 开发步骤
1. `Fork` 本仓库到你自己的 Github。
2. `Clone` 你刚刚 Fork 的仓库到本地。
3. 执行 `git checkout dev` 切换到 `dev` 分支并进行开发。
4. 提交代码到自己的仓库。
5. 回到自己的仓库页面,选择 `New pull request` 按钮,创建 `Pull request` 到原仓库的 `dev` 分支。
6. 等待合并。
#### 1. Fork 此仓库
点击右上角的 `fork` 按钮即可。
#### 2. Clone 仓库到本地
```bash
git clone https://github.com/{YOUR_USERNAME}/halo
git submodule init
git submodule update
```
#### 3. 创建新的开发分支
```bash
git checkout -b {BRANCH_NAME}
```
#### 4. 提交代码
```bash
git push origin {BRANCH_NAME}
```
#### 5. 提交 pull request
回到自己的仓库页面,选择 `New pull request` 按钮,创建 `Pull request` 到原仓库的 `master` 分支。
然后等待我们 Review 即可,如有 `Change Request`,再本地修改之后再次提交即可。
#### 6. 更新主仓库代码到自己的仓库
```bash
git remote add upstream git@github.com:halo-dev/halo.git
git pull upstream master
git push
```
### 开发规范
1. 在提交前请使用 IDE 格式化代码。
2. 不接受创建 `Pull request``master` 分支。
请参考 [https://halo.run/archives/code-style](https://halo.run/archives/code-style),请确保所有代码格式化之后再提交。

View File

@ -26,7 +26,7 @@
另外,写给想自己拉代码编译运行的同学:
> 目前我们的开发分支即 master肯定会有很多小问题不要运行不起来就跑过来吐槽什么代码开源不完整之类的多找找自己的原因。同时建议下载最新 release 版本的代码,或者在 master 分支执行 `git checkout v1.3.0`。
> 目前我们的开发分支即 master肯定会有很多小问题不要运行不起来就跑过来吐槽什么代码开源不完整之类的多找找自己的原因。同时建议下载最新 release 版本的代码,或者在 master 分支执行 `git checkout v1.3.1`。
PS实在不想写这个声明影响 README 的美观),但是就目前来看,写在 README 上是有必要的,因为大部分遇到问题的人都不会去仔细阅读文档。
@ -35,13 +35,13 @@ PS实在不想写这个声明影响 README 的美观),但是就目前
### 下载最新的 Halo 安装包
```bash
curl -L https://github.com/halo-dev/halo/releases/download/v1.3.0/halo-1.3.0.jar --output halo-latest.jar
curl -L https://github.com/halo-dev/halo/releases/download/v1.3.1/halo-1.3.1.jar --output halo-latest.jar
```
或者
```bash
wget https://github.com/halo-dev/halo/releases/download/v1.3.0/halo-1.3.0.jar -O halo-latest.jar
wget https://github.com/halo-dev/halo/releases/download/v1.3.1/halo-1.3.1.jar -O halo-latest.jar
```
### 启动 Halo

View File

@ -1,22 +1,22 @@
plugins {
id 'org.springframework.boot' version '2.2.5.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'checkstyle'
id 'java'
id "org.springframework.boot" version "2.2.5.RELEASE"
id "io.spring.dependency-management" version "1.0.9.RELEASE"
id "checkstyle"
id "java"
}
group = 'run.halo.app'
version = '1.3.0'
description = 'Halo, An excellent open source blog publishing application.'
group = "run.halo.app"
version = "1.3.1"
description = "Halo, An excellent open source blog publishing application."
java {
archivesBaseName = 'halo'
archivesBaseName = "halo"
sourceCompatibility = JavaVersion.VERSION_1_8
}
repositories {
maven {
url 'https://maven.aliyun.com/nexus/content/groups/public'
url "https://maven.aliyun.com/nexus/content/groups/public"
}
mavenCentral()
jcenter()
@ -24,8 +24,8 @@ repositories {
configurations {
implementation {
exclude module: 'spring-boot-starter-tomcat'
exclude module: 'slf4j-log4j12'
exclude module: "spring-boot-starter-tomcat"
exclude module: "slf4j-log4j12"
}
developmentOnly
@ -39,95 +39,100 @@ configurations {
}
}
bootJar {
manifest {
attributes('Implementation-Title': 'Halo Application',
'Implementation-Version': archiveVersion)
springBoot {
buildInfo()
}
// gradle Property Expansion ${..} springboot springboot \${..}
processResources {
filesMatching("application.yaml") {
expand(project.properties)
}
}
ext {
set('hutoolVersion', "5.2.3")
set('upyunSdkVersion', "4.2.0")
set('qiniuSdkVersion', "7.2.28")
set('aliyunSdkVersion', "3.8.1")
set('baiduSdkVersion', "0.10.36")
set('qcloudSdkVersion', "5.6.18")
set('swaggerVersion', "2.9.2")
set('commonsLangVersion', "3.9")
set('httpclientVersion', "4.5.12")
set('dataformatYamlVersion', "2.10.3")
set('jgitVersion', "5.7.0.202003110725-r")
set('flexmarkVersion', "0.60.2")
set('thumbnailatorVersion', "0.4.11")
set('image4jVersion', "0.7zensight1")
set('flywayVersion', "6.3.1")
set('h2Version', "1.4.196")
set('levelDbVersion', "0.12")
set('jsonVersion', "20190722")
set('fastJsonVersion', "1.2.66")
set('annotationsVersion',"3.0.1")
hutoolVersion = "5.2.3"
upyunSdkVersion = "4.2.0"
qiniuSdkVersion = "7.2.28"
aliyunSdkVersion = "3.8.1"
baiduSdkVersion = "0.10.36"
qcloudSdkVersion = "5.6.18"
swaggerVersion = "2.9.2"
commonsLangVersion = "3.9"
httpclientVersion = "4.5.12"
dataformatYamlVersion = "2.10.3"
jgitVersion = "5.7.0.202003110725-r"
flexmarkVersion = "0.60.2"
thumbnailatorVersion = "0.4.11"
image4jVersion = "0.7zensight1"
flywayVersion = "6.3.1"
h2Version = "1.4.196"
levelDbVersion = "0.12"
jsonVersion = "20190722"
fastJsonVersion = "1.2.67"
annotationsVersion = "3.0.1"
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-undertow'
implementation 'org.springframework.boot:spring-boot-starter-freemarker'
implementation "org.springframework.boot:spring-boot-starter-actuator"
implementation "org.springframework.boot:spring-boot-starter-data-jpa"
implementation "org.springframework.boot:spring-boot-starter-web"
implementation "org.springframework.boot:spring-boot-starter-undertow"
implementation "org.springframework.boot:spring-boot-starter-freemarker"
implementation "com.sun.mail:jakarta.mail"
implementation "cn.hutool:hutool-core:${hutoolVersion}"
implementation "cn.hutool:hutool-crypto:${hutoolVersion}"
implementation "cn.hutool:hutool-extra:${hutoolVersion}"
implementation "com.upyun:java-sdk:${upyunSdkVersion}"
implementation "com.qiniu:qiniu-java-sdk:${qiniuSdkVersion}"
implementation "com.aliyun.oss:aliyun-sdk-oss:${aliyunSdkVersion}"
implementation "com.baidubce:bce-java-sdk:${baiduSdkVersion}"
implementation "com.qcloud:cos_api:${qcloudSdkVersion}"
implementation "io.springfox:springfox-swagger2:${swaggerVersion}"
implementation "io.springfox:springfox-swagger-ui:${swaggerVersion}"
implementation "org.apache.commons:commons-lang3:${commonsLangVersion}"
implementation "org.apache.httpcomponents:httpclient:${httpclientVersion}"
implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${dataformatYamlVersion}"
implementation "org.eclipse.jgit:org.eclipse.jgit:${jgitVersion}"
implementation "com.google.code.findbugs:annotations:${annotationsVersion}"
implementation "cn.hutool:hutool-core:$hutoolVersion"
implementation "cn.hutool:hutool-crypto:$hutoolVersion"
implementation "cn.hutool:hutool-extra:$hutoolVersion"
implementation "com.upyun:java-sdk:$upyunSdkVersion"
implementation "com.qiniu:qiniu-java-sdk:$qiniuSdkVersion"
implementation "com.aliyun.oss:aliyun-sdk-oss:$aliyunSdkVersion"
implementation "com.baidubce:bce-java-sdk:$baiduSdkVersion"
implementation "com.qcloud:cos_api:$qcloudSdkVersion"
implementation "io.springfox:springfox-swagger2:$swaggerVersion"
implementation "io.springfox:springfox-swagger-ui:$swaggerVersion"
implementation "org.apache.commons:commons-lang3:$commonsLangVersion"
implementation "org.apache.httpcomponents:httpclient:$httpclientVersion"
implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$dataformatYamlVersion"
implementation "org.eclipse.jgit:org.eclipse.jgit:$jgitVersion"
implementation "com.google.code.findbugs:annotations:$annotationsVersion"
implementation "com.vladsch.flexmark:flexmark:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark-ext-attributes:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark-ext-autolink:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark-ext-emoji:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark-ext-escaped-character:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark-ext-gfm-strikethrough:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark-ext-gfm-tasklist:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark-ext-ins:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark-ext-media-tags:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark-ext-tables:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark-ext-toc:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark-ext-superscript:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark-ext-yaml-front-matter:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark-ext-gitlab:${flexmarkVersion}"
// implementation "com.vladsch.flexmark:flexmark-html-parser:${flexmarkVersion}"
implementation "com.vladsch.flexmark:flexmark:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-attributes:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-autolink:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-emoji:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-escaped-character:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-gfm-strikethrough:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-gfm-tasklist:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-ins:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-media-tags:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-tables:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-toc:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-superscript:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-yaml-front-matter:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-gitlab:$flexmarkVersion"
// implementation "com.vladsch.flexmark:flexmark-html-parser:$flexmarkVersion"
implementation "net.coobird:thumbnailator:${thumbnailatorVersion}"
implementation "net.sf.image4j:image4j:${image4jVersion}"
implementation "org.flywaydb:flyway-core:${flywayVersion}"
implementation "net.coobird:thumbnailator:$thumbnailatorVersion"
implementation "net.sf.image4j:image4j:$image4jVersion"
implementation "org.flywaydb:flyway-core:$flywayVersion"
implementation "org.json:json:${jsonVersion}"
implementation "com.alibaba:fastjson:${fastJsonVersion}"
implementation "org.json:json:$jsonVersion"
implementation "com.alibaba:fastjson:$fastJsonVersion"
implementation "org.iq80.leveldb:leveldb:${levelDbVersion}"
runtimeOnly "com.h2database:h2:${h2Version}"
runtimeOnly 'mysql:mysql-connector-java'
implementation "org.iq80.leveldb:leveldb:$levelDbVersion"
runtimeOnly "com.h2database:h2:$h2Version"
runtimeOnly "mysql:mysql-connector-java"
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
compileOnly "org.projectlombok:lombok"
annotationProcessor "org.projectlombok:lombok"
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
testCompileOnly "org.projectlombok:lombok"
testAnnotationProcessor "org.projectlombok:lombok"
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation "org.springframework.boot:spring-boot-starter-test"
developmentOnly 'org.springframework.boot:spring-boot-devtools'
developmentOnly "org.springframework.boot:spring-boot-devtools"
}

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.info.BuildProperties;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -15,8 +16,10 @@ import run.halo.app.cache.AbstractStringCacheStore;
import run.halo.app.cache.InMemoryCacheStore;
import run.halo.app.cache.LevelCacheStore;
import run.halo.app.config.properties.HaloProperties;
import run.halo.app.model.support.HaloConst;
import run.halo.app.utils.HttpClientUtils;
import javax.annotation.PostConstruct;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
@ -34,6 +37,9 @@ public class HaloConfiguration {
@Autowired
HaloProperties haloProperties;
@Autowired
BuildProperties buildProperties;
@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
builder.failOnEmptyBeans(false);
@ -70,4 +76,8 @@ public class HaloConfiguration {
}
@PostConstruct
public void init() {
HaloConst.HALO_VERSION = buildProperties.getVersion();
}
}

View File

@ -113,8 +113,8 @@ public class YamlThemeConfigResolverImpl implements ThemeConfigResolver {
item.setName(itemMap.get("name").toString());
item.setLabel(itemMap.getOrDefault("label", item.getName()).toString());
Object dataType = itemMap.getOrDefault("data-type", itemMap.get("dataType"));
item.setDataType(DataType.typeOf(dataType));
item.setType(InputType.typeOf(itemMap.get("type")));
item.setDataType(item.getType().equals(InputType.SWITCH) ? DataType.BOOL : DataType.typeOf(dataType));
item.setDefaultValue(itemMap.get("default"));
item.setPlaceholder(itemMap.getOrDefault("placeholder", "").toString());
item.setDescription(itemMap.getOrDefault("description", "").toString());
@ -140,8 +140,8 @@ public class YamlThemeConfigResolverImpl implements ThemeConfigResolver {
item.setName(key.toString());
item.setLabel(itemMap.getOrDefault("label", item.getName()).toString());
Object dataType = itemMap.getOrDefault("data-type", itemMap.get("dataType"));
item.setDataType(DataType.typeOf(dataType));
item.setType(InputType.typeOf(itemMap.get("type")));
item.setDataType(item.getType().equals(InputType.SWITCH) ? DataType.BOOL : DataType.typeOf(dataType));
item.setDefaultValue(itemMap.get("default"));
item.setPlaceholder(itemMap.getOrDefault("placeholder", "").toString());
item.setDescription(itemMap.getOrDefault("description", "").toString());

View File

@ -17,7 +17,9 @@ import javax.persistence.*;
*/
@Data
@Entity
@Table(name = "attachments")
@Table(name = "attachments",
indexes = {@Index(name = "attachments_media_type", columnList = "media_type"),
@Index(name = "attachments_create_time", columnList = "create_time")})
@ToString
@EqualsAndHashCode(callSuper = true)
public class Attachment extends BaseEntity {

View File

@ -16,7 +16,9 @@ import javax.persistence.*;
*/
@Data
@Entity
@Table(name = "menus", indexes = {@Index(name = "menus_parent_id", columnList = "parent_id")})
@Table(name = "menus",
indexes = {@Index(name = "menus_parent_id", columnList = "parent_id"),
@Index(name = "menus_name", columnList = "name")})
@ToString
@EqualsAndHashCode(callSuper = true)
public class Menu extends BaseEntity {

View File

@ -16,7 +16,9 @@ import java.util.Date;
*/
@Data
@Entity
@Table(name = "photos", indexes = {@Index(name = "photos_team", columnList = "team")})
@Table(name = "photos",
indexes = {@Index(name = "photos_team", columnList = "team"),
@Index(name = "photos_create_time", columnList = "create_time")})
@ToString
@EqualsAndHashCode(callSuper = true)
public class Photo extends BaseEntity {

View File

@ -44,7 +44,12 @@ public enum InputType {
/**
* Attachment picker input type
*/
ATTACHMENT;
ATTACHMENT,
/**
* Switch input type, only true or false
*/
SWITCH;
/**
* Convert type to input type.

View File

@ -50,10 +50,6 @@ public class HaloConst {
*/
public final static String DEFAULT_THEME_ID = "caicai_anatole";
/**
* Version constant. (Available in production environment)
*/
public static final String HALO_VERSION;
/**
* Path separator.
*/
@ -143,8 +139,9 @@ public class HaloConst {
*/
public static String USER_SESSION_KEY = "user_session";
static {
// Set version
HALO_VERSION = HaloConst.class.getPackage().getImplementationVersion();
}
/**
* Version constant.
*/
public static String HALO_VERSION = null;
}

View File

@ -10,9 +10,9 @@ import run.halo.app.repository.PostCommentRepository;
import run.halo.app.service.CommentBlackListService;
import run.halo.app.service.OptionService;
import run.halo.app.service.base.AbstractCrudService;
import run.halo.app.utils.DateTimeUtils;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Optional;
@ -26,7 +26,6 @@ import java.util.Optional;
@Service
@Slf4j
public class CommentBlackListServiceImpl extends AbstractCrudService<CommentBlackList, Long> implements CommentBlackListService {
private static final ZoneId ZONE_ID = ZoneId.of("Asia/Shanghai");
private final CommentBlackListRepository commentBlackListRepository;
private final PostCommentRepository postCommentRepository;
private final OptionService optionService;
@ -50,10 +49,9 @@ public class CommentBlackListServiceImpl extends AbstractCrudService<CommentBlac
*/
Optional<CommentBlackList> blackList = commentBlackListRepository.findByIpAddress(ipAddress);
LocalDateTime now = LocalDateTime.now();
Date endTime = new Date(now.atZone(ZONE_ID).toInstant().toEpochMilli());
Date endTime = new Date(DateTimeUtils.toEpochMilli(now));
Integer banTime = optionService.getByPropertyOrDefault(CommentProperties.COMMENT_BAN_TIME, Integer.class, 10);
Date startTime = new Date(now.minusMinutes(banTime)
.atZone(ZONE_ID).toInstant().toEpochMilli());
Date startTime = new Date(DateTimeUtils.toEpochMilli(now.minusMinutes(banTime)));
Integer range = optionService.getByPropertyOrDefault(CommentProperties.COMMENT_RANGE, Integer.class, 30);
boolean isPresent = postCommentRepository.countByIpAndTime(ipAddress, startTime, endTime) >= range;
if (isPresent && blackList.isPresent()) {
@ -61,10 +59,10 @@ public class CommentBlackListServiceImpl extends AbstractCrudService<CommentBlac
return CommentViolationTypeEnum.FREQUENTLY;
} else if (isPresent) {
CommentBlackList commentBlackList = CommentBlackList
.builder()
.banTime(getBanTime(now, banTime))
.ipAddress(ipAddress)
.build();
.builder()
.banTime(getBanTime(now, banTime))
.ipAddress(ipAddress)
.build();
super.create(commentBlackList);
return CommentViolationTypeEnum.FREQUENTLY;
}
@ -75,10 +73,10 @@ public class CommentBlackListServiceImpl extends AbstractCrudService<CommentBlac
blackList.setBanTime(getBanTime(localDateTime, banTime));
int updateResult = commentBlackListRepository.updateByIpAddress(blackList);
Optional.of(updateResult)
.filter(result -> result <= 0).ifPresent(result -> log.error("更新评论封禁时间失败"));
.filter(result -> result <= 0).ifPresent(result -> log.error("更新评论封禁时间失败"));
}
private Date getBanTime(LocalDateTime localDateTime, Integer banTime) {
return new Date(localDateTime.plusMinutes(banTime).atZone(ZONE_ID).toInstant().toEpochMilli());
return new Date(DateTimeUtils.toEpochMilli(localDateTime.plusMinutes(banTime)));
}
}

View File

@ -0,0 +1,543 @@
package run.halo.app.utils;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.Temporal;
import static cn.hutool.core.date.DatePattern.*;
/**
*
*
* @author LeiXinXin
* @date 2019/12/10
*/
public class DateTimeUtils {
/**
* {@link DateTimeFormatter}yyyyMMddHHmmssSSS
*/
public static final DateTimeFormatter PURE_DATETIME_MS_FORMATTER = new DateTimeFormatterBuilder()
.appendPattern(PURE_DATETIME_PATTERN)
.appendValue(ChronoField.MILLI_OF_SECOND, 3)
.toFormatter();
/**
* {@link DateTimeFormatter}yyyyMMdd
*/
public static final DateTimeFormatter PURE_DATE_FORMATTER = DateTimeFormatter.ofPattern(PURE_DATE_PATTERN);
/**
* {@link DateTimeFormatter}yyyy-MM-dd
*/
public static final DateTimeFormatter NORM_DATE_FORMATTER = DateTimeFormatter.ofPattern(NORM_DATE_PATTERN);
/**
* HHmm
*/
public final static String TIME_PATTERN = "HHmm";
/**
* {@link DateTimeFormatter} HHmm
*/
public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(TIME_PATTERN);
/**
* HH:mm
*/
public final static String NORM_TIME_PATTERN = "HH:mm";
/**
* {@link DateTimeFormatter} HH:mm
*/
public static final DateTimeFormatter NORM_TIME_FORMATTER = DateTimeFormatter.ofPattern(NORM_TIME_PATTERN);
/**
* {@link DateTimeFormatter}yyyy-MM-dd HH:mm:ss
*/
public static final DateTimeFormatter NORM_DATETIME_FORMATTER = DateTimeFormatter.ofPattern(NORM_DATETIME_PATTERN);
/**
*
*/
public static final String CTT = ZoneId.SHORT_IDS.get("CTT");
/**
*
*/
public static final ZoneId CTT_ZONE_ID = ZoneId.of(CTT);
private DateTimeUtils() {
}
/**
*
*
* @return Now LocalDateTime
*/
public static LocalDateTime now() {
return now(CTT_ZONE_ID);
}
/**
*
*
* @param zoneId
* @return Now LocalDateTime
*/
public static LocalDateTime now(ZoneId zoneId) {
return LocalDateTime.now(zoneId);
}
/**
* yyyyMMdd
*
* @param localDateTime
* @return Result
*/
public static String formatDate(LocalDateTime localDateTime) {
return format(localDateTime, PURE_DATE_FORMATTER);
}
/**
* yyyyMMdd
*
* @param localDate
* @return Result
*/
public static String formatDate(LocalDate localDate) {
return format(localDate, PURE_DATE_FORMATTER);
}
/**
* HHmm
*
* @param localDateTime
* @return Result
*/
public static String formatTime(LocalDateTime localDateTime) {
return format(localDateTime, TIME_FORMATTER);
}
/**
* HHmm
*
* @param localTime
* @return Result
*/
public static String formatTime(LocalTime localTime) {
return format(localTime, TIME_FORMATTER);
}
/**
* yyyy-MM-dd HH:mm:ss
*
* @param localDateTime
* @return Result
*/
public static String formatDateTime(LocalDateTime localDateTime) {
return format(localDateTime, NORM_DATETIME_FORMATTER);
}
/**
*
*
* @param localDateTime
* @param formatter
* @return Result
*/
public static String format(LocalDateTime localDateTime, DateTimeFormatter formatter) {
return localDateTime.format(formatter);
}
/**
*
*
* @param localTime
* @param formatter
* @return Result
*/
public static String format(LocalTime localTime, DateTimeFormatter formatter) {
return localTime.format(formatter);
}
/**
*
*
* @param localDate
* @param formatter
* @return Result
*/
public static String format(LocalDate localDate, DateTimeFormatter formatter) {
return localDate.format(formatter);
}
/**
*
* <p>
* yyyyMMddHHmmssSSS
*
* @param time
* @return LocalDateTime
*/
public static LocalDateTime parseCttDateTime(String time) {
return parse(time, PURE_DATETIME_MS_FORMATTER);
}
/**
*
*
* @param formatter
* @param time
* @return LocalDateTime
*/
public static LocalDateTime parse(String time, DateTimeFormatter formatter) {
return LocalDateTime.parse(time, formatter);
}
/**
* to instant by default zoneId(Shanghai)
*
* @param localDateTime
* @return Instant
*/
public static Instant toInstant(LocalDateTime localDateTime) {
return toInstant(localDateTime, CTT_ZONE_ID);
}
/**
* To instant by zoneId
*
* @param localDateTime
* @return Instant
*/
public static Instant toInstant(LocalDateTime localDateTime, ZoneId zoneId) {
return localDateTime.atZone(zoneId).toInstant();
}
/**
* localDateTime
*
* @param localDateTime
* @return
*/
public static long getEpochSecond(LocalDateTime localDateTime) {
return toInstant(localDateTime).getEpochSecond();
}
/**
* localDateTime
*
* @param localDateTime
* @return
*/
public static long toEpochMilli(LocalDateTime localDateTime) {
return toInstant(localDateTime).toEpochMilli();
}
/**
* 0
*
* @param localDateTime
* @return LocalDateTime
*/
public static LocalDateTime secondAndNanoSetZero(LocalDateTime localDateTime) {
return localDateTime.withSecond(0).withNano(0);
}
/**
*
*
* @param localDateTime
* @return LocalDateTime
*/
public static LocalDateTime plusOneDayToDateTime(LocalDateTime localDateTime) {
return plusDays(localDateTime, 1);
}
/**
*
*
* @param localDateTime
* @param localTime
* @return LocalDateTime
*/
public static LocalDateTime plusOneDay(LocalDateTime localDateTime, LocalTime localTime) {
return plusOneDay(localDateTime.toLocalDate(), localTime);
}
/**
*
*
* @param localDate
* @param localTime
* @return LocalDateTime
*/
public static LocalDateTime plusOneDay(LocalDate localDate, LocalTime localTime) {
final LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
return plusDays(localDateTime, 1);
}
/**
*
*
* @param localDateTime
* @return LocalDate
*/
public static LocalDate plusOneDayToDate(LocalDateTime localDateTime) {
return plusDays(localDateTime, 1).toLocalDate();
}
/**
* days
*
* @param localDateTime
* @param days
* @return days LocalDateTime
*/
public static LocalDateTime plusDays(LocalDateTime localDateTime, long days) {
return localDateTime.plusDays(days);
}
/**
*
*
* @param localDate
* @return LocalDate
*/
public static LocalDate plusOneDayToDate(LocalDate localDate) {
return plusDays(localDate, 1);
}
/**
* days
*
* @param localDate
* @param days
* @return days LocalDate
*/
public static LocalDate plusDays(LocalDate localDate, long days) {
return localDate.plusDays(days);
}
/**
* 1
*
* @param localDateTime
* @return LocalDateTime
*/
public static LocalDateTime plusOneMinute(LocalDateTime localDateTime, LocalTime localTime) {
return plusOneMinute(localDateTime.toLocalDate(), localTime);
}
/**
* 1
*
* @param localDate
* @param localTime
* @return LocalDateTime
*/
public static LocalDateTime plusOneMinute(LocalDate localDate, LocalTime localTime) {
final LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
return plusMinutes(localDateTime, 1);
}
/**
* 1
*
* @param localDateTime
* @return LocalDateTime
*/
public static LocalDateTime plusOneMinute(LocalDateTime localDateTime) {
return plusMinutes(localDateTime, 1);
}
/**
* 30
*
* @param localDateTime
* @return LocalDateTime
*/
public static LocalDateTime plusThirtyMinute(LocalDateTime localDateTime) {
return plusMinutes(localDateTime, 30);
}
/**
* 1
*
* @param localDateTime
* @return LocalTime
*/
public static LocalTime plusOneMinuteToTime(LocalDateTime localDateTime) {
return plusMinutes(localDateTime, 1).toLocalTime();
}
/**
* 1
*
* @param localTime
* @return LocalTime
*/
public static LocalTime plusOneMinute(LocalTime localTime) {
return plusMinutes(localTime, 1);
}
/**
* 30
*
* @param localTime
* @return LocalTime
*/
public static LocalTime plusThirtyMinute(LocalTime localTime) {
return plusMinutes(localTime, 30);
}
/**
* minutes
*
* @param localDateTime
* @param minutes
* @return LocalDateTime
*/
public static LocalDateTime plusMinutes(LocalDateTime localDateTime, long minutes) {
return localDateTime.plusMinutes(minutes);
}
/**
* minutes
*
* @param localTime
* @param minutes
* @return LocalTime
*/
public static LocalTime plusMinutes(LocalTime localTime, long minutes) {
return localTime.plusMinutes(minutes);
}
/**
* 1
*
* @param localDateTime
* @param localTime
* @return LocalTime
*/
public static LocalDateTime minusOneMinutes(LocalDateTime localDateTime, LocalTime localTime) {
return minusOneMinutes(localDateTime.toLocalDate(), localTime);
}
/**
* 1
*
* @param localDate
* @param localTime
* @return LocalTime
*/
public static LocalDateTime minusOneMinutes(LocalDate localDate, LocalTime localTime) {
final LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
return minusMinutes(localDateTime, 1);
}
/**
* 1
*
* @param localDateTime
* @return LocalTime
*/
public static LocalDateTime minusOneMinutes(LocalDateTime localDateTime) {
return minusMinutes(localDateTime, 1);
}
/**
* minutes
*
* @param localDateTime
* @param minutes
* @return LocalTime
*/
public static LocalDateTime minusMinutes(LocalDateTime localDateTime, long minutes) {
return localDateTime.minusMinutes(minutes);
}
/**
* minutes
*
* @param localTime
* @param minutes
* @return LocalTime
*/
public static LocalTime minusMinutes(LocalTime localTime, long minutes) {
return localTime.minusMinutes(minutes);
}
/**
*
*
* @param startInclusive Start
* @return boolean
*/
public static boolean isNoon(LocalDateTime startInclusive) {
LocalDateTime noonDateTime = LocalDateTime.of(startInclusive.toLocalDate(), LocalTime.NOON);
return Duration.between(startInclusive, noonDateTime).isZero();
}
/**
*
*
* @param startInclusive Start
* @return boolean
*/
public static boolean isNoon(LocalTime startInclusive) {
return Duration.between(startInclusive, LocalTime.NOON).isZero();
}
/**
* startInclusive endInclusive
*
* @param startInclusive Start
* @param endInclusive end
* @return boolean
*/
public static boolean isNegative(Temporal startInclusive, Temporal endInclusive) {
return Duration.between(startInclusive, endInclusive).isNegative();
}
/**
* 00
*
* @param startInclusive Start
* @param endInclusive end
* @return boolean
*/
public static boolean isZero(Temporal startInclusive, Temporal endInclusive) {
return Duration.between(startInclusive, endInclusive).isZero();
}
/**
* endInclusive startInclusive
*
* @param startInclusive Start
* @param endInclusive end
* @return boolean
*/
public static boolean isGreaterOrEqual(Temporal startInclusive, Temporal endInclusive) {
return Duration.between(startInclusive, endInclusive).toNanos() >= 0;
}
/**
* endInclusive startInclusive
*
* @param startInclusive Start
* @param endInclusive end
* @return boolean
*/
public static boolean isGreater(Temporal startInclusive, Temporal endInclusive) {
return Duration.between(startInclusive, endInclusive).toNanos() > 0;
}
/**
* endInclusive startInclusive
*
* @param startInclusive Start
* @param endInclusive end
* @return boolean
*/
public static boolean isLessThanOrEqual(Temporal startInclusive, Temporal endInclusive) {
return Duration.between(startInclusive, endInclusive).toNanos() <= 0;
}
}

File diff suppressed because one or more lines are too long

View File

@ -37,7 +37,7 @@ spring:
multipart:
max-file-size: 10240MB
max-request-size: 10240MB
location: ${java.io.tmpdir}
location: \${java.io.tmpdir}
management:
endpoints:
web:
@ -48,7 +48,10 @@ logging:
level:
run.halo.app: INFO
file:
path: ${user.home}/.halo/logs
path: \${user.home}/.halo/logs
halo:
download-timeout: 5m
download-timeout: 5m
application:
version: ${version}

View File

@ -0,0 +1,156 @@
package run.halo.app.utils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
import java.time.*;
import java.time.format.DateTimeFormatter;
/**
* DateTimeUtils
*
* @author LeiXinXin
* @date 2020/1/9
*/
@RunWith(SpringRunner.class)
public class DateTimeUtilsTest {
/**
*
*/
@Test
public void nowTest() {
final LocalDateTime now = DateTimeUtils.now().withNano(0);
Assert.assertNotNull(now);
final LocalDateTime ctt = DateTimeUtils.now(ZoneId.of(ZoneId.SHORT_IDS.get("CTT"))).withNano(0);
Assert.assertNotNull(ctt);
Assert.assertEquals(Duration.between(now, ctt).toMinutes(), 0);
}
/**
*
*/
@Test
public void formatTest() {
final LocalDateTime now = LocalDateTime.of(2020, 1, 9, 20, 20, 20);
final String formatDate = DateTimeUtils.formatDate(now);
Assert.assertEquals(formatDate, "20200109");
final LocalDate localDate = LocalDate.of(2020, 1, 9);
final String localFormatDate = DateTimeUtils.formatDate(localDate);
Assert.assertEquals(localFormatDate, "20200109");
final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
final String formatDateTime1 = DateTimeUtils.format(now, dateTimeFormatter);
Assert.assertEquals(formatDateTime1, "2020/01/09");
final LocalTime time1 = LocalTime.of(10, 20);
final String formatTime = DateTimeUtils.formatTime(time1);
Assert.assertEquals(formatTime, "1020");
final String formatTime1 = DateTimeUtils.format(time1, DateTimeFormatter.ofPattern("HH:mm"));
Assert.assertEquals(formatTime1, "10:20");
}
/**
*
*/
@Test
public void plusTest() {
final LocalDateTime now = LocalDateTime.of(2020, 1, 9, 10, 20);
final LocalDateTime localDateTime = DateTimeUtils.plusOneMinute(now);
Assert.assertEquals(localDateTime.toString(), "2020-01-09T10:21");
LocalTime localTime = LocalTime.of(7, 30);
final LocalDateTime localDateTime1 = DateTimeUtils.plusOneMinute(now, localTime);
Assert.assertEquals(localDateTime1.toString(), "2020-01-09T07:31");
final LocalDate date = LocalDate.of(2020, 1, 3);
final LocalDateTime localDateTime2 = DateTimeUtils.plusOneMinute(date, localTime);
Assert.assertEquals(localDateTime2.toString(), "2020-01-03T07:31");
final LocalTime localTime1 = DateTimeUtils.plusOneMinute(localTime);
Assert.assertEquals(localTime1.toString(), "07:31");
final LocalDateTime localDateTime3 = DateTimeUtils.plusDays(now, 10);
Assert.assertEquals(localDateTime3.toString(), "2020-01-19T10:20");
}
/**
* LocalDateTime
*/
@Test
public void parseTest() {
String time = "20200109135500000";
final LocalDateTime localDateTime = DateTimeUtils.parseCttDateTime(time);
Assert.assertEquals(localDateTime.toString(), "2020-01-09T13:55");
String time2 = "2020/1/9 13:56";
final LocalDateTime dateTime = DateTimeUtils.parse(time2, DateTimeFormatter.ofPattern("yyyy/M/d HH:mm"));
Assert.assertEquals(dateTime.toString(), "2020-01-09T13:56");
}
/**
*
*/
@Test
public void minusTest() {
final LocalDateTime now = LocalDateTime.of(2020, 1, 3, 14, 20);
final LocalDateTime localDateTime = DateTimeUtils.minusOneMinutes(now);
Assert.assertEquals(localDateTime.toString(), "2020-01-03T14:19");
}
/**
* Instant
*/
@Test
public void toInstantTest() {
final LocalDateTime now = LocalDateTime.of(2020, 1, 3, 14, 20);
final Instant instant = DateTimeUtils.toInstant(now);
Assert.assertEquals(instant.toString(), "2020-01-03T06:20:00Z");
final Instant jst = DateTimeUtils.toInstant(now, ZoneId.of(ZoneId.SHORT_IDS.get("JST")));
Assert.assertEquals(jst.toString(), "2020-01-03T05:20:00Z");
}
/**
* 使
*/
@Test
public void other() {
LocalDateTime startInclusive = LocalDateTime.of(2020, 1, 3, 10, 10, 30);
LocalDateTime endInclusive = LocalDateTime.of(2020, 1, 4, 10, 10, 30);
// End 大于等于 Start
final boolean greaterOrEqual = DateTimeUtils.isGreaterOrEqual(startInclusive, endInclusive);
Assert.assertTrue(greaterOrEqual);
/*
*
*/
final boolean lessThanOrEqual = DateTimeUtils.isLessThanOrEqual(startInclusive, endInclusive);
Assert.assertFalse(lessThanOrEqual);
/*
* 0
*/
final boolean zero = DateTimeUtils.isZero(startInclusive, endInclusive);
Assert.assertFalse(zero);
// 是否是负数startInclusive 大于 endInclusive 就是负数
final boolean negative = DateTimeUtils.isNegative(startInclusive, endInclusive);
Assert.assertFalse(negative);
// 是否是中午
final boolean noon = DateTimeUtils.isNoon(LocalTime.of(12, 0));
Assert.assertTrue(noon);
// 把纳秒和秒设置为0
final LocalDateTime localDateTime = LocalDateTime.of(2020, 1, 5, 6, 40, 30, 999);
final LocalDateTime time = DateTimeUtils.secondAndNanoSetZero(localDateTime);
Assert.assertEquals(time.toString(), "2020-01-05T06:40");
}
}