Datetime对象以两种不同的格式进入我的程序:unix时间戳和yyyy-MM-dd HH:mm:ss.S
。例如,1520877600
或2018-04-23 11:12:00.0
。我需要从这些对象中提取一年和一个月,自动识别格式。
这是从year
中提取yyyy-MM-dd HH:mm:ss.S
的功能:
def getYear(datetimeString: Any): Int = {
var year = 2017
if (!datetimeString.toString.isEmpty) {
val dateFormat = "yyyy-MM-dd HH:mm:ss.S"
val dtf = java.time.format.DateTimeFormatter.ofPattern(dateFormat)
val d = java.time.LocalDate.parse(datetimeString.toString, dtf)
year = d.getYear
}
year
}
这与unix时间戳的功能相同:
def getYear(timestamp: Any): Int = {
var year = 2017
if (!timestamp.toString.isEmpty)
{
year = new DateTime(timestamp.toString.toLong).getYear
}
year
}
如何将它们合并到一个函数中,以便我的程序可以灵活运行并适用于这两种格式?
答案 0 :(得分:1)
您可以使用java.time.format.DateTimeFormatterBuilder
构建带有可选部分的格式化程序,其中每个可选部分都是opener = urllib.request.URLopener()
opener.addheader('User-Agent', 'whatever')
opener.retrieve(manga_url, manga_name)
,可以解析其中一种格式。
我在Java中发布代码,因为我不是Scala开发人员,但应该很难适应它。
首先为日期/时间模式制作格式化程序:
DateTimeFormatter
然后你创建另一个格式化程序来解析时间戳。自{unix epoch 以来,值DateTimeFormatter datetimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
似乎处于秒内,因此您可以使用ChronoField.INSTANT_SECONDS
字段:
1520877600
然后你将上面的2个格式化程序加入到一个格式化程序中,使每个格式化程序都可选:
DateTimeFormatter timestampFormatter = new DateTimeFormatterBuilder()
// parse timestamp value in seconds
.appendValue(ChronoField.INSTANT_SECONDS)
// create formatter
.toFormatter();
另一个细节是DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date/time
.appendOptional(datetimeFormatter)
// timestamp
.appendOptional(timestampFormatter)
// use JVM default timezone
.toFormatter().withZone(ZoneId.systemDefault());
方法,用于设置格式化程序使用的时区。这是因为unix时间戳表示自unix时期以来经过的时间计数,值1520877600可以表示不同的日期和时间,具体取决于您所在的时区。
我正在使用JVM默认时区(withZone
),但您可以根据需要选择它。例如:如果我使用ZoneId.systemDefault()
,时间戳将转换为纽约时区。使用不同的时区会影响年份和月份的值,特别是如果该值对应于该月的第一天或最后一天(如果我没有设置时区,则解析将因时间戳而失败,因为它需要一个时区将时间戳“翻译”为日期/时间。
无论如何,正如您想要的年份和月份值,最好的选择是直接解析为java.time.YearMonth
,而{{3}}又可用于获取年份和月份的对应ZoneId.of("America/New_York")
值:
int
答案 1 :(得分:1)
val isoFormat = "(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2})\\:(\\d{2})\\:(\\d{2})\\.(\\d+)".r
def getYear(timestamp: Any): Int = timestamp match {
case isoFormat(year, month, day, hour, minute, second, millis) => year.toInt
case l : Long => {
val c = Calendar.getInstance()
c.setTimeInMillis(l)
c.get(Calendar.YEAR)
}
case _ => 2017
}
println(getYear("2018-03-31 14:12:00.231"))
println(getYear(System.currentTimeMillis()))
println(getYear("Foo"))
此示例使用scala的模式匹配语法。让我们从底部开始:
我在上述方法中看到的主要好处是,使用其他日期格式扩展方法非常简单。
答案 2 :(得分:1)
此代码获取您的输入并获得年份。它使用SimpleDateFormat进行转换。
import java.text.SimpleDateFormat
import java.util.{Calendar, Date, GregorianCalendar}
import scala.util.{Failure, Success, Try}
def recognizeTimeStamp(timeStamp: String): Int = {
val myCal = new GregorianCalendar();
timeStamp match {
case "unknown" => -1
case x if x.replaceAll("\\d", "") == "" => {
myCal.setTime(new Date(x.toLong))
myCal.get(Calendar.YEAR)
}
case x =>
val format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S")
Try(format.parse(x)) match {
case Success(t) => {
myCal.setTime(t)
myCal.get(Calendar.YEAR)
}
case Failure(_) => -1
}
}
}
recognizeTimeStamp("2018-04-23 11:12:00.0")
recognizeTimeStamp("1334946600000")
来自我的Scala工作表的答案:
res0: Int = 2018
res1: Int = 2012
答案 3 :(得分:0)
我想出了评论中建议的解决方案。我创建了一个函数def isAllDigits(x: String) = x forall Character.isDigit
并检查字符串是否都是数字。