Created
April 12, 2015 09:09
-
-
Save lshoo/4718c8e7c7cce1ba10ff to your computer and use it in GitHub Desktop.
DateTimeUtls.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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