如何根据最大日期过滤 import AVFoundation
import Foundation
protocol VideoPlayerDelegate {
func downloadedProgress(progress:Double)
func readyToPlay()
func didUpdateProgress(progress:Double)
func didFinishPlayItem()
func didFailPlayToEnd()
}
let videoContext: UnsafeMutableRawPointer? = nil
class VideoPlayer : NSObject {
private var assetPlayer:AVPlayer?
private var playerItem:AVPlayerItem?
private var urlAsset:AVURLAsset?
private var videoOutput:AVPlayerItemVideoOutput?
private var assetDuration:Double = 0
private var playerView:PlayerView?
// Also change values in convenience init
private var autoRepeatPlay:Bool = false
private var autoPlay:Bool = false
var delegate:VideoPlayerDelegate?
var playerRate:Float = 1 {
didSet {
if let player = assetPlayer {
player.rate = playerRate > 0 ? playerRate : 0.0
}
}
}
var volume:Float = 1.0 {
didSet {
if let player = assetPlayer {
player.volume = volume > 0 ? volume : 0.0
}
}
}
// MARK: - Init
convenience init(urlAsset:NSURL, view:PlayerView, startAutoPlay:Bool = false, repeatAfterEnd:Bool = false) {
self.init()
playerView = view
autoPlay = startAutoPlay
autoRepeatPlay = repeatAfterEnd
if let playView = playerView, let playerLayer = playView.layer as? AVPlayerLayer {
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
}
initialSetupWithURL(url: urlAsset)
prepareToPlay()
}
override init() {
super.init()
}
// MARK: - Public
func isPlaying() -> Bool {
if let player = assetPlayer {
return player.rate > 0
} else {
return false
}
}
func seekToPosition(seconds:Float64) {
if let player = assetPlayer {
pause()
if let timeScale = player.currentItem?.asset.duration.timescale {
player.seek(to: CMTimeMakeWithSeconds(seconds, preferredTimescale: timeScale), completionHandler: { (complete) in
self.play()
})
}
}
}
func pause() {
if let player = assetPlayer {
player.pause()
}
}
func play() {
if let player = assetPlayer {
if (player.currentItem?.status == .readyToPlay) {
player.play()
player.rate = playerRate
}
}
}
func cleanUp() {
if let item = playerItem {
item.removeObserver(self, forKeyPath: "status")
item.removeObserver(self, forKeyPath: "loadedTimeRanges")
}
NotificationCenter.default.removeObserver(self)
assetPlayer = nil
playerItem = nil
urlAsset = nil
}
func getSize() -> CGSize? {
guard let track = AVURLAsset(url: urlAsset!.url).tracks(withMediaType: AVMediaType.video).first else { return nil }
let size = track.naturalSize.applying(track.preferredTransform)
return CGSize(width: abs(size.width), height: abs(size.height))
}
// MARK: - Private
private func prepareToPlay() {
let keys = ["tracks"]
if let asset = urlAsset {
asset.loadValuesAsynchronously(forKeys: keys, completionHandler: {
DispatchQueue.main.async {
self.startLoading()
}
})
}
}
private func startLoading(){
var error:NSError?
guard let asset = urlAsset else {return}
let status:AVKeyValueStatus = asset.statusOfValue(forKey: "tracks", error: &error)
if status == AVKeyValueStatus.loaded {
assetDuration = CMTimeGetSeconds(asset.duration)
let videoOutputOptions = [kCVPixelBufferPixelFormatTypeKey as String : Int(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)]
videoOutput = AVPlayerItemVideoOutput(pixelBufferAttributes: videoOutputOptions)
playerItem = AVPlayerItem(asset: asset)
if let item = playerItem {
item.addObserver(self, forKeyPath: "status", options: .initial, context: videoContext)
item.addObserver(self, forKeyPath: "loadedTimeRanges", options: [.new, .old], context: videoContext)
NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidReachEnd), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(didFailedToPlayToEnd), name: NSNotification.Name.AVPlayerItemFailedToPlayToEndTime, object: nil)
if let output = videoOutput {
item.add(output)
item.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithm.varispeed
assetPlayer = AVPlayer(playerItem: item)
if let player = assetPlayer {
player.rate = playerRate
}
addPeriodicalObserver()
if let playView = playerView, let layer = playView.layer as? AVPlayerLayer {
layer.player = assetPlayer
print("player created")
}
}
}
}
}
private func addPeriodicalObserver() {
let timeInterval = CMTimeMake(value: 1, timescale: 1)
if let player = assetPlayer {
player.addPeriodicTimeObserver(forInterval: timeInterval, queue: DispatchQueue.main, using: { (time) in
self.playerDidChangeTime(time: time)
})
}
}
private func playerDidChangeTime(time:CMTime) {
if let player = assetPlayer {
let timeNow = CMTimeGetSeconds(player.currentTime())
let progress = timeNow / assetDuration
delegate?.didUpdateProgress(progress: progress)
}
}
@objc private func playerItemDidReachEnd() {
delegate?.didFinishPlayItem()
if let player = assetPlayer {
player.seek(to: CMTime.zero)
if autoRepeatPlay == true {
play()
}
}
}
@objc private func didFailedToPlayToEnd() {
delegate?.didFailPlayToEnd()
}
private func playerDidChangeStatus(status:AVPlayer.Status) {
if status == .failed {
print("Failed to load video")
} else if status == .readyToPlay, let player = assetPlayer {
volume = player.volume
delegate?.readyToPlay()
if autoPlay == true && player.rate == 0.0 {
play()
} else {
pause()
}
}
}
private func moviewPlayerLoadedTimeRangeDidUpdated(ranges:Array<NSValue>) {
var maximum:TimeInterval = 0
for value in ranges {
let range:CMTimeRange = value.timeRangeValue
let currentLoadedTimeRange = CMTimeGetSeconds(range.start) + CMTimeGetSeconds(range.duration)
if currentLoadedTimeRange > maximum {
maximum = currentLoadedTimeRange
}
}
let progress:Double = assetDuration == 0 ? 0.0 : Double(maximum) / assetDuration
delegate?.downloadedProgress(progress: progress)
}
deinit {
cleanUp()
}
private func initialSetupWithURL(url:NSURL) {
let options = [AVURLAssetPreferPreciseDurationAndTimingKey : true]
urlAsset = AVURLAsset(url: url as URL, options: options)
}
// MARK: - Observations
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if context == videoContext {
if let key = keyPath {
if key == "status", let player = assetPlayer {
playerDidChangeStatus(status: player.status)
} else if key == "loadedTimeRanges", let item = playerItem {
moviewPlayerLoadedTimeRangeDidUpdated(ranges: item.loadedTimeRanges)
}
}
}
}
}
[This is how the app looks like][1]
[1]: https://i.stack.imgur.com/DTZkT.jpg
结果。
这是我的代码..
BatchStage
这里是模型类
BatchStage<TestModel> testModel = value.map(model -> JsonUtil.mapFrom(model.getObject_value()))
.map(json -> new TestModel(json.get("id"), json.get("json_obs")));
在控制台中,我目前正在获取此输出
public class TestModel implements Serializable {
private Object key;
private Object value;
//getters and setter
// HashCode and equals method
}
现在我只想在值对象中保留最大日期映射
示例:-
TestModel [key=0001, value=[{date=09/03/2021}, {date=10/03/2021}]]
TestModel[key=0002, value=[{date=09/03/2021}, {date=11/03/2021}]]
任何建议都会有所帮助。
答案 0 :(得分:0)
您需要做的就是编写一个函数,该函数需要获取日期列表中的最大日期。
而且我想我需要知道“日期”的类型... 如果是“java.util.Date”的类型,函数可以是这样的:
public static Date getMaxDate(List<Date> dates) {
if (dates.size() == 0) {
throw new RuntimeException("No date value in list...");
}
Date max = dates.get(0);
for (Date date : dates) {
//use the implemented compareTo() function
if (max.compareTo(date) < 0) {
max = date;
}
}
return max;
}
如果它是“java.time.LocalDate”的类型,函数可以是这样的:
public static LocalDate getMaxLocalDate(List<LocalDate> dates) {
if (dates.size() == 0) {
throw new RuntimeException("No date value in list...");
}
LocalDate max = dates.get(0);
for (LocalDate date : dates) {
//use isBefore function
if (max.isBefore(date)) {
max = date;
}
}
return max;
}
如果是你自己的类型,定义如下:
public class MyDate {
public int year;
public int month;
public int day;
public MyDate() {
}
public MyDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
@Override
public String toString() {
return "MyDate{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}
}
那么函数可以是这样的:
public static MyDate getMaxMyDate(List<MyDate> dates) {
if (dates.size() == 0) {
throw new RuntimeException("No date value in list...");
}
MyDate max = dates.get(0);
LocalDate maxLocalDate = LocalDate.of(max.year, max.month, max.day);
for (MyDate date : dates) {
//convert to LocalDate to compare
LocalDate currentLocalDate = LocalDate.of(date.year, date.month, date.day);
if (maxLocalDate.isBefore(currentLocalDate)) {
max = date;
maxLocalDate = LocalDate.of(max.year, max.month, max.day);
}
}
return max;
}
而且好像需要以列表的形式获取结果,可以使用List.of(max)
来获取列表结果。