Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ma yanling
hutool-5-master
Commits
45cda665
Commit
45cda665
authored
Sep 25, 2024
by
ma yanling
Browse files
project commit
parent
ad2fb30a
Pipeline
#2354
failed with stages
in 0 seconds
Changes
369
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
2699 additions
and
0 deletions
+2699
-0
hutool-core/src/main/java/cn/hutool/core/convert/impl/PairConverter.java
.../main/java/cn/hutool/core/convert/impl/PairConverter.java
+115
-0
hutool-core/src/main/java/cn/hutool/core/convert/impl/PathConverter.java
.../main/java/cn/hutool/core/convert/impl/PathConverter.java
+41
-0
hutool-core/src/main/java/cn/hutool/core/convert/impl/PeriodConverter.java
...ain/java/cn/hutool/core/convert/impl/PeriodConverter.java
+29
-0
hutool-core/src/main/java/cn/hutool/core/convert/impl/PrimitiveConverter.java
.../java/cn/hutool/core/convert/impl/PrimitiveConverter.java
+92
-0
hutool-core/src/main/java/cn/hutool/core/convert/impl/ReferenceConverter.java
.../java/cn/hutool/core/convert/impl/ReferenceConverter.java
+56
-0
hutool-core/src/main/java/cn/hutool/core/convert/impl/StackTraceElementConverter.java
.../hutool/core/convert/impl/StackTraceElementConverter.java
+34
-0
hutool-core/src/main/java/cn/hutool/core/convert/impl/StringConverter.java
...ain/java/cn/hutool/core/convert/impl/StringConverter.java
+80
-0
hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java
...n/hutool/core/convert/impl/TemporalAccessorConverter.java
+308
-0
hutool-core/src/main/java/cn/hutool/core/convert/impl/TimeZoneConverter.java
...n/java/cn/hutool/core/convert/impl/TimeZoneConverter.java
+20
-0
hutool-core/src/main/java/cn/hutool/core/convert/impl/URIConverter.java
...c/main/java/cn/hutool/core/convert/impl/URIConverter.java
+34
-0
hutool-core/src/main/java/cn/hutool/core/convert/impl/URLConverter.java
...c/main/java/cn/hutool/core/convert/impl/URLConverter.java
+34
-0
hutool-core/src/main/java/cn/hutool/core/convert/impl/UUIDConverter.java
.../main/java/cn/hutool/core/convert/impl/UUIDConverter.java
+22
-0
hutool-core/src/main/java/cn/hutool/core/convert/impl/package-info.java
...c/main/java/cn/hutool/core/convert/impl/package-info.java
+7
-0
hutool-core/src/main/java/cn/hutool/core/convert/package-info.java
...re/src/main/java/cn/hutool/core/convert/package-info.java
+7
-0
hutool-core/src/main/java/cn/hutool/core/date/BetweenFormatter.java
...e/src/main/java/cn/hutool/core/date/BetweenFormatter.java
+208
-0
hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java
...-core/src/main/java/cn/hutool/core/date/CalendarUtil.java
+775
-0
hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java
...l-core/src/main/java/cn/hutool/core/date/ChineseDate.java
+462
-0
hutool-core/src/main/java/cn/hutool/core/date/DateBetween.java
...l-core/src/main/java/cn/hutool/core/date/DateBetween.java
+185
-0
hutool-core/src/main/java/cn/hutool/core/date/DateException.java
...core/src/main/java/cn/hutool/core/date/DateException.java
+32
-0
hutool-core/src/main/java/cn/hutool/core/date/DateField.java
hutool-core/src/main/java/cn/hutool/core/date/DateField.java
+158
-0
No files found.
Too many changes to show.
To preserve performance only
369 of 369+
files are displayed.
Plain diff
Email patch
hutool-core/src/main/java/cn/hutool/core/convert/impl/PairConverter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.convert.impl
;
import
cn.hutool.core.bean.BeanUtil
;
import
cn.hutool.core.convert.AbstractConverter
;
import
cn.hutool.core.convert.ConvertException
;
import
cn.hutool.core.convert.ConverterRegistry
;
import
cn.hutool.core.lang.Pair
;
import
cn.hutool.core.map.MapUtil
;
import
cn.hutool.core.util.ReflectUtil
;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.core.util.TypeUtil
;
import
java.lang.reflect.Type
;
import
java.util.Map
;
public
class
PairConverter
extends
AbstractConverter
<
Pair
<?,
?>>
{
/** Pair类型 */
private
final
Type
pairType
;
/** 键类型 */
private
final
Type
keyType
;
/** 值类型 */
private
final
Type
valueType
;
/**
* 构造,Pair的key和value泛型类型自动获取
*
* @param pairType Map类型
*/
public
PairConverter
(
Type
pairType
)
{
this
(
pairType
,
null
,
null
);
}
/**
* 构造
*
* @param pairType Pair类型
* @param keyType 键类型
* @param valueType 值类型
*/
public
PairConverter
(
Type
pairType
,
Type
keyType
,
Type
valueType
)
{
this
.
pairType
=
pairType
;
this
.
keyType
=
keyType
;
this
.
valueType
=
valueType
;
}
@SuppressWarnings
(
"rawtypes"
)
@Override
protected
Pair
<?,
?>
convertInternal
(
Object
value
)
{
Map
map
=
null
;
if
(
value
instanceof
Map
.
Entry
)
{
final
Map
.
Entry
entry
=
(
Map
.
Entry
)
value
;
map
=
MapUtil
.
of
(
entry
.
getKey
(),
entry
.
getValue
());
}
else
if
(
value
instanceof
Map
)
{
map
=
(
Map
)
value
;
}
else
if
(
value
instanceof
CharSequence
)
{
final
CharSequence
str
=
(
CharSequence
)
value
;
map
=
strToMap
(
str
);
}
else
if
(
BeanUtil
.
isReadableBean
(
value
.
getClass
()))
{
map
=
BeanUtil
.
beanToMap
(
value
);
}
if
(
null
!=
map
)
{
return
mapToPair
(
pairType
,
keyType
,
valueType
,
map
);
}
throw
new
ConvertException
(
"Unsupported to map from [{}] of type: {}"
,
value
,
value
.
getClass
().
getName
());
}
/**
* 字符串转单个键值对的Map,支持分隔符{@code :}、{@code =}、{@code ,}
*
* @param str 字符串
* @return map or null
*/
private
static
Map
<
CharSequence
,
CharSequence
>
strToMap
(
final
CharSequence
str
)
{
// key:value key=value key,value
final
int
index
=
StrUtil
.
indexOf
(
str
,
'='
,
0
,
str
.
length
());
if
(
index
>
-
1
)
{
return
MapUtil
.
of
(
str
.
subSequence
(
0
,
index
+
1
),
str
.
subSequence
(
index
,
str
.
length
()));
}
return
null
;
}
/**
* Map转Entry
*
* @param targetType 目标的Map类型
* @param keyType 键类型
* @param valueType 值类型
* @param map 被转换的map
* @return Entry
*/
@SuppressWarnings
(
"rawtypes"
)
private
static
Pair
<?,
?>
mapToPair
(
final
Type
targetType
,
final
Type
keyType
,
final
Type
valueType
,
final
Map
map
)
{
Object
key
=
null
;
Object
value
=
null
;
if
(
1
==
map
.
size
())
{
final
Map
.
Entry
entry
=
(
Map
.
Entry
)
map
.
entrySet
().
iterator
().
next
();
key
=
entry
.
getKey
();
value
=
entry
.
getValue
();
}
else
if
(
2
==
map
.
size
())
{
key
=
map
.
get
(
"key"
);
value
=
map
.
get
(
"value"
);
}
final
ConverterRegistry
convert
=
ConverterRegistry
.
getInstance
();
return
(
Pair
<?,
?>)
ReflectUtil
.
newInstance
(
TypeUtil
.
getClass
(
targetType
),
TypeUtil
.
isUnknown
(
keyType
)
?
key
:
convert
.
convert
(
keyType
,
key
),
TypeUtil
.
isUnknown
(
valueType
)
?
value
:
convert
.
convert
(
valueType
,
value
)
);
}
}
hutool-core/src/main/java/cn/hutool/core/convert/impl/PathConverter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.convert.impl
;
import
java.io.File
;
import
java.net.URI
;
import
java.net.URL
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
cn.hutool.core.convert.AbstractConverter
;
/**
* 字符串转换器
* @author Looly
*
*/
public
class
PathConverter
extends
AbstractConverter
<
Path
>{
private
static
final
long
serialVersionUID
=
1L
;
@Override
protected
Path
convertInternal
(
Object
value
)
{
try
{
if
(
value
instanceof
URI
){
return
Paths
.
get
((
URI
)
value
);
}
if
(
value
instanceof
URL
){
return
Paths
.
get
(((
URL
)
value
).
toURI
());
}
if
(
value
instanceof
File
){
return
((
File
)
value
).
toPath
();
}
return
Paths
.
get
(
convertToStr
(
value
));
}
catch
(
Exception
e
)
{
// Ignore Exception
}
return
null
;
}
}
hutool-core/src/main/java/cn/hutool/core/convert/impl/PeriodConverter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.convert.impl
;
import
cn.hutool.core.convert.AbstractConverter
;
import
java.time.Period
;
import
java.time.temporal.TemporalAmount
;
/**
*
* {@link Period}对象转换器
*
* @author Looly
* @since 5.0.0
*/
public
class
PeriodConverter
extends
AbstractConverter
<
Period
>
{
private
static
final
long
serialVersionUID
=
1L
;
@Override
protected
Period
convertInternal
(
Object
value
)
{
if
(
value
instanceof
TemporalAmount
){
return
Period
.
from
((
TemporalAmount
)
value
);
}
else
if
(
value
instanceof
Integer
){
return
Period
.
ofDays
((
Integer
)
value
);
}
else
{
return
Period
.
parse
(
convertToStr
(
value
));
}
}
}
hutool-core/src/main/java/cn/hutool/core/convert/impl/PrimitiveConverter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.convert.impl
;
import
cn.hutool.core.convert.AbstractConverter
;
import
cn.hutool.core.convert.Convert
;
import
cn.hutool.core.convert.ConvertException
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.StrUtil
;
import
java.util.function.Function
;
/**
* 原始类型转换器<br>
* 支持类型为:<br>
* <ul>
* <li>{@code byte}</li>
* <li>{@code short}</li>
* <li>{@code int}</li>
* <li>{@code long}</li>
* <li>{@code float}</li>
* <li>{@code double}</li>
* <li>{@code char}</li>
* <li>{@code boolean}</li>
* </ul>
*
* @author Looly
*/
public
class
PrimitiveConverter
extends
AbstractConverter
<
Object
>
{
private
static
final
long
serialVersionUID
=
1L
;
private
final
Class
<?>
targetType
;
/**
* 构造<br>
*
* @param clazz 需要转换的原始
* @throws IllegalArgumentException 传入的转换类型非原始类型时抛出
*/
public
PrimitiveConverter
(
Class
<?>
clazz
)
{
if
(
null
==
clazz
)
{
throw
new
NullPointerException
(
"PrimitiveConverter not allow null target type!"
);
}
else
if
(
false
==
clazz
.
isPrimitive
())
{
throw
new
IllegalArgumentException
(
"["
+
clazz
+
"] is not a primitive class!"
);
}
this
.
targetType
=
clazz
;
}
@Override
protected
Object
convertInternal
(
Object
value
)
{
return
PrimitiveConverter
.
convert
(
value
,
this
.
targetType
,
this
::
convertToStr
);
}
@Override
protected
String
convertToStr
(
Object
value
)
{
return
StrUtil
.
trim
(
super
.
convertToStr
(
value
));
}
@Override
@SuppressWarnings
(
"unchecked"
)
public
Class
<
Object
>
getTargetType
()
{
return
(
Class
<
Object
>)
this
.
targetType
;
}
/**
* 将指定值转换为原始类型的值
* @param value 值
* @param primitiveClass 原始类型
* @param toStringFunc 当无法直接转换时,转为字符串后再转换的函数
* @return 转换结果
* @since 5.5.0
*/
protected
static
Object
convert
(
Object
value
,
Class
<?>
primitiveClass
,
Function
<
Object
,
String
>
toStringFunc
)
{
if
(
byte
.
class
==
primitiveClass
)
{
return
ObjectUtil
.
defaultIfNull
(
NumberConverter
.
convert
(
value
,
Byte
.
class
,
toStringFunc
),
0
);
}
else
if
(
short
.
class
==
primitiveClass
)
{
return
ObjectUtil
.
defaultIfNull
(
NumberConverter
.
convert
(
value
,
Short
.
class
,
toStringFunc
),
0
);
}
else
if
(
int
.
class
==
primitiveClass
)
{
return
ObjectUtil
.
defaultIfNull
(
NumberConverter
.
convert
(
value
,
Integer
.
class
,
toStringFunc
),
0
);
}
else
if
(
long
.
class
==
primitiveClass
)
{
return
ObjectUtil
.
defaultIfNull
(
NumberConverter
.
convert
(
value
,
Long
.
class
,
toStringFunc
),
0
);
}
else
if
(
float
.
class
==
primitiveClass
)
{
return
ObjectUtil
.
defaultIfNull
(
NumberConverter
.
convert
(
value
,
Float
.
class
,
toStringFunc
),
0
);
}
else
if
(
double
.
class
==
primitiveClass
)
{
return
ObjectUtil
.
defaultIfNull
(
NumberConverter
.
convert
(
value
,
Double
.
class
,
toStringFunc
),
0
);
}
else
if
(
char
.
class
==
primitiveClass
)
{
return
Convert
.
convert
(
Character
.
class
,
value
);
}
else
if
(
boolean
.
class
==
primitiveClass
)
{
return
Convert
.
convert
(
Boolean
.
class
,
value
);
}
throw
new
ConvertException
(
"Unsupported target type: {}"
,
primitiveClass
);
}
}
hutool-core/src/main/java/cn/hutool/core/convert/impl/ReferenceConverter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.convert.impl
;
import
cn.hutool.core.convert.AbstractConverter
;
import
cn.hutool.core.convert.ConverterRegistry
;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.core.util.TypeUtil
;
import
java.lang.ref.Reference
;
import
java.lang.ref.SoftReference
;
import
java.lang.ref.WeakReference
;
import
java.lang.reflect.Type
;
/**
* {@link Reference}转换器
*
* @author Looly
* @since 3.0.8
*/
@SuppressWarnings
(
"rawtypes"
)
public
class
ReferenceConverter
extends
AbstractConverter
<
Reference
>
{
private
static
final
long
serialVersionUID
=
1L
;
private
final
Class
<?
extends
Reference
>
targetType
;
/**
* 构造
* @param targetType {@link Reference}实现类型
*/
public
ReferenceConverter
(
Class
<?
extends
Reference
>
targetType
)
{
this
.
targetType
=
targetType
;
}
@SuppressWarnings
(
"unchecked"
)
@Override
protected
Reference
<?>
convertInternal
(
Object
value
)
{
//尝试将值转换为Reference泛型的类型
Object
targetValue
=
null
;
final
Type
paramType
=
TypeUtil
.
getTypeArgument
(
targetType
);
if
(
false
==
TypeUtil
.
isUnknown
(
paramType
)){
targetValue
=
ConverterRegistry
.
getInstance
().
convert
(
paramType
,
value
);
}
if
(
null
==
targetValue
){
targetValue
=
value
;
}
if
(
this
.
targetType
==
WeakReference
.
class
){
return
new
WeakReference
(
targetValue
);
}
else
if
(
this
.
targetType
==
SoftReference
.
class
){
return
new
SoftReference
(
targetValue
);
}
throw
new
UnsupportedOperationException
(
StrUtil
.
format
(
"Unsupport Reference type: {}"
,
this
.
targetType
.
getName
()));
}
}
hutool-core/src/main/java/cn/hutool/core/convert/impl/StackTraceElementConverter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.convert.impl
;
import
java.util.Map
;
import
cn.hutool.core.convert.AbstractConverter
;
import
cn.hutool.core.map.MapUtil
;
import
cn.hutool.core.util.ObjectUtil
;
/**
* {@link StackTraceElement} 转换器<br>
* 只支持Map方式转换
*
* @author Looly
* @since 3.0.8
*/
public
class
StackTraceElementConverter
extends
AbstractConverter
<
StackTraceElement
>
{
private
static
final
long
serialVersionUID
=
1L
;
@Override
protected
StackTraceElement
convertInternal
(
Object
value
)
{
if
(
value
instanceof
Map
)
{
final
Map
<?,
?>
map
=
(
Map
<?,
?>)
value
;
final
String
declaringClass
=
MapUtil
.
getStr
(
map
,
"className"
);
final
String
methodName
=
MapUtil
.
getStr
(
map
,
"methodName"
);
final
String
fileName
=
MapUtil
.
getStr
(
map
,
"fileName"
);
final
Integer
lineNumber
=
MapUtil
.
getInt
(
map
,
"lineNumber"
);
return
new
StackTraceElement
(
declaringClass
,
methodName
,
fileName
,
ObjectUtil
.
defaultIfNull
(
lineNumber
,
0
));
}
return
null
;
}
}
hutool-core/src/main/java/cn/hutool/core/convert/impl/StringConverter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.convert.impl
;
import
cn.hutool.core.convert.AbstractConverter
;
import
cn.hutool.core.convert.ConvertException
;
import
cn.hutool.core.io.IoUtil
;
import
cn.hutool.core.util.CharsetUtil
;
import
cn.hutool.core.util.XmlUtil
;
import
java.io.InputStream
;
import
java.io.Reader
;
import
java.lang.reflect.Type
;
import
java.sql.Blob
;
import
java.sql.Clob
;
import
java.sql.SQLException
;
import
java.util.TimeZone
;
/**
* 字符串转换器,提供各种对象转换为字符串的逻辑封装
*
* @author Looly
*/
public
class
StringConverter
extends
AbstractConverter
<
String
>
{
private
static
final
long
serialVersionUID
=
1L
;
@Override
protected
String
convertInternal
(
Object
value
)
{
if
(
value
instanceof
TimeZone
)
{
return
((
TimeZone
)
value
).
getID
();
}
else
if
(
value
instanceof
org
.
w3c
.
dom
.
Node
)
{
return
XmlUtil
.
toStr
((
org
.
w3c
.
dom
.
Node
)
value
);
}
else
if
(
value
instanceof
Clob
)
{
return
clobToStr
((
Clob
)
value
);
}
else
if
(
value
instanceof
Blob
)
{
return
blobToStr
((
Blob
)
value
);
}
else
if
(
value
instanceof
Type
)
{
return
((
Type
)
value
).
getTypeName
();
}
// 其它情况
return
convertToStr
(
value
);
}
/**
* Clob字段值转字符串
*
* @param clob {@link Clob}
* @return 字符串
* @since 5.4.5
*/
private
static
String
clobToStr
(
Clob
clob
)
{
Reader
reader
=
null
;
try
{
reader
=
clob
.
getCharacterStream
();
return
IoUtil
.
read
(
reader
);
}
catch
(
SQLException
e
)
{
throw
new
ConvertException
(
e
);
}
finally
{
IoUtil
.
close
(
reader
);
}
}
/**
* Blob字段值转字符串
*
* @param blob {@link Blob}
* @return 字符串
* @since 5.4.5
*/
private
static
String
blobToStr
(
Blob
blob
)
{
InputStream
in
=
null
;
try
{
in
=
blob
.
getBinaryStream
();
return
IoUtil
.
read
(
in
,
CharsetUtil
.
CHARSET_UTF_8
);
}
catch
(
SQLException
e
)
{
throw
new
ConvertException
(
e
);
}
finally
{
IoUtil
.
close
(
in
);
}
}
}
hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.convert.impl
;
import
cn.hutool.core.convert.AbstractConverter
;
import
cn.hutool.core.convert.Convert
;
import
cn.hutool.core.convert.ConvertException
;
import
cn.hutool.core.date.DateTime
;
import
cn.hutool.core.date.DateUtil
;
import
cn.hutool.core.date.format.GlobalCustomFormat
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.StrUtil
;
import
java.time.DayOfWeek
;
import
java.time.Instant
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
java.time.LocalTime
;
import
java.time.Month
;
import
java.time.MonthDay
;
import
java.time.OffsetDateTime
;
import
java.time.OffsetTime
;
import
java.time.ZoneId
;
import
java.time.ZonedDateTime
;
import
java.time.chrono.Era
;
import
java.time.chrono.IsoEra
;
import
java.time.format.DateTimeFormatter
;
import
java.time.temporal.TemporalAccessor
;
import
java.util.Calendar
;
import
java.util.Date
;
import
java.util.Map
;
import
java.util.Objects
;
/**
* JDK8中新加入的java.time包对象解析转换器<br>
* 支持的对象包括:
*
* <pre>
* java.time.Instant
* java.time.LocalDateTime
* java.time.LocalDate
* java.time.LocalTime
* java.time.ZonedDateTime
* java.time.OffsetDateTime
* java.time.OffsetTime
* </pre>
*
* @author looly
* @since 5.0.0
*/
public
class
TemporalAccessorConverter
extends
AbstractConverter
<
TemporalAccessor
>
{
private
static
final
long
serialVersionUID
=
1L
;
private
final
Class
<?>
targetType
;
/**
* 日期格式化
*/
private
String
format
;
/**
* 构造
*
* @param targetType 目标类型
*/
public
TemporalAccessorConverter
(
Class
<?>
targetType
)
{
this
(
targetType
,
null
);
}
/**
* 构造
*
* @param targetType 目标类型
* @param format 日期格式
*/
public
TemporalAccessorConverter
(
Class
<?>
targetType
,
String
format
)
{
this
.
targetType
=
targetType
;
this
.
format
=
format
;
}
/**
* 获取日期格式
*
* @return 设置日期格式
*/
public
String
getFormat
()
{
return
format
;
}
/**
* 设置日期格式
*
* @param format 日期格式
*/
public
void
setFormat
(
String
format
)
{
this
.
format
=
format
;
}
@SuppressWarnings
(
"unchecked"
)
@Override
public
Class
<
TemporalAccessor
>
getTargetType
()
{
return
(
Class
<
TemporalAccessor
>)
this
.
targetType
;
}
@Override
protected
TemporalAccessor
convertInternal
(
Object
value
)
{
if
(
value
instanceof
Number
)
{
return
parseFromLong
(((
Number
)
value
).
longValue
());
}
else
if
(
value
instanceof
TemporalAccessor
)
{
return
parseFromTemporalAccessor
((
TemporalAccessor
)
value
);
}
else
if
(
value
instanceof
Date
)
{
final
DateTime
dateTime
=
DateUtil
.
date
((
Date
)
value
);
return
parseFromInstant
(
dateTime
.
toInstant
(),
dateTime
.
getZoneId
());
}
else
if
(
value
instanceof
Calendar
)
{
final
Calendar
calendar
=
(
Calendar
)
value
;
return
parseFromInstant
(
calendar
.
toInstant
(),
calendar
.
getTimeZone
().
toZoneId
());
}
else
if
(
value
instanceof
Map
)
{
final
Map
<?,
?>
map
=
(
Map
<?,
?>)
value
;
if
(
LocalDate
.
class
.
equals
(
this
.
targetType
))
{
return
LocalDate
.
of
(
Convert
.
toInt
(
map
.
get
(
"year"
)),
Convert
.
toInt
(
map
.
get
(
"month"
)),
Convert
.
toInt
(
map
.
get
(
"day"
)));
}
else
if
(
LocalDateTime
.
class
.
equals
(
this
.
targetType
))
{
return
LocalDateTime
.
of
(
Convert
.
toInt
(
map
.
get
(
"year"
)),
Convert
.
toInt
(
map
.
get
(
"month"
)),
Convert
.
toInt
(
map
.
get
(
"day"
)),
Convert
.
toInt
(
map
.
get
(
"hour"
)),
Convert
.
toInt
(
map
.
get
(
"minute"
)),
Convert
.
toInt
(
map
.
get
(
"second"
)),
Convert
.
toInt
(
map
.
get
(
"second"
)));
}
else
if
(
LocalTime
.
class
.
equals
(
this
.
targetType
))
{
return
LocalTime
.
of
(
Convert
.
toInt
(
map
.
get
(
"hour"
)),
Convert
.
toInt
(
map
.
get
(
"minute"
)),
Convert
.
toInt
(
map
.
get
(
"second"
)),
Convert
.
toInt
(
map
.
get
(
"nano"
)));
}
throw
new
ConvertException
(
"Unsupported type: [{}] from map: [{}]"
,
this
.
targetType
,
map
);
}
else
{
return
parseFromCharSequence
(
convertToStr
(
value
));
}
}
/**
* 通过反射从字符串转java.time中的对象
*
* @param value 字符串值
* @return 日期对象
*/
private
TemporalAccessor
parseFromCharSequence
(
CharSequence
value
)
{
if
(
StrUtil
.
isBlank
(
value
))
{
return
null
;
}
if
(
DayOfWeek
.
class
.
equals
(
this
.
targetType
)){
return
DayOfWeek
.
valueOf
(
StrUtil
.
toString
(
value
));
}
else
if
(
Month
.
class
.
equals
(
this
.
targetType
)){
return
Month
.
valueOf
(
StrUtil
.
toString
(
value
));
}
else
if
(
Era
.
class
.
equals
(
this
.
targetType
)){
return
IsoEra
.
valueOf
(
StrUtil
.
toString
(
value
));
}
else
if
(
MonthDay
.
class
.
equals
(
this
.
targetType
)){
return
MonthDay
.
parse
(
value
);
}
final
Instant
instant
;
ZoneId
zoneId
;
if
(
null
!=
this
.
format
)
{
final
DateTimeFormatter
formatter
=
DateTimeFormatter
.
ofPattern
(
this
.
format
);
instant
=
formatter
.
parse
(
value
,
Instant:
:
from
);
zoneId
=
formatter
.
getZone
();
}
else
{
final
DateTime
dateTime
=
DateUtil
.
parse
(
value
);
instant
=
Objects
.
requireNonNull
(
dateTime
).
toInstant
();
zoneId
=
dateTime
.
getZoneId
();
}
return
parseFromInstant
(
instant
,
zoneId
);
}
/**
* 将Long型时间戳转换为java.time中的对象
*
* @param time 时间戳
* @return java.time中的对象
*/
private
TemporalAccessor
parseFromLong
(
Long
time
)
{
if
(
DayOfWeek
.
class
.
equals
(
this
.
targetType
)){
return
DayOfWeek
.
of
(
Math
.
toIntExact
(
time
));
}
else
if
(
Month
.
class
.
equals
(
this
.
targetType
)){
return
Month
.
of
(
Math
.
toIntExact
(
time
));
}
else
if
(
Era
.
class
.
equals
(
this
.
targetType
)){
return
IsoEra
.
of
(
Math
.
toIntExact
(
time
));
}
final
Instant
instant
;
if
(
GlobalCustomFormat
.
FORMAT_SECONDS
.
equals
(
this
.
format
)){
// https://gitee.com/dromara/hutool/issues/I6IS5B
// Unix时间戳
instant
=
Instant
.
ofEpochSecond
(
time
);
}
else
{
instant
=
Instant
.
ofEpochMilli
(
time
);
}
return
parseFromInstant
(
instant
,
null
);
}
/**
* 将TemporalAccessor型时间戳转换为java.time中的对象
*
* @param temporalAccessor TemporalAccessor对象
* @return java.time中的对象
*/
private
TemporalAccessor
parseFromTemporalAccessor
(
TemporalAccessor
temporalAccessor
)
{
if
(
DayOfWeek
.
class
.
equals
(
this
.
targetType
)){
return
DayOfWeek
.
from
(
temporalAccessor
);
}
else
if
(
Month
.
class
.
equals
(
this
.
targetType
)){
return
Month
.
from
(
temporalAccessor
);
}
else
if
(
MonthDay
.
class
.
equals
(
this
.
targetType
)){
return
MonthDay
.
from
(
temporalAccessor
);
}
TemporalAccessor
result
=
null
;
if
(
temporalAccessor
instanceof
LocalDateTime
)
{
result
=
parseFromLocalDateTime
((
LocalDateTime
)
temporalAccessor
);
}
else
if
(
temporalAccessor
instanceof
ZonedDateTime
)
{
result
=
parseFromZonedDateTime
((
ZonedDateTime
)
temporalAccessor
);
}
if
(
null
==
result
)
{
result
=
parseFromInstant
(
DateUtil
.
toInstant
(
temporalAccessor
),
null
);
}
return
result
;
}
/**
* 将TemporalAccessor型时间戳转换为java.time中的对象
*
* @param localDateTime {@link LocalDateTime}对象
* @return java.time中的对象
*/
private
TemporalAccessor
parseFromLocalDateTime
(
LocalDateTime
localDateTime
)
{
if
(
Instant
.
class
.
equals
(
this
.
targetType
))
{
return
DateUtil
.
toInstant
(
localDateTime
);
}
if
(
LocalDate
.
class
.
equals
(
this
.
targetType
))
{
return
localDateTime
.
toLocalDate
();
}
if
(
LocalTime
.
class
.
equals
(
this
.
targetType
))
{
return
localDateTime
.
toLocalTime
();
}
if
(
ZonedDateTime
.
class
.
equals
(
this
.
targetType
))
{
return
localDateTime
.
atZone
(
ZoneId
.
systemDefault
());
}
if
(
OffsetDateTime
.
class
.
equals
(
this
.
targetType
))
{
return
localDateTime
.
atZone
(
ZoneId
.
systemDefault
()).
toOffsetDateTime
();
}
if
(
OffsetTime
.
class
.
equals
(
this
.
targetType
))
{
return
localDateTime
.
atZone
(
ZoneId
.
systemDefault
()).
toOffsetDateTime
().
toOffsetTime
();
}
return
null
;
}
/**
* 将TemporalAccessor型时间戳转换为java.time中的对象
*
* @param zonedDateTime {@link ZonedDateTime}对象
* @return java.time中的对象
*/
private
TemporalAccessor
parseFromZonedDateTime
(
ZonedDateTime
zonedDateTime
)
{
if
(
Instant
.
class
.
equals
(
this
.
targetType
))
{
return
DateUtil
.
toInstant
(
zonedDateTime
);
}
if
(
LocalDateTime
.
class
.
equals
(
this
.
targetType
))
{
return
zonedDateTime
.
toLocalDateTime
();
}
if
(
LocalDate
.
class
.
equals
(
this
.
targetType
))
{
return
zonedDateTime
.
toLocalDate
();
}
if
(
LocalTime
.
class
.
equals
(
this
.
targetType
))
{
return
zonedDateTime
.
toLocalTime
();
}
if
(
OffsetDateTime
.
class
.
equals
(
this
.
targetType
))
{
return
zonedDateTime
.
toOffsetDateTime
();
}
if
(
OffsetTime
.
class
.
equals
(
this
.
targetType
))
{
return
zonedDateTime
.
toOffsetDateTime
().
toOffsetTime
();
}
return
null
;
}
/**
* 将TemporalAccessor型时间戳转换为java.time中的对象
*
* @param instant {@link Instant}对象
* @param zoneId 时区ID,null表示当前系统默认的时区
* @return java.time中的对象
*/
private
TemporalAccessor
parseFromInstant
(
Instant
instant
,
ZoneId
zoneId
)
{
if
(
Instant
.
class
.
equals
(
this
.
targetType
))
{
return
instant
;
}
zoneId
=
ObjectUtil
.
defaultIfNull
(
zoneId
,
ZoneId:
:
systemDefault
);
TemporalAccessor
result
=
null
;
if
(
LocalDateTime
.
class
.
equals
(
this
.
targetType
))
{
result
=
LocalDateTime
.
ofInstant
(
instant
,
zoneId
);
}
else
if
(
LocalDate
.
class
.
equals
(
this
.
targetType
))
{
result
=
instant
.
atZone
(
zoneId
).
toLocalDate
();
}
else
if
(
LocalTime
.
class
.
equals
(
this
.
targetType
))
{
result
=
instant
.
atZone
(
zoneId
).
toLocalTime
();
}
else
if
(
ZonedDateTime
.
class
.
equals
(
this
.
targetType
))
{
result
=
instant
.
atZone
(
zoneId
);
}
else
if
(
OffsetDateTime
.
class
.
equals
(
this
.
targetType
))
{
result
=
OffsetDateTime
.
ofInstant
(
instant
,
zoneId
);
}
else
if
(
OffsetTime
.
class
.
equals
(
this
.
targetType
))
{
result
=
OffsetTime
.
ofInstant
(
instant
,
zoneId
);
}
return
result
;
}
}
hutool-core/src/main/java/cn/hutool/core/convert/impl/TimeZoneConverter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.convert.impl
;
import
java.util.TimeZone
;
import
cn.hutool.core.convert.AbstractConverter
;
/**
* TimeZone转换器
* @author Looly
*
*/
public
class
TimeZoneConverter
extends
AbstractConverter
<
TimeZone
>{
private
static
final
long
serialVersionUID
=
1L
;
@Override
protected
TimeZone
convertInternal
(
Object
value
)
{
return
TimeZone
.
getTimeZone
(
convertToStr
(
value
));
}
}
hutool-core/src/main/java/cn/hutool/core/convert/impl/URIConverter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.convert.impl
;
import
java.io.File
;
import
java.net.URI
;
import
java.net.URL
;
import
cn.hutool.core.convert.AbstractConverter
;
/**
* URI对象转换器
* @author Looly
*
*/
public
class
URIConverter
extends
AbstractConverter
<
URI
>{
private
static
final
long
serialVersionUID
=
1L
;
@Override
protected
URI
convertInternal
(
Object
value
)
{
try
{
if
(
value
instanceof
File
){
return
((
File
)
value
).
toURI
();
}
if
(
value
instanceof
URL
){
return
((
URL
)
value
).
toURI
();
}
return
new
URI
(
convertToStr
(
value
));
}
catch
(
Exception
e
)
{
// Ignore Exception
}
return
null
;
}
}
hutool-core/src/main/java/cn/hutool/core/convert/impl/URLConverter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.convert.impl
;
import
java.io.File
;
import
java.net.URI
;
import
java.net.URL
;
import
cn.hutool.core.convert.AbstractConverter
;
/**
* URL对象转换器
* @author Looly
*
*/
public
class
URLConverter
extends
AbstractConverter
<
URL
>{
private
static
final
long
serialVersionUID
=
1L
;
@Override
protected
URL
convertInternal
(
Object
value
)
{
try
{
if
(
value
instanceof
File
){
return
((
File
)
value
).
toURI
().
toURL
();
}
if
(
value
instanceof
URI
){
return
((
URI
)
value
).
toURL
();
}
return
new
URL
(
convertToStr
(
value
));
}
catch
(
Exception
e
)
{
// Ignore Exception
}
return
null
;
}
}
hutool-core/src/main/java/cn/hutool/core/convert/impl/UUIDConverter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.convert.impl
;
import
java.util.UUID
;
import
cn.hutool.core.convert.AbstractConverter
;
/**
* UUID对象转换器转换器
*
* @author Looly
* @since 4.0.10
*
*/
public
class
UUIDConverter
extends
AbstractConverter
<
UUID
>
{
private
static
final
long
serialVersionUID
=
1L
;
@Override
protected
UUID
convertInternal
(
Object
value
)
{
return
UUID
.
fromString
(
convertToStr
(
value
));
}
}
hutool-core/src/main/java/cn/hutool/core/convert/impl/package-info.java
0 → 100644
View file @
45cda665
/**
* 各种类型转换的实现类,其都为Converter接口的实现,用于将未知的Object类型转换为指定类型
*
* @author looly
*
*/
package
cn.hutool.core.convert.impl
;
\ No newline at end of file
hutool-core/src/main/java/cn/hutool/core/convert/package-info.java
0 → 100644
View file @
45cda665
/**
* 万能类型转换器以及各种类型转换的实现类,其中Convert为转换器入口,提供各种toXXX方法和convert方法
*
* @author looly
*
*/
package
cn.hutool.core.convert
;
\ No newline at end of file
hutool-core/src/main/java/cn/hutool/core/date/BetweenFormatter.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.date
;
import
cn.hutool.core.util.StrUtil
;
import
java.io.Serializable
;
/**
* 时长格式化器,用于格式化输出两个日期相差的时长<br>
* 根据{@link Level}不同,调用{@link #format()}方法后返回类似于:
* <ul>
* <li>XX小时XX分XX秒</li>
* <li>XX天XX小时</li>
* <li>XX月XX天XX小时</li>
* </ul>
*
* @author Looly
*/
public
class
BetweenFormatter
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 时长毫秒数
*/
private
long
betweenMs
;
/**
* 格式化级别
*/
private
Level
level
;
/**
* 格式化级别的最大个数
*/
private
final
int
levelMaxCount
;
/**
* 构造
*
* @param betweenMs 日期间隔
* @param level 级别,按照天、小时、分、秒、毫秒分为5个等级,根据传入等级,格式化到相应级别
*/
public
BetweenFormatter
(
long
betweenMs
,
Level
level
)
{
this
(
betweenMs
,
level
,
0
);
}
/**
* 构造
*
* @param betweenMs 日期间隔
* @param level 级别,按照天、小时、分、秒、毫秒分为5个等级,根据传入等级,格式化到相应级别
* @param levelMaxCount 格式化级别的最大个数,假如级别个数为1,但是级别到秒,那只显示一个级别
*/
public
BetweenFormatter
(
long
betweenMs
,
Level
level
,
int
levelMaxCount
)
{
this
.
betweenMs
=
betweenMs
;
this
.
level
=
level
;
this
.
levelMaxCount
=
levelMaxCount
;
}
/**
* 格式化日期间隔输出<br>
*
* @return 格式化后的字符串
*/
public
String
format
()
{
final
StringBuilder
sb
=
new
StringBuilder
();
if
(
betweenMs
>
0
)
{
long
day
=
betweenMs
/
DateUnit
.
DAY
.
getMillis
();
long
hour
=
betweenMs
/
DateUnit
.
HOUR
.
getMillis
()
-
day
*
24
;
long
minute
=
betweenMs
/
DateUnit
.
MINUTE
.
getMillis
()
-
day
*
24
*
60
-
hour
*
60
;
final
long
BetweenOfSecond
=
((
day
*
24
+
hour
)
*
60
+
minute
)
*
60
;
long
second
=
betweenMs
/
DateUnit
.
SECOND
.
getMillis
()
-
BetweenOfSecond
;
long
millisecond
=
betweenMs
-
(
BetweenOfSecond
+
second
)
*
1000
;
final
int
level
=
this
.
level
.
ordinal
();
int
levelCount
=
0
;
if
(
isLevelCountValid
(
levelCount
)
&&
0
!=
day
&&
level
>=
Level
.
DAY
.
ordinal
())
{
sb
.
append
(
day
).
append
(
Level
.
DAY
.
name
);
levelCount
++;
}
if
(
isLevelCountValid
(
levelCount
)
&&
0
!=
hour
&&
level
>=
Level
.
HOUR
.
ordinal
())
{
sb
.
append
(
hour
).
append
(
Level
.
HOUR
.
name
);
levelCount
++;
}
if
(
isLevelCountValid
(
levelCount
)
&&
0
!=
minute
&&
level
>=
Level
.
MINUTE
.
ordinal
())
{
sb
.
append
(
minute
).
append
(
Level
.
MINUTE
.
name
);
levelCount
++;
}
if
(
isLevelCountValid
(
levelCount
)
&&
0
!=
second
&&
level
>=
Level
.
SECOND
.
ordinal
())
{
sb
.
append
(
second
).
append
(
Level
.
SECOND
.
name
);
levelCount
++;
}
if
(
isLevelCountValid
(
levelCount
)
&&
0
!=
millisecond
&&
level
>=
Level
.
MILLISECOND
.
ordinal
())
{
sb
.
append
(
millisecond
).
append
(
Level
.
MILLISECOND
.
name
);
// levelCount++;
}
}
if
(
StrUtil
.
isEmpty
(
sb
))
{
sb
.
append
(
0
).
append
(
this
.
level
.
name
);
}
return
sb
.
toString
();
}
/**
* 获得 时长毫秒数
*
* @return 时长毫秒数
*/
public
long
getBetweenMs
()
{
return
betweenMs
;
}
/**
* 设置 时长毫秒数
*
* @param betweenMs 时长毫秒数
*/
public
void
setBetweenMs
(
long
betweenMs
)
{
this
.
betweenMs
=
betweenMs
;
}
/**
* 获得 格式化级别
*
* @return 格式化级别
*/
public
Level
getLevel
()
{
return
level
;
}
/**
* 设置格式化级别
*
* @param level 格式化级别
*/
public
void
setLevel
(
Level
level
)
{
this
.
level
=
level
;
}
/**
* 格式化等级枚举
*
* @author Looly
*/
public
enum
Level
{
/**
* 天
*/
DAY
(
"天"
),
/**
* 小时
*/
HOUR
(
"小时"
),
/**
* 分钟
*/
MINUTE
(
"分"
),
/**
* 秒
*/
SECOND
(
"秒"
),
/**
* 毫秒
*/
MILLISECOND
(
"毫秒"
);
/**
* 级别名称
*/
private
final
String
name
;
/**
* 构造
*
* @param name 级别名称
*/
Level
(
String
name
)
{
this
.
name
=
name
;
}
/**
* 获取级别名称
*
* @return 级别名称
*/
public
String
getName
()
{
return
this
.
name
;
}
}
@Override
public
String
toString
()
{
return
format
();
}
/**
* 等级数量是否有效<br>
* 有效的定义是:levelMaxCount大于0(被设置),当前等级数量没有超过这个最大值
*
* @param levelCount 登记数量
* @return 是否有效
*/
private
boolean
isLevelCountValid
(
int
levelCount
)
{
return
this
.
levelMaxCount
<=
0
||
levelCount
<
this
.
levelMaxCount
;
}
}
hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.date
;
import
cn.hutool.core.comparator.CompareUtil
;
import
cn.hutool.core.convert.NumberChineseFormatter
;
import
cn.hutool.core.date.format.DateParser
;
import
cn.hutool.core.date.format.FastDateParser
;
import
cn.hutool.core.date.format.GlobalCustomFormat
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.StrUtil
;
import
java.text.ParsePosition
;
import
java.time.Instant
;
import
java.time.LocalDateTime
;
import
java.util.Calendar
;
import
java.util.Date
;
import
java.util.LinkedHashSet
;
import
java.util.Locale
;
import
java.util.TimeZone
;
/**
* 针对{@link Calendar} 对象封装工具类
*
* @author looly
* @since 5.3.0
*/
public
class
CalendarUtil
{
/**
* 创建Calendar对象,时间为默认时区的当前时间
*
* @return Calendar对象
* @since 4.6.6
*/
public
static
Calendar
calendar
()
{
return
Calendar
.
getInstance
();
}
/**
* 转换为Calendar对象
*
* @param date 日期对象
* @return Calendar对象
*/
public
static
Calendar
calendar
(
Date
date
)
{
if
(
date
instanceof
DateTime
)
{
return
((
DateTime
)
date
).
toCalendar
();
}
else
{
return
calendar
(
date
.
getTime
());
}
}
/**
* 转换为Calendar对象,使用当前默认时区
*
* @param millis 时间戳
* @return Calendar对象
*/
public
static
Calendar
calendar
(
long
millis
)
{
return
calendar
(
millis
,
TimeZone
.
getDefault
());
}
/**
* 转换为Calendar对象
*
* @param millis 时间戳
* @param timeZone 时区
* @return Calendar对象
* @since 5.7.22
*/
public
static
Calendar
calendar
(
long
millis
,
TimeZone
timeZone
)
{
final
Calendar
cal
=
Calendar
.
getInstance
(
timeZone
);
cal
.
setTimeInMillis
(
millis
);
return
cal
;
}
/**
* 是否为上午
*
* @param calendar {@link Calendar}
* @return 是否为上午
*/
public
static
boolean
isAM
(
Calendar
calendar
)
{
return
Calendar
.
AM
==
calendar
.
get
(
Calendar
.
AM_PM
);
}
/**
* 是否为下午
*
* @param calendar {@link Calendar}
* @return 是否为下午
*/
public
static
boolean
isPM
(
Calendar
calendar
)
{
return
Calendar
.
PM
==
calendar
.
get
(
Calendar
.
AM_PM
);
}
/**
* 修改日期为某个时间字段起始时间
*
* @param calendar {@link Calendar}
* @param dateField 保留到的时间字段,如定义为 {@link DateField#SECOND},表示这个字段不变,这个字段以下字段全部归0
* @return 原{@link Calendar}
*/
public
static
Calendar
truncate
(
Calendar
calendar
,
DateField
dateField
)
{
return
DateModifier
.
modify
(
calendar
,
dateField
.
getValue
(),
DateModifier
.
ModifyType
.
TRUNCATE
);
}
/**
* 修改日期为某个时间字段四舍五入时间
*
* @param calendar {@link Calendar}
* @param dateField 时间字段
* @return 原{@link Calendar}
*/
public
static
Calendar
round
(
Calendar
calendar
,
DateField
dateField
)
{
return
DateModifier
.
modify
(
calendar
,
dateField
.
getValue
(),
DateModifier
.
ModifyType
.
ROUND
);
}
/**
* 修改日期为某个时间字段结束时间
*
* @param calendar {@link Calendar}
* @param dateField 保留到的时间字段,如定义为 {@link DateField#SECOND},表示这个字段不变,这个字段以下字段全部取最大值
* @return 原{@link Calendar}
*/
public
static
Calendar
ceiling
(
Calendar
calendar
,
DateField
dateField
)
{
return
DateModifier
.
modify
(
calendar
,
dateField
.
getValue
(),
DateModifier
.
ModifyType
.
CEILING
);
}
/**
* 修改日期为某个时间字段结束时间<br>
* 可选是否归零毫秒。
*
* <p>
* 有时候由于毫秒部分必须为0(如MySQL数据库中),因此在此加上选项。
* </p>
*
* @param calendar {@link Calendar}
* @param dateField 时间字段
* @param truncateMillisecond 是否毫秒归零
* @return 原{@link Calendar}
*/
public
static
Calendar
ceiling
(
Calendar
calendar
,
DateField
dateField
,
boolean
truncateMillisecond
)
{
return
DateModifier
.
modify
(
calendar
,
dateField
.
getValue
(),
DateModifier
.
ModifyType
.
CEILING
,
truncateMillisecond
);
}
/**
* 修改秒级别的开始时间,即忽略毫秒部分
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
* @since 4.6.2
*/
public
static
Calendar
beginOfSecond
(
Calendar
calendar
)
{
return
truncate
(
calendar
,
DateField
.
SECOND
);
}
/**
* 修改秒级别的结束时间,即毫秒设置为999
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
* @since 4.6.2
*/
public
static
Calendar
endOfSecond
(
Calendar
calendar
)
{
return
ceiling
(
calendar
,
DateField
.
SECOND
);
}
/**
* 修改某小时的开始时间
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
*/
public
static
Calendar
beginOfHour
(
Calendar
calendar
)
{
return
truncate
(
calendar
,
DateField
.
HOUR_OF_DAY
);
}
/**
* 修改某小时的结束时间
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
*/
public
static
Calendar
endOfHour
(
Calendar
calendar
)
{
return
ceiling
(
calendar
,
DateField
.
HOUR_OF_DAY
);
}
/**
* 修改某分钟的开始时间
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
*/
public
static
Calendar
beginOfMinute
(
Calendar
calendar
)
{
return
truncate
(
calendar
,
DateField
.
MINUTE
);
}
/**
* 修改某分钟的结束时间
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
*/
public
static
Calendar
endOfMinute
(
Calendar
calendar
)
{
return
ceiling
(
calendar
,
DateField
.
MINUTE
);
}
/**
* 修改某天的开始时间
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
*/
public
static
Calendar
beginOfDay
(
Calendar
calendar
)
{
return
truncate
(
calendar
,
DateField
.
DAY_OF_MONTH
);
}
/**
* 修改某天的结束时间
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
*/
public
static
Calendar
endOfDay
(
Calendar
calendar
)
{
return
ceiling
(
calendar
,
DateField
.
DAY_OF_MONTH
);
}
/**
* 修改给定日期当前周的开始时间,周一定为一周的开始时间
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
*/
public
static
Calendar
beginOfWeek
(
Calendar
calendar
)
{
return
beginOfWeek
(
calendar
,
true
);
}
/**
* 修改给定日期当前周的开始时间
*
* @param calendar 日期 {@link Calendar}
* @param isMondayAsFirstDay 是否周一做为一周的第一天(false表示周日做为第一天)
* @return {@link Calendar}
* @since 3.1.2
*/
public
static
Calendar
beginOfWeek
(
Calendar
calendar
,
boolean
isMondayAsFirstDay
)
{
calendar
.
setFirstDayOfWeek
(
isMondayAsFirstDay
?
Calendar
.
MONDAY
:
Calendar
.
SUNDAY
);
// WEEK_OF_MONTH为上限的字段(不包括),实际调整的为DAY_OF_MONTH
return
truncate
(
calendar
,
DateField
.
WEEK_OF_MONTH
);
}
/**
* 修改某周的结束时间,周日定为一周的结束
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
*/
public
static
Calendar
endOfWeek
(
Calendar
calendar
)
{
return
endOfWeek
(
calendar
,
true
);
}
/**
* 修改某周的结束时间
*
* @param calendar 日期 {@link Calendar}
* @param isSundayAsLastDay 是否周日做为一周的最后一天(false表示周六做为最后一天)
* @return {@link Calendar}
*/
public
static
Calendar
endOfWeek
(
Calendar
calendar
,
boolean
isSundayAsLastDay
)
{
calendar
.
setFirstDayOfWeek
(
isSundayAsLastDay
?
Calendar
.
MONDAY
:
Calendar
.
SUNDAY
);
// WEEK_OF_MONTH为上限的字段(不包括),实际调整的为DAY_OF_MONTH
return
ceiling
(
calendar
,
DateField
.
WEEK_OF_MONTH
);
}
/**
* 修改某月的开始时间
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
*/
public
static
Calendar
beginOfMonth
(
Calendar
calendar
)
{
return
truncate
(
calendar
,
DateField
.
MONTH
);
}
/**
* 修改某月的结束时间
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
*/
public
static
Calendar
endOfMonth
(
Calendar
calendar
)
{
return
ceiling
(
calendar
,
DateField
.
MONTH
);
}
/**
* 修改某季度的开始时间
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
* @since 4.1.0
*/
public
static
Calendar
beginOfQuarter
(
Calendar
calendar
)
{
//noinspection MagicConstant
calendar
.
set
(
Calendar
.
MONTH
,
calendar
.
get
(
DateField
.
MONTH
.
getValue
())
/
3
*
3
);
calendar
.
set
(
Calendar
.
DAY_OF_MONTH
,
1
);
return
beginOfDay
(
calendar
);
}
/**
* 获取某季度的结束时间
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
* @since 4.1.0
*/
@SuppressWarnings
({
"MagicConstant"
,
"ConstantConditions"
})
public
static
Calendar
endOfQuarter
(
Calendar
calendar
)
{
final
int
year
=
calendar
.
get
(
Calendar
.
YEAR
);
final
int
month
=
calendar
.
get
(
DateField
.
MONTH
.
getValue
())
/
3
*
3
+
2
;
final
Calendar
resultCal
=
Calendar
.
getInstance
(
calendar
.
getTimeZone
());
resultCal
.
set
(
year
,
month
,
Month
.
of
(
month
).
getLastDay
(
DateUtil
.
isLeapYear
(
year
)));
return
endOfDay
(
resultCal
);
}
/**
* 修改某年的开始时间
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
*/
public
static
Calendar
beginOfYear
(
Calendar
calendar
)
{
return
truncate
(
calendar
,
DateField
.
YEAR
);
}
/**
* 修改某年的结束时间
*
* @param calendar 日期 {@link Calendar}
* @return {@link Calendar}
*/
public
static
Calendar
endOfYear
(
Calendar
calendar
)
{
return
ceiling
(
calendar
,
DateField
.
YEAR
);
}
/**
* 比较两个日期是否为同一天
*
* @param cal1 日期1
* @param cal2 日期2
* @return 是否为同一天
*/
public
static
boolean
isSameDay
(
Calendar
cal1
,
Calendar
cal2
)
{
if
(
cal1
==
null
||
cal2
==
null
)
{
throw
new
IllegalArgumentException
(
"The date must not be null"
);
}
return
cal1
.
get
(
Calendar
.
DAY_OF_YEAR
)
==
cal2
.
get
(
Calendar
.
DAY_OF_YEAR
)
&&
//
cal1
.
get
(
Calendar
.
YEAR
)
==
cal2
.
get
(
Calendar
.
YEAR
)
&&
//
cal1
.
get
(
Calendar
.
ERA
)
==
cal2
.
get
(
Calendar
.
ERA
);
}
/**
* 比较两个日期是否为同一周
*
* @param cal1 日期1
* @param cal2 日期2
* @param isMon 是否为周一。国内第一天为星期一,国外第一天为星期日
* @return 是否为同一周
* @since 5.7.21
*/
public
static
boolean
isSameWeek
(
Calendar
cal1
,
Calendar
cal2
,
boolean
isMon
)
{
if
(
cal1
==
null
||
cal2
==
null
)
{
throw
new
IllegalArgumentException
(
"The date must not be null"
);
}
// 防止比较前修改原始Calendar对象
cal1
=
(
Calendar
)
cal1
.
clone
();
cal2
=
(
Calendar
)
cal2
.
clone
();
// 把所传日期设置为其当前周的第一天
// 比较设置后的两个日期是否是同一天:true 代表同一周
if
(
isMon
)
{
cal1
.
setFirstDayOfWeek
(
Calendar
.
MONDAY
);
cal1
.
set
(
Calendar
.
DAY_OF_WEEK
,
Calendar
.
MONDAY
);
cal2
.
setFirstDayOfWeek
(
Calendar
.
MONDAY
);
cal2
.
set
(
Calendar
.
DAY_OF_WEEK
,
Calendar
.
MONDAY
);
}
else
{
cal1
.
setFirstDayOfWeek
(
Calendar
.
SUNDAY
);
cal1
.
set
(
Calendar
.
DAY_OF_WEEK
,
Calendar
.
SUNDAY
);
cal2
.
setFirstDayOfWeek
(
Calendar
.
SUNDAY
);
cal2
.
set
(
Calendar
.
DAY_OF_WEEK
,
Calendar
.
SUNDAY
);
}
return
isSameDay
(
cal1
,
cal2
);
}
/**
* 比较两个日期是否为同一月<br>
* 同一个月的意思是:ERA(公元)、year(年)、month(月)都一致。
*
* @param cal1 日期1
* @param cal2 日期2
* @return 是否为同一月
* @since 5.4.1
*/
public
static
boolean
isSameMonth
(
Calendar
cal1
,
Calendar
cal2
)
{
if
(
cal1
==
null
||
cal2
==
null
)
{
throw
new
IllegalArgumentException
(
"The date must not be null"
);
}
return
cal1
.
get
(
Calendar
.
YEAR
)
==
cal2
.
get
(
Calendar
.
YEAR
)
&&
//
cal1
.
get
(
Calendar
.
MONTH
)
==
cal2
.
get
(
Calendar
.
MONTH
)
&&
// issue#3011@Github
cal1
.
get
(
Calendar
.
ERA
)
==
cal2
.
get
(
Calendar
.
ERA
);
}
/**
* <p>检查两个Calendar时间戳是否相同。</p>
*
* <p>此方法检查两个Calendar的毫秒数时间戳是否相同。</p>
*
* @param date1 时间1
* @param date2 时间2
* @return 两个Calendar时间戳是否相同。如果两个时间都为{@code null}返回true,否则有{@code null}返回false
* @since 5.3.11
*/
public
static
boolean
isSameInstant
(
Calendar
date1
,
Calendar
date2
)
{
if
(
null
==
date1
)
{
return
null
==
date2
;
}
if
(
null
==
date2
)
{
return
false
;
}
return
date1
.
getTimeInMillis
()
==
date2
.
getTimeInMillis
();
}
/**
* 获得指定日期区间内的年份和季度<br>
*
* @param startDate 起始日期(包含)
* @param endDate 结束日期(包含)
* @return 季度列表 ,元素类似于 20132
* @since 4.1.15
*/
public
static
LinkedHashSet
<
String
>
yearAndQuarter
(
long
startDate
,
long
endDate
)
{
LinkedHashSet
<
String
>
quarters
=
new
LinkedHashSet
<>();
final
Calendar
cal
=
calendar
(
startDate
);
while
(
startDate
<=
endDate
)
{
// 如果开始时间超出结束时间,让结束时间为开始时间,处理完后结束循环
quarters
.
add
(
yearAndQuarter
(
cal
));
cal
.
add
(
Calendar
.
MONTH
,
3
);
startDate
=
cal
.
getTimeInMillis
();
}
return
quarters
;
}
/**
* 获得指定日期年份和季度<br>
* 格式:[20131]表示2013年第一季度
*
* @param cal 日期
* @return 年和季度,格式类似于20131
*/
public
static
String
yearAndQuarter
(
Calendar
cal
)
{
return
StrUtil
.
builder
().
append
(
cal
.
get
(
Calendar
.
YEAR
)).
append
(
cal
.
get
(
Calendar
.
MONTH
)
/
3
+
1
).
toString
();
}
/**
* 获取指定日期字段的最小值,例如分钟的最小值是0
*
* @param calendar {@link Calendar}
* @param dateField {@link DateField}
* @return 字段最小值
* @see Calendar#getActualMinimum(int)
* @since 5.4.2
*/
public
static
int
getBeginValue
(
Calendar
calendar
,
DateField
dateField
)
{
return
getBeginValue
(
calendar
,
dateField
.
getValue
());
}
/**
* 获取指定日期字段的最小值,例如分钟的最小值是0
*
* @param calendar {@link Calendar}
* @param dateField {@link DateField}
* @return 字段最小值
* @see Calendar#getActualMinimum(int)
* @since 4.5.7
*/
public
static
int
getBeginValue
(
Calendar
calendar
,
int
dateField
)
{
if
(
Calendar
.
DAY_OF_WEEK
==
dateField
)
{
return
calendar
.
getFirstDayOfWeek
();
}
return
calendar
.
getActualMinimum
(
dateField
);
}
/**
* 获取指定日期字段的最大值,例如分钟的最大值是59
*
* @param calendar {@link Calendar}
* @param dateField {@link DateField}
* @return 字段最大值
* @see Calendar#getActualMaximum(int)
* @since 5.4.2
*/
public
static
int
getEndValue
(
Calendar
calendar
,
DateField
dateField
)
{
return
getEndValue
(
calendar
,
dateField
.
getValue
());
}
/**
* 获取指定日期字段的最大值,例如分钟的最大值是59
*
* @param calendar {@link Calendar}
* @param dateField {@link DateField}
* @return 字段最大值
* @see Calendar#getActualMaximum(int)
* @since 4.5.7
*/
public
static
int
getEndValue
(
Calendar
calendar
,
int
dateField
)
{
if
(
Calendar
.
DAY_OF_WEEK
==
dateField
)
{
return
(
calendar
.
getFirstDayOfWeek
()
+
6
)
%
7
;
}
return
calendar
.
getActualMaximum
(
dateField
);
}
/**
* Calendar{@link Instant}对象
*
* @param calendar Date对象
* @return {@link Instant}对象
* @since 5.0.5
*/
public
static
Instant
toInstant
(
Calendar
calendar
)
{
return
null
==
calendar
?
null
:
calendar
.
toInstant
();
}
/**
* {@link Calendar} 转换为 {@link LocalDateTime},使用系统默认时区
*
* @param calendar {@link Calendar}
* @return {@link LocalDateTime}
* @since 5.0.5
*/
public
static
LocalDateTime
toLocalDateTime
(
Calendar
calendar
)
{
return
LocalDateTime
.
ofInstant
(
calendar
.
toInstant
(),
calendar
.
getTimeZone
().
toZoneId
());
}
/**
* {@code null}安全的{@link Calendar}比较,{@code null}小于任何日期
*
* @param calendar1 日期1
* @param calendar2 日期2
* @return 比较结果,如果calendar1 < calendar2,返回数小于0,calendar1==calendar2返回0,calendar1 > calendar2 大于0
* @since 4.6.2
*/
public
static
int
compare
(
Calendar
calendar1
,
Calendar
calendar2
)
{
return
CompareUtil
.
compare
(
calendar1
,
calendar2
);
}
/**
* 计算相对于dateToCompare的年龄,长用于计算指定生日在某年的年龄
*
* @param birthday 生日
* @param dateToCompare 需要对比的日期
* @return 年龄
*/
public
static
int
age
(
Calendar
birthday
,
Calendar
dateToCompare
)
{
return
age
(
birthday
.
getTimeInMillis
(),
dateToCompare
.
getTimeInMillis
());
}
/**
* 将指定Calendar时间格式化为纯中文形式,比如:
*
* <pre>
* 2018-02-24 12:13:14 转换为 二〇一八年二月二十四日(withTime为false)
* 2018-02-24 12:13:14 转换为 二〇一八年二月二十四日十二时十三分十四秒(withTime为true)
* </pre>
*
* @param calendar {@link Calendar}
* @param withTime 是否包含时间部分
* @return 格式化后的字符串
* @since 5.3.9
*/
public
static
String
formatChineseDate
(
Calendar
calendar
,
boolean
withTime
)
{
final
StringBuilder
result
=
StrUtil
.
builder
();
// 年
final
String
year
=
String
.
valueOf
(
calendar
.
get
(
Calendar
.
YEAR
));
final
int
length
=
year
.
length
();
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
result
.
append
(
NumberChineseFormatter
.
numberCharToChinese
(
year
.
charAt
(
i
),
false
));
}
result
.
append
(
'年'
);
// 月
int
month
=
calendar
.
get
(
Calendar
.
MONTH
)
+
1
;
result
.
append
(
NumberChineseFormatter
.
formatThousand
(
month
,
false
));
result
.
append
(
'月'
);
// 日
int
day
=
calendar
.
get
(
Calendar
.
DAY_OF_MONTH
);
result
.
append
(
NumberChineseFormatter
.
formatThousand
(
day
,
false
));
result
.
append
(
'日'
);
// 只替换年月日,时分秒中零不需要替换
String
temp
=
result
.
toString
().
replace
(
'零'
,
'〇'
);
result
.
delete
(
0
,
result
.
length
());
result
.
append
(
temp
);
if
(
withTime
)
{
// 时
int
hour
=
calendar
.
get
(
Calendar
.
HOUR_OF_DAY
);
result
.
append
(
NumberChineseFormatter
.
formatThousand
(
hour
,
false
));
result
.
append
(
'时'
);
// 分
int
minute
=
calendar
.
get
(
Calendar
.
MINUTE
);
result
.
append
(
NumberChineseFormatter
.
formatThousand
(
minute
,
false
));
result
.
append
(
'分'
);
// 秒
int
second
=
calendar
.
get
(
Calendar
.
SECOND
);
result
.
append
(
NumberChineseFormatter
.
formatThousand
(
second
,
false
));
result
.
append
(
'秒'
);
}
return
result
.
toString
();
}
/**
* 计算相对于dateToCompare的年龄,常用于计算指定生日在某年的年龄
*
* @param birthday 生日
* @param dateToCompare 需要对比的日期
* @return 年龄
*/
protected
static
int
age
(
long
birthday
,
long
dateToCompare
)
{
if
(
birthday
>
dateToCompare
)
{
throw
new
IllegalArgumentException
(
"Birthday is after dateToCompare!"
);
}
final
Calendar
cal
=
Calendar
.
getInstance
();
cal
.
setTimeInMillis
(
dateToCompare
);
final
int
year
=
cal
.
get
(
Calendar
.
YEAR
);
final
int
month
=
cal
.
get
(
Calendar
.
MONTH
);
final
int
dayOfMonth
=
cal
.
get
(
Calendar
.
DAY_OF_MONTH
);
final
boolean
isLastDayOfMonth
=
dayOfMonth
==
cal
.
getActualMaximum
(
Calendar
.
DAY_OF_MONTH
);
cal
.
setTimeInMillis
(
birthday
);
int
age
=
year
-
cal
.
get
(
Calendar
.
YEAR
);
final
int
monthBirth
=
cal
.
get
(
Calendar
.
MONTH
);
//当前日期,则为0岁
if
(
age
==
0
){
return
0
;
}
else
if
(
month
==
monthBirth
)
{
final
int
dayOfMonthBirth
=
cal
.
get
(
Calendar
.
DAY_OF_MONTH
);
final
boolean
isLastDayOfMonthBirth
=
dayOfMonthBirth
==
cal
.
getActualMaximum
(
Calendar
.
DAY_OF_MONTH
);
if
((
false
==
isLastDayOfMonth
||
false
==
isLastDayOfMonthBirth
)
&&
dayOfMonth
<=
dayOfMonthBirth
)
{
// 如果生日在当月,但是未超过生日当天的日期,年龄减一
age
--;
}
}
else
if
(
month
<
monthBirth
)
{
// 如果当前月份未达到生日的月份,年龄计算减一
age
--;
}
return
age
;
}
/**
* 通过给定的日期格式解析日期时间字符串。<br>
* 传入的日期格式会逐个尝试,直到解析成功,返回{@link Calendar}对象,否则抛出{@link DateException}异常。
* 方法来自:Apache Commons-Lang3
*
* @param str 日期时间字符串,非空
* @param parsePatterns 需要尝试的日期时间格式数组,非空, 见SimpleDateFormat
* @return 解析后的Calendar
* @throws IllegalArgumentException if the date string or pattern array is null
* @throws DateException if none of the date patterns were suitable
* @since 5.3.11
*/
public
static
Calendar
parseByPatterns
(
String
str
,
String
...
parsePatterns
)
throws
DateException
{
return
parseByPatterns
(
str
,
null
,
parsePatterns
);
}
/**
* 通过给定的日期格式解析日期时间字符串。<br>
* 传入的日期格式会逐个尝试,直到解析成功,返回{@link Calendar}对象,否则抛出{@link DateException}异常。
* 方法来自:Apache Commons-Lang3
*
* @param str 日期时间字符串,非空
* @param locale 地区,当为{@code null}时使用{@link Locale#getDefault()}
* @param parsePatterns 需要尝试的日期时间格式数组,非空, 见SimpleDateFormat
* @return 解析后的Calendar
* @throws IllegalArgumentException if the date string or pattern array is null
* @throws DateException if none of the date patterns were suitable
* @since 5.3.11
*/
public
static
Calendar
parseByPatterns
(
String
str
,
Locale
locale
,
String
...
parsePatterns
)
throws
DateException
{
return
parseByPatterns
(
str
,
locale
,
true
,
parsePatterns
);
}
/**
* 通过给定的日期格式解析日期时间字符串。<br>
* 传入的日期格式会逐个尝试,直到解析成功,返回{@link Calendar}对象,否则抛出{@link DateException}异常。
* 方法来自:Apache Commons-Lang3
*
* @param str 日期时间字符串,非空
* @param locale 地区,当为{@code null}时使用{@link Locale#getDefault()}
* @param lenient 日期时间解析是否使用严格模式
* @param parsePatterns 需要尝试的日期时间格式数组,非空, 见SimpleDateFormat
* @return 解析后的Calendar
* @throws IllegalArgumentException if the date string or pattern array is null
* @throws DateException if none of the date patterns were suitable
* @see java.util.Calendar#isLenient()
* @since 5.3.11
*/
public
static
Calendar
parseByPatterns
(
String
str
,
Locale
locale
,
boolean
lenient
,
String
...
parsePatterns
)
throws
DateException
{
if
(
str
==
null
||
parsePatterns
==
null
)
{
throw
new
IllegalArgumentException
(
"Date and Patterns must not be null"
);
}
final
TimeZone
tz
=
TimeZone
.
getDefault
();
final
Locale
lcl
=
ObjectUtil
.
defaultIfNull
(
locale
,
Locale
.
getDefault
());
final
ParsePosition
pos
=
new
ParsePosition
(
0
);
final
Calendar
calendar
=
Calendar
.
getInstance
(
tz
,
lcl
);
calendar
.
setLenient
(
lenient
);
for
(
final
String
parsePattern
:
parsePatterns
)
{
if
(
GlobalCustomFormat
.
isCustomFormat
(
parsePattern
))
{
final
Date
parse
=
GlobalCustomFormat
.
parse
(
str
,
parsePattern
);
if
(
null
==
parse
)
{
continue
;
}
calendar
.
setTime
(
parse
);
return
calendar
;
}
final
FastDateParser
fdp
=
new
FastDateParser
(
parsePattern
,
tz
,
lcl
);
calendar
.
clear
();
try
{
if
(
fdp
.
parse
(
str
,
pos
,
calendar
)
&&
pos
.
getIndex
()
==
str
.
length
())
{
return
calendar
;
}
}
catch
(
final
IllegalArgumentException
ignore
)
{
// leniency is preventing calendar from being set
}
pos
.
setIndex
(
0
);
}
throw
new
DateException
(
"Unable to parse the date: {}"
,
str
);
}
/**
* 使用指定{@link DateParser}解析字符串为{@link Calendar}
*
* @param str 日期字符串
* @param lenient 是否宽容模式
* @param parser {@link DateParser}
* @return 解析后的 {@link Calendar},解析失败返回{@code null}
* @since 5.7.14
*/
public
static
Calendar
parse
(
CharSequence
str
,
boolean
lenient
,
DateParser
parser
)
{
final
Calendar
calendar
=
Calendar
.
getInstance
(
parser
.
getTimeZone
(),
parser
.
getLocale
());
calendar
.
clear
();
calendar
.
setLenient
(
lenient
);
return
parser
.
parse
(
StrUtil
.
str
(
str
),
new
ParsePosition
(
0
),
calendar
)
?
calendar
:
null
;
}
}
hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.date
;
import
cn.hutool.core.convert.NumberChineseFormatter
;
import
cn.hutool.core.date.chinese.ChineseMonth
;
import
cn.hutool.core.date.chinese.GanZhi
;
import
cn.hutool.core.date.chinese.LunarFestival
;
import
cn.hutool.core.date.chinese.LunarInfo
;
import
cn.hutool.core.date.chinese.SolarTerms
;
import
cn.hutool.core.util.StrUtil
;
import
java.time.LocalDate
;
import
java.util.Calendar
;
import
java.util.Date
;
/**
* 农历日期工具,最大支持到2099年,支持:
*
* <ul>
* <li>通过公历日期构造获取对应农历</li>
* <li>通过农历日期直接构造</li>
* </ul>
*
* @author zjw, looly
* @since 5.1.1
*/
public
class
ChineseDate
{
//农历年
private
final
int
year
;
//农历月,润N月这个值就是N+1,其他月按照显示月份赋值
private
final
int
month
;
// 当前月份是否闰月
private
final
boolean
isLeapMonth
;
//农历日
private
final
int
day
;
//公历年
private
final
int
gyear
;
//公历月,从1开始计数
private
final
int
gmonthBase1
;
//公历日
private
final
int
gday
;
/**
* 通过公历日期构造
*
* @param date 公历日期
*/
public
ChineseDate
(
Date
date
)
{
this
(
LocalDateTimeUtil
.
ofDate
(
date
.
toInstant
()));
}
/**
* 通过公历日期构造
*
* @param localDate 公历日期
* @since 5.7.22
*/
public
ChineseDate
(
LocalDate
localDate
)
{
// 公历
gyear
=
localDate
.
getYear
();
gmonthBase1
=
localDate
.
getMonthValue
();
gday
=
localDate
.
getDayOfMonth
();
// 求出和1900年1月31日相差的天数
int
offset
=
(
int
)
(
localDate
.
toEpochDay
()
-
LunarInfo
.
BASE_DAY
);
// 计算农历年份
// 用offset减去每农历年的天数,计算当天是农历第几天,offset是当年的第几天
int
daysOfYear
;
int
iYear
;
for
(
iYear
=
LunarInfo
.
BASE_YEAR
;
iYear
<=
LunarInfo
.
MAX_YEAR
;
iYear
++)
{
daysOfYear
=
LunarInfo
.
yearDays
(
iYear
);
if
(
offset
<
daysOfYear
)
{
break
;
}
offset
-=
daysOfYear
;
}
year
=
iYear
;
// 计算农历月份
final
int
leapMonth
=
LunarInfo
.
leapMonth
(
iYear
);
// 闰哪个月,1-12
// 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
int
month
;
int
daysOfMonth
;
boolean
hasLeapMonth
=
false
;
for
(
month
=
1
;
month
<
13
;
month
++)
{
// 闰月,如润的是五月,则5表示五月,6表示润五月
if
(
leapMonth
>
0
&&
month
==
(
leapMonth
+
1
))
{
daysOfMonth
=
LunarInfo
.
leapDays
(
year
);
hasLeapMonth
=
true
;
}
else
{
// 普通月,当前面的月份存在闰月时,普通月份要-1,递补闰月的数字
// 如2月是闰月,此时3月实际是第四个月
daysOfMonth
=
LunarInfo
.
monthDays
(
year
,
hasLeapMonth
?
month
-
1
:
month
);
}
if
(
offset
<
daysOfMonth
)
{
// offset不足月,结束
break
;
}
offset
-=
daysOfMonth
;
}
this
.
isLeapMonth
=
leapMonth
>
0
&&
(
month
==
(
leapMonth
+
1
));
if
(
hasLeapMonth
&&
false
==
this
.
isLeapMonth
)
{
// 当前月份前有闰月,则月份显示要-1,除非当前月份就是润月
month
--;
}
this
.
month
=
month
;
this
.
day
=
offset
+
1
;
}
/**
* 构造方法传入日期<br>
* 此方法自动判断闰月,如果chineseMonth为本年的闰月,则按照闰月计算
*
* @param chineseYear 农历年
* @param chineseMonth 农历月,1表示一月(正月)
* @param chineseDay 农历日,1表示初一
* @since 5.2.4
*/
public
ChineseDate
(
int
chineseYear
,
int
chineseMonth
,
int
chineseDay
)
{
this
(
chineseYear
,
chineseMonth
,
chineseDay
,
chineseMonth
==
LunarInfo
.
leapMonth
(
chineseYear
));
}
/**
* 构造方法传入日期<br>
* 通过isLeapMonth参数区分是否闰月,如五月是闰月,当isLeapMonth为{@code true}时,表示润五月,{@code false}表示五月
*
* @param chineseYear 农历年
* @param chineseMonth 农历月,1表示一月(正月),如果isLeapMonth为{@code true},1表示润一月
* @param chineseDay 农历日,1表示初一
* @param isLeapMonth 当前月份是否闰月
* @since 5.7.18
*/
public
ChineseDate
(
int
chineseYear
,
int
chineseMonth
,
int
chineseDay
,
boolean
isLeapMonth
)
{
if
(
chineseMonth
!=
LunarInfo
.
leapMonth
(
chineseYear
)){
// issue#I5YB1A,用户传入的月份可能非闰月,此时此参数无效。
isLeapMonth
=
false
;
}
this
.
day
=
chineseDay
;
// 当月是闰月的后边的月定义为闰月,如润的是五月,则5表示五月,6表示润五月
this
.
isLeapMonth
=
isLeapMonth
;
// 闰月时,农历月份+1,如6表示润五月
this
.
month
=
isLeapMonth
?
chineseMonth
+
1
:
chineseMonth
;
this
.
year
=
chineseYear
;
final
DateTime
dateTime
=
lunar2solar
(
chineseYear
,
chineseMonth
,
chineseDay
,
isLeapMonth
);
if
(
null
!=
dateTime
)
{
//初始化公历年
this
.
gday
=
dateTime
.
dayOfMonth
();
//初始化公历月
this
.
gmonthBase1
=
dateTime
.
month
()
+
1
;
//初始化公历日
this
.
gyear
=
dateTime
.
year
();
}
else
{
//初始化公历年
this
.
gday
=
-
1
;
//初始化公历月
this
.
gmonthBase1
=
-
1
;
//初始化公历日
this
.
gyear
=
-
1
;
}
}
/**
* 获得农历年份
*
* @return 返回农历年份
*/
public
int
getChineseYear
()
{
return
this
.
year
;
}
/**
* 获取公历的年
*
* @return 公历年
* @since 5.6.1
*/
public
int
getGregorianYear
()
{
return
this
.
gyear
;
}
/**
* 获取农历的月,从1开始计数<br>
* 此方法返回实际的月序号,如一月是闰月,则一月返回1,润一月返回2
*
* @return 农历的月
* @since 5.2.4
*/
public
int
getMonth
()
{
return
this
.
month
;
}
/**
* 获取公历的月,从1开始计数
*
* @return 公历月
* @since 5.6.1
*/
public
int
getGregorianMonthBase1
()
{
return
this
.
gmonthBase1
;
}
/**
* 获取公历的月,从0开始计数
*
* @return 公历月
* @since 5.6.1
*/
public
int
getGregorianMonth
()
{
return
this
.
gmonthBase1
-
1
;
}
/**
* 当前农历月份是否为闰月
*
* @return 是否为闰月
* @since 5.4.2
*/
public
boolean
isLeapMonth
()
{
return
this
.
isLeapMonth
;
}
/**
* 获得农历月份(中文,例如二月,十二月,或者润一月)
*
* @return 返回农历月份
*/
public
String
getChineseMonth
()
{
return
getChineseMonth
(
false
);
}
/**
* 获得农历月称呼(中文,例如二月,腊月,或者润正月)
*
* @return 返回农历月份称呼
*/
public
String
getChineseMonthName
()
{
return
getChineseMonth
(
true
);
}
/**
* 获得农历月份(中文,例如二月,十二月,或者润一月)
*
* @param isTraditional 是否传统表示,例如一月传统表示为正月
* @return 返回农历月份
* @since 5.7.18
*/
public
String
getChineseMonth
(
boolean
isTraditional
)
{
return
ChineseMonth
.
getChineseMonthName
(
isLeapMonth
(),
isLeapMonth
()
?
this
.
month
-
1
:
this
.
month
,
isTraditional
);
}
/**
* 获取农历的日,从1开始计数
*
* @return 农历的日,从1开始计数
* @since 5.2.4
*/
public
int
getDay
()
{
return
this
.
day
;
}
/**
* 获取公历的日
*
* @return 公历日
* @since 5.6.1
*/
public
int
getGregorianDay
()
{
return
this
.
gday
;
}
/**
* 获得农历日
*
* @return 获得农历日
*/
public
String
getChineseDay
()
{
String
[]
chineseTen
=
{
"初"
,
"十"
,
"廿"
,
"卅"
};
int
n
=
(
day
%
10
==
0
)
?
9
:
(
day
%
10
-
1
);
if
(
day
>
30
)
{
return
""
;
}
switch
(
day
)
{
case
10
:
return
"初十"
;
case
20
:
return
"二十"
;
case
30
:
return
"三十"
;
default
:
return
chineseTen
[
day
/
10
]
+
NumberChineseFormatter
.
format
(
n
+
1
,
false
);
}
}
/**
* 获取公历的Date
*
* @return 公历Date
* @since 5.6.1
*/
public
Date
getGregorianDate
()
{
return
DateUtil
.
date
(
getGregorianCalendar
());
}
/**
* 获取公历的Calendar
*
* @return 公历Calendar
* @since 5.6.1
*/
public
Calendar
getGregorianCalendar
()
{
final
Calendar
calendar
=
CalendarUtil
.
calendar
();
//noinspection MagicConstant
calendar
.
set
(
this
.
gyear
,
getGregorianMonth
(),
this
.
gday
,
0
,
0
,
0
);
return
calendar
;
}
/**
* 获得节日,闰月不计入节日中
*
* @return 获得农历节日
*/
public
String
getFestivals
()
{
return
StrUtil
.
join
(
","
,
LunarFestival
.
getFestivals
(
this
.
year
,
this
.
month
,
day
));
}
/**
* 获得年份生肖
*
* @return 获得年份生肖
*/
public
String
getChineseZodiac
()
{
return
Zodiac
.
getChineseZodiac
(
this
.
year
);
}
/**
* 获得年的天干地支
*
* @return 获得天干地支
*/
public
String
getCyclical
()
{
return
GanZhi
.
getGanzhiOfYear
(
this
.
year
);
}
/**
* 干支纪年信息
*
* @return 获得天干地支的年月日信息
*/
public
String
getCyclicalYMD
()
{
if
(
gyear
>=
LunarInfo
.
BASE_YEAR
&&
gmonthBase1
>
0
&&
gday
>
0
)
{
return
cyclicalm
(
gyear
,
gmonthBase1
,
gday
);
}
return
null
;
}
/**
* 获得节气
*
* @return 获得节气
* @since 5.6.3
*/
public
String
getTerm
()
{
return
SolarTerms
.
getTerm
(
gyear
,
gmonthBase1
,
gday
);
}
/**
* 转换为标准的日期格式来表示农历日期,例如2020-01-13<br>
* 如果存在闰月,显示闰月月份,如润二月显示2
*
* @return 标准的日期格式
* @since 5.2.4
*/
public
String
toStringNormal
()
{
return
String
.
format
(
"%04d-%02d-%02d"
,
this
.
year
,
isLeapMonth
()
?
this
.
month
-
1
:
this
.
month
,
this
.
day
);
}
@Override
public
String
toString
()
{
return
String
.
format
(
"%s%s年 %s%s"
,
getCyclical
(),
getChineseZodiac
(),
getChineseMonthName
(),
getChineseDay
());
}
// ------------------------------------------------------- private method start
/**
* 这里同步处理年月日的天干地支信息
*
* @param year 公历年
* @param month 公历月,从1开始
* @param day 公历日
* @return 天干地支信息
*/
private
String
cyclicalm
(
int
year
,
int
month
,
int
day
)
{
return
StrUtil
.
format
(
"{}年{}月{}日"
,
GanZhi
.
getGanzhiOfYear
(
this
.
year
),
GanZhi
.
getGanzhiOfMonth
(
year
,
month
,
day
),
GanZhi
.
getGanzhiOfDay
(
year
,
month
,
day
));
}
/**
* 通过农历年月日信息 返回公历信息 提供给构造函数
*
* @param chineseYear 农历年
* @param chineseMonth 农历月
* @param chineseDay 农历日
* @param isLeapMonth 传入的月是不是闰月
* @return 公历信息
*/
private
DateTime
lunar2solar
(
int
chineseYear
,
int
chineseMonth
,
int
chineseDay
,
boolean
isLeapMonth
)
{
//超出了最大极限值
if
((
chineseYear
==
2100
&&
chineseMonth
==
12
&&
chineseDay
>
1
)
||
(
chineseYear
==
LunarInfo
.
BASE_YEAR
&&
chineseMonth
==
1
&&
chineseDay
<
31
))
{
return
null
;
}
int
day
=
LunarInfo
.
monthDays
(
chineseYear
,
chineseMonth
);
int
_day
=
day
;
if
(
isLeapMonth
)
{
_day
=
LunarInfo
.
leapDays
(
chineseYear
);
}
//参数合法性效验
if
(
chineseYear
<
LunarInfo
.
BASE_YEAR
||
chineseYear
>
2100
||
chineseDay
>
_day
)
{
return
null
;
}
//计算农历的时间差
int
offset
=
0
;
for
(
int
i
=
LunarInfo
.
BASE_YEAR
;
i
<
chineseYear
;
i
++)
{
offset
+=
LunarInfo
.
yearDays
(
i
);
}
int
leap
;
boolean
isAdd
=
false
;
for
(
int
i
=
1
;
i
<
chineseMonth
;
i
++)
{
leap
=
LunarInfo
.
leapMonth
(
chineseYear
);
if
(
false
==
isAdd
)
{
//处理闰月
if
(
leap
<=
i
&&
leap
>
0
)
{
offset
+=
LunarInfo
.
leapDays
(
chineseYear
);
isAdd
=
true
;
}
}
offset
+=
LunarInfo
.
monthDays
(
chineseYear
,
i
);
}
//转换闰月农历 需补充该年闰月的前一个月的时差
if
(
isLeapMonth
)
{
offset
+=
day
;
}
//1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点) -2203804800000
return
DateUtil
.
date
(((
offset
+
chineseDay
-
31
)
*
86400000L
)
-
2203804800000L
);
}
// ------------------------------------------------------- private method end
}
hutool-core/src/main/java/cn/hutool/core/date/DateBetween.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.date
;
import
cn.hutool.core.lang.Assert
;
import
java.io.Serializable
;
import
java.util.Calendar
;
import
java.util.Date
;
/**
* 日期间隔
*
* @author Looly
*/
public
class
DateBetween
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 开始日期
*/
private
final
Date
begin
;
/**
* 结束日期
*/
private
final
Date
end
;
/**
* 创建<br>
* 在前的日期做为起始时间,在后的做为结束时间,间隔只保留绝对值正数
*
* @param begin 起始时间
* @param end 结束时间
* @return DateBetween
* @since 3.2.3
*/
public
static
DateBetween
create
(
Date
begin
,
Date
end
)
{
return
new
DateBetween
(
begin
,
end
);
}
/**
* 创建<br>
* 在前的日期做为起始时间,在后的做为结束时间,间隔只保留绝对值正数
*
* @param begin 起始时间
* @param end 结束时间
* @param isAbs 日期间隔是否只保留绝对值正数
* @return DateBetween
* @since 3.2.3
*/
public
static
DateBetween
create
(
Date
begin
,
Date
end
,
boolean
isAbs
)
{
return
new
DateBetween
(
begin
,
end
,
isAbs
);
}
/**
* 构造<br>
* 在前的日期做为起始时间,在后的做为结束时间,间隔只保留绝对值正数
*
* @param begin 起始时间
* @param end 结束时间
*/
public
DateBetween
(
Date
begin
,
Date
end
)
{
this
(
begin
,
end
,
true
);
}
/**
* 构造<br>
* 在前的日期做为起始时间,在后的做为结束时间
*
* @param begin 起始时间
* @param end 结束时间
* @param isAbs 日期间隔是否只保留绝对值正数
* @since 3.1.1
*/
public
DateBetween
(
Date
begin
,
Date
end
,
boolean
isAbs
)
{
Assert
.
notNull
(
begin
,
"Begin date is null !"
);
Assert
.
notNull
(
end
,
"End date is null !"
);
if
(
isAbs
&&
begin
.
after
(
end
))
{
// 间隔只为正数的情况下,如果开始日期晚于结束日期,置换之
this
.
begin
=
end
;
this
.
end
=
begin
;
}
else
{
this
.
begin
=
begin
;
this
.
end
=
end
;
}
}
/**
* 判断两个日期相差的时长<br>
* 返回 给定单位的时长差
*
* @param unit 相差的单位:相差 天{@link DateUnit#DAY}、小时{@link DateUnit#HOUR} 等
* @return 时长差
*/
public
long
between
(
DateUnit
unit
)
{
long
diff
=
end
.
getTime
()
-
begin
.
getTime
();
return
diff
/
unit
.
getMillis
();
}
/**
* 计算两个日期相差月数<br>
* 在非重置情况下,如果起始日期的天大于结束日期的天,月数要少算1(不足1个月)
*
* @param isReset 是否重置时间为起始时间(重置天时分秒)
* @return 相差月数
* @since 3.0.8
*/
public
long
betweenMonth
(
boolean
isReset
)
{
final
Calendar
beginCal
=
DateUtil
.
calendar
(
begin
);
final
Calendar
endCal
=
DateUtil
.
calendar
(
end
);
final
int
betweenYear
=
endCal
.
get
(
Calendar
.
YEAR
)
-
beginCal
.
get
(
Calendar
.
YEAR
);
final
int
betweenMonthOfYear
=
endCal
.
get
(
Calendar
.
MONTH
)
-
beginCal
.
get
(
Calendar
.
MONTH
);
int
result
=
betweenYear
*
12
+
betweenMonthOfYear
;
if
(
false
==
isReset
)
{
endCal
.
set
(
Calendar
.
YEAR
,
beginCal
.
get
(
Calendar
.
YEAR
));
endCal
.
set
(
Calendar
.
MONTH
,
beginCal
.
get
(
Calendar
.
MONTH
));
long
between
=
endCal
.
getTimeInMillis
()
-
beginCal
.
getTimeInMillis
();
if
(
between
<
0
)
{
return
result
-
1
;
}
}
return
result
;
}
/**
* 计算两个日期相差年数<br>
* 在非重置情况下,如果起始日期的月大于结束日期的月,年数要少算1(不足1年)
*
* @param isReset 是否重置时间为起始时间(重置月天时分秒)
* @return 相差年数
* @since 3.0.8
*/
public
long
betweenYear
(
boolean
isReset
)
{
final
Calendar
beginCal
=
DateUtil
.
calendar
(
begin
);
final
Calendar
endCal
=
DateUtil
.
calendar
(
end
);
int
result
=
endCal
.
get
(
Calendar
.
YEAR
)
-
beginCal
.
get
(
Calendar
.
YEAR
);
if
(
false
==
isReset
)
{
// 考虑闰年的2月情况
if
(
Calendar
.
FEBRUARY
==
beginCal
.
get
(
Calendar
.
MONTH
)
&&
Calendar
.
FEBRUARY
==
endCal
.
get
(
Calendar
.
MONTH
))
{
if
(
beginCal
.
get
(
Calendar
.
DAY_OF_MONTH
)
==
beginCal
.
getActualMaximum
(
Calendar
.
DAY_OF_MONTH
)
&&
endCal
.
get
(
Calendar
.
DAY_OF_MONTH
)
==
endCal
.
getActualMaximum
(
Calendar
.
DAY_OF_MONTH
))
{
// 两个日期都位于2月的最后一天,此时月数按照相等对待,此时都设置为1号
beginCal
.
set
(
Calendar
.
DAY_OF_MONTH
,
1
);
endCal
.
set
(
Calendar
.
DAY_OF_MONTH
,
1
);
}
}
endCal
.
set
(
Calendar
.
YEAR
,
beginCal
.
get
(
Calendar
.
YEAR
));
long
between
=
endCal
.
getTimeInMillis
()
-
beginCal
.
getTimeInMillis
();
if
(
between
<
0
)
{
return
result
-
1
;
}
}
return
result
;
}
/**
* 格式化输出时间差
*
* @param unit 日期单位
* @param level 级别
* @return 字符串
* @since 5.7.17
*/
public
String
toString
(
DateUnit
unit
,
BetweenFormatter
.
Level
level
)
{
return
DateUtil
.
formatBetween
(
between
(
unit
),
level
);
}
/**
* 格式化输出时间差
*
* @param level 级别
* @return 字符串
*/
public
String
toString
(
BetweenFormatter
.
Level
level
)
{
return
toString
(
DateUnit
.
MS
,
level
);
}
@Override
public
String
toString
()
{
return
toString
(
BetweenFormatter
.
Level
.
MILLISECOND
);
}
}
hutool-core/src/main/java/cn/hutool/core/date/DateException.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.date
;
import
cn.hutool.core.exceptions.ExceptionUtil
;
import
cn.hutool.core.util.StrUtil
;
/**
* 工具类异常
* @author xiaoleilu
*/
public
class
DateException
extends
RuntimeException
{
private
static
final
long
serialVersionUID
=
8247610319171014183L
;
public
DateException
(
Throwable
e
)
{
super
(
ExceptionUtil
.
getMessage
(
e
),
e
);
}
public
DateException
(
String
message
)
{
super
(
message
);
}
public
DateException
(
String
messageTemplate
,
Object
...
params
)
{
super
(
StrUtil
.
format
(
messageTemplate
,
params
));
}
public
DateException
(
String
message
,
Throwable
throwable
)
{
super
(
message
,
throwable
);
}
public
DateException
(
Throwable
throwable
,
String
messageTemplate
,
Object
...
params
)
{
super
(
StrUtil
.
format
(
messageTemplate
,
params
),
throwable
);
}
}
hutool-core/src/main/java/cn/hutool/core/date/DateField.java
0 → 100644
View file @
45cda665
package
cn.hutool.core.date
;
import
java.util.Calendar
;
/**
* 日期各个部分的枚举<br>
* 与Calendar相应值对应
*
* @author Looly
*
*/
public
enum
DateField
{
/**
* 世纪
*
* @see Calendar#ERA
*/
ERA
(
Calendar
.
ERA
),
/**
* 年
*
* @see Calendar#YEAR
*/
YEAR
(
Calendar
.
YEAR
),
/**
* 月
*
* @see Calendar#MONTH
*/
MONTH
(
Calendar
.
MONTH
),
/**
* 一年中第几周
*
* @see Calendar#WEEK_OF_YEAR
*/
WEEK_OF_YEAR
(
Calendar
.
WEEK_OF_YEAR
),
/**
* 一月中第几周
*
* @see Calendar#WEEK_OF_MONTH
*/
WEEK_OF_MONTH
(
Calendar
.
WEEK_OF_MONTH
),
/**
* 一月中的第几天
*
* @see Calendar#DAY_OF_MONTH
*/
DAY_OF_MONTH
(
Calendar
.
DAY_OF_MONTH
),
/**
* 一年中的第几天
*
* @see Calendar#DAY_OF_YEAR
*/
DAY_OF_YEAR
(
Calendar
.
DAY_OF_YEAR
),
/**
* 周几,1表示周日,2表示周一
*
* @see Calendar#DAY_OF_WEEK
*/
DAY_OF_WEEK
(
Calendar
.
DAY_OF_WEEK
),
/**
* 天所在的周是这个月的第几周
*
* @see Calendar#DAY_OF_WEEK_IN_MONTH
*/
DAY_OF_WEEK_IN_MONTH
(
Calendar
.
DAY_OF_WEEK_IN_MONTH
),
/**
* 上午或者下午
*
* @see Calendar#AM_PM
*/
AM_PM
(
Calendar
.
AM_PM
),
/**
* 小时,用于12小时制
*
* @see Calendar#HOUR
*/
HOUR
(
Calendar
.
HOUR
),
/**
* 小时,用于24小时制
*
* @see Calendar#HOUR
*/
HOUR_OF_DAY
(
Calendar
.
HOUR_OF_DAY
),
/**
* 分钟
*
* @see Calendar#MINUTE
*/
MINUTE
(
Calendar
.
MINUTE
),
/**
* 秒
*
* @see Calendar#SECOND
*/
SECOND
(
Calendar
.
SECOND
),
/**
* 毫秒
*
* @see Calendar#MILLISECOND
*/
MILLISECOND
(
Calendar
.
MILLISECOND
);
// ---------------------------------------------------------------
private
final
int
value
;
DateField
(
int
value
)
{
this
.
value
=
value
;
}
public
int
getValue
()
{
return
this
.
value
;
}
/**
* 将 {@link Calendar}相关值转换为DatePart枚举对象<br>
*
* @param calendarPartIntValue Calendar中关于Week的int值
* @return DateField
*/
public
static
DateField
of
(
int
calendarPartIntValue
)
{
switch
(
calendarPartIntValue
)
{
case
Calendar
.
ERA
:
return
ERA
;
case
Calendar
.
YEAR
:
return
YEAR
;
case
Calendar
.
MONTH
:
return
MONTH
;
case
Calendar
.
WEEK_OF_YEAR
:
return
WEEK_OF_YEAR
;
case
Calendar
.
WEEK_OF_MONTH
:
return
WEEK_OF_MONTH
;
case
Calendar
.
DAY_OF_MONTH
:
return
DAY_OF_MONTH
;
case
Calendar
.
DAY_OF_YEAR
:
return
DAY_OF_YEAR
;
case
Calendar
.
DAY_OF_WEEK
:
return
DAY_OF_WEEK
;
case
Calendar
.
DAY_OF_WEEK_IN_MONTH
:
return
DAY_OF_WEEK_IN_MONTH
;
case
Calendar
.
AM_PM
:
return
AM_PM
;
case
Calendar
.
HOUR
:
return
HOUR
;
case
Calendar
.
HOUR_OF_DAY
:
return
HOUR_OF_DAY
;
case
Calendar
.
MINUTE
:
return
MINUTE
;
case
Calendar
.
SECOND
:
return
SECOND
;
case
Calendar
.
MILLISECOND
:
return
MILLISECOND
;
default
:
return
null
;
}
}
}
Prev
1
…
13
14
15
16
17
18
19
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment