Skip to content

Instantly share code, notes, and snippets.

@lshoo
Created April 12, 2015 09:09
Show Gist options
  • Save lshoo/4718c8e7c7cce1ba10ff to your computer and use it in GitHub Desktop.
Save lshoo/4718c8e7c7cce1ba10ff to your computer and use it in GitHub Desktop.
DateTimeUtls.scala
package utils
import org.joda.time.DateTime
import org.joda.time.format.{DateTimeFormatterBuilder, DateTimeFormat, DateTimeFormatter}
import scala.concurrent.stm._
/**
* Created by liaoshifu on 2015/4/11
*/
object DateTimeUtils {
val Pattern_Cache: Ref[Map[String, DateTimeFormatter]] = Ref(Map.empty)
def parsePatternTo(builder: DateTimeFormatterBuilder, pattern: String): Unit = {
val length = pattern.length
val indexRef: Array[Int] = Array.ofDim(1)
var i = 0
var toLoop = true
while (i < length && toLoop) {
indexRef(0) = i
val token = parseToken(pattern, indexRef)
i = indexRef(0)
val tokenLen = token.length
if (tokenLen == 0) {
toLoop = false
} else {
val c = token.charAt(0)
c match {
case 'G' =>
builder.appendEraText()
toLoop = false
case 'C' =>
builder.appendCenturyOfEra(tokenLen, tokenLen)
toLoop = false
case 'x' =>
case 'y' =>
case 'Y' =>
if (tokenLen == 2) {
var lenientParse = true
if (i + 1 < length) {
indexRef(0) = indexRef(0) + 1
if (isNumericToken(parseToken(pattern, indexRef))) {
lenientParse = false
} else {
indexRef(0) = indexRef(0) - 1
}
}
c match {
case 'x' =>
builder.appendTwoDigitWeekyear(new DateTime().getWeekyear - 30, lenientParse)
//case 'y' =>
//case 'Y' =>
case _ =>
builder.appendTwoDigitYear(new DateTime().getYear - 30, lenientParse)
}
} else {
var maxDigits: Int = 9
// Peek ahead to next token.
if (i + 1 < length) {
indexRef(0) += 1
if (isNumericToken(parseToken(pattern, indexRef))) {
maxDigits = tokenLen
}
indexRef(0) -= 1
}
c match {
case 'x' =>
builder.appendWeekyear(tokenLen, maxDigits)
case 'y' =>
builder.appendYear(tokenLen, maxDigits)
case 'Y' =>
builder.appendYearOfEra(tokenLen, maxDigits)
}
}
case 'M' =>
if (tokenLen >= 3) {
if (tokenLen >= 4) {
builder.appendMonthOfYearText
}
else {
builder.appendMonthOfYearShortText
}
}
else {
builder.appendMonthOfYear(tokenLen)
}
case 'd' =>
builder.appendDayOfMonth(tokenLen)
case 'a' =>
builder.appendHalfdayOfDayText
case 'h' =>
builder.appendClockhourOfHalfday(tokenLen)
case 'H' =>
builder.appendHourOfDay(tokenLen)
case 'k' =>
builder.appendClockhourOfDay(tokenLen)
case 'K' =>
builder.appendHourOfHalfday(tokenLen)
case 'm' =>
builder.appendMinuteOfHour(tokenLen)
case 's' =>
builder.appendSecondOfMinute(tokenLen)
case 'S' =>
builder.appendFractionOfSecond(tokenLen, tokenLen)
case 'e' =>
builder.appendDayOfWeek(tokenLen)
case 'E' =>
if (tokenLen >= 4) {
builder.appendDayOfWeekText
}
else {
builder.appendDayOfWeekShortText
}
case 'D' =>
builder.appendDayOfYear(tokenLen)
case 'w' =>
builder.appendWeekOfWeekyear(tokenLen)
case 'z' =>
if (tokenLen >= 4) {
builder.appendTimeZoneName
}
else {
builder.appendTimeZoneShortName(null)
}
case 'Z' =>
if (tokenLen == 1) {
builder.appendTimeZoneOffset(null, "Z", false, 2, 2)
}
else if (tokenLen == 2) {
builder.appendTimeZoneOffset(null, "Z", true, 2, 2)
}
else {
builder.appendTimeZoneId
}
case '\'' =>
val sub: String = token.substring(1)
if (sub.length == 1) {
builder.appendLiteral(sub.charAt(0))
}
else {
builder.appendLiteral(new String(sub))
}
case other =>
throw new IllegalArgumentException("Illegal pattern component: " + token)
}
}
i +=1
}
}
private def isNumericToken (token: String): Boolean = {
val tokenLen: Int = token.length
if (tokenLen > 0) {
val c: Char = token.charAt(0)
// 匹配不到,用最好的值(false)
c match {
case 'c' => false
case 'C' => false
case 'x' => false
case 'y' => false
case 'Y' => false
case 'd' => false
case 'h' => false
case 'H' => false
case 'm' => false
case 's' => false
case 'S' => false
case 'e' => false
case 'D' => false
case 'F' => false
case 'w' => false
case 'W' => false
case 'k' => false
case 'K' =>
true
case 'M' =>
if (tokenLen <= 2) {
true
} else false
}
} else false
}
private def parseToken(pattern: String, indexRef: Array[Int]): String = {
val buf = new StringBuilder
var i = indexRef(0)
val length = pattern.length
// break loop tag
var toLoop = true
var c: Char = pattern.charAt(i)
if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') {
// Scan a run of the same cha racter, which indicates a time pattern.
buf.append(c)
while ((i + 1 < length) && toLoop) {
val peek = pattern.charAt(i + 1)
if (peek == c) {
buf.append(c)
i = i + 1
} else {
toLoop = false
}
}
} else {
buf.append('\'')
var inLiteral = false
while (i < length && toLoop) {
c = pattern.charAt(i)
if (c == '\'') {
if (i + 1 < length && pattern.charAt(i + 1) == '\'') {
i += 1
buf.append(c)
}
else {
inLiteral = !inLiteral
}
}
else if (!inLiteral && (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')) {
i -= 1
toLoop = false
}
else {
buf.append(c)
}
i += 1
}
}
indexRef(0) = i
buf.toString()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment