代码之家  ›  专栏  ›  技术社区  ›  ACP

Java发现当前时间在本地日期时间映射之间

  •  0
  • ACP  · 技术社区  · 2 年前

    目前,我有一个 地图 包含以下条目:

    Map<LocalDateTime, Integer> resultMap = new HashMap<LocalDateTime, Integer>();
     //Put localdatetime and 30mins split indicator
    
      for(Map.Entry<LocalDateTime, Integer> entry: resultMap.entrySet()) {
          System.out.println(entry.getKey() + " : " + entry.getValue());
      }
    
      2022-03-29T00:30 : 1
      2022-03-29T01:00 : 2
      2022-03-29T01:30 : 3
      2022-03-29T02:00 : 4
      2022-03-29T02:30 : 5
      2022-03-29T03:00 : 6
      2022-03-29T03:30 : 7
      .
      .
      .
      2022-03-29T23:30 : 47
      2022-03-30T00:00 : 48
    

    如何发现当前 LocalDateTime 落在时代之间?

    例如,如果当前时间为 2022-03-29T01:27 需要得到值 3 .

    我能够用一个 迭代器 .还有其他有效的方法吗?

    Iterator keyIterator = resultMap.entrySet().iterator(); 
      Map.Entry<LocalDateTime, Integer> perviousEntry = new AbstractMap.SimpleEntry<LocalDateTime, Integer>(null, 0); 
      while(keyIterator.hasNext()) {
              Map.Entry<LocalDateTime, Integer> NextEntry = 
                   (Entry<LocalDateTime, Integer>) keyIterator.next();
              if(null != perviousEntry.getKey()) {
                  if(LocalDateTime.now().isBefore(NextEntry.getKey()) && LocalDateTime.now().isAfter(perviousEntry.getKey())){
                      System.out.println(NextEntry.getKey() + " Value : " + NextEntry.getValue());
                  }
              }
              perviousEntry = NextEntry; 
      }
    
    0 回复  |  直到 2 年前
        1
  •  2
  •   Alexander Ivanchenko    2 年前

    您可以在中检索值 O(对数n) 时间利用a TreeMap .

    找出哪一个 日期时间 对象是最接近给定的,我们需要比较两者 钥匙 :

    • lo -通过以下方式获得 floorKey() ( <= 对于给定 日期时间 );
    • hi -通过以下方式获得 ceilingKey() ( >= 对于给定 日期时间 ).

    要比较 你好 我们可以利用 Duration 类,它模拟了时间的数量。其静态方法 between() 允许获得a 持续时间 表示两者之间间隔的对象 世俗的 物体。

    下面是一个完整的例子,说明如何实现:

    public class DataTimeStorage {
        private final NavigableMap<LocalDateTime, Integer> storage = new TreeMap<>();
    
        public int getClosest(LocalDateTime dateTime) {
            LocalDateTime lo = storage.floorKey(dateTime);
            LocalDateTime hi = storage.ceilingKey(dateTime);
    
            if (lo == null && hi == null) throw new IllegalArgumentException();
            if (lo == null) return storage.get(hi);
            if (hi == null) return storage.get(lo);
    
            return diffInMillis(lo, dateTime) < diffInMillis(dateTime, hi) ?
                    storage.get(lo) : storage.get(hi);
        }
    
        public long diffInMillis(LocalDateTime dateTime1, LocalDateTime dateTime2) {
            return Duration.between(dateTime1, dateTime2).toMillis();
        }
    
        public void addItemsForDay(LocalDate day) {
            int count = 0;
            for (LocalDateTime i = day.atTime(0, 0);
                 i.toLocalDate().equals(day);
                 i = i.plusMinutes(30))
                storage.put(i, count++);
        }
    
        @Override
        public String toString() {
            return storage.toString();
        }
    }
    

    main() -demo

    public static void main(String[] args) {
        DataTimeStorage storage = new DataTimeStorage();
    
        storage.addItemsForDay(LocalDate.of(2022,03,29));
        System.out.println(storage.getClosest(
                LocalDateTime.of(2022,03,29,01,27)));
    }
    

    输出

    3
    
        2
  •  1
  •   mlogario    2 年前

    第一个想法: 如果你知道地图上的所有时间值都是00分钟或30分钟 您可以尝试处理地图中存在的当前TimeRoundedToTheNext00或30分钟值。

    例如:(伪代码,因为我不熟悉LocalDateTime)

    LocalDateTime currentTimeRoundedToTheNext00or30min = currentTime;
    if (0 < currentTime.minutes < 30) {
        currentTimeRoundedToTheNext00or30min.setMinutes(30);
    } else {
        currentTimeRoundedToTheNext00or30min.setMinutes(0);
        currentTimeRoundedToTheNext00or30min.addHour(1);
    }
    int result = yourMap.get(currentTimeRoundedToTheNext00or30min);
    

    第二个想法: 如果对地图中用作关键字的时间值进行排序,您的需求也可以被视为“找到地图中大于当前时间的第一个关键字”。通过遍历映射键,将键与currentTime进行比较,并在一个键大于测试的currentTime值时立即退出循环,您可以解决这个问题

    第三个想法:即使不使用地图,也有一种简单的方法可以根据currentTime的小时和分钟值找到期望值。(也是伪代码,因为我不确定使用LocalDateTime函数的语法)

    LocalDateTime currentTime = LocalDateTime.now();
    Integer result = currentTime.getHours() * 2;
    if (0 < currentTime.getMinutes() <= 30) {
        result += 1;
    } else {
        result += 2;
    }
    

    这可以被视为“计算自一天开始以来已经开始的30分钟分段的数量”

        3
  •  1
  •   Anton Balaniuc    2 年前

    查找当前LocalDateTime是否介于两个时间之间 可以使用
    LocalDateTime::isBefore 随着 Duration::between 作为第一步,我们可以找出在当前时间之前发生的所有日期,在这些日期中,我们可以找到在过去15秒内(或任何其他有意义的时间段)发生的日期。

    类似的东西

    resultMap.entrySet().stream()
    .filter( entry -> { 
      val now = LocalDateTime.now(); 
       return (entry.getKey() == now) || entry.getKey().isBefore(now) && 
              Duration.between(entry.getKey(),now()).toSeconds() == 15)
    )
    .forEach( entry -> System.out.println(entry.getKey() + " : " + entry.getValue());
    
    
        4
  •  1
  •   VGR    2 年前

    你说得对 NavigableMap 这是一个很好的方法:

    NavigableMap<LocalDateTime, Integer> sorted = new TreeMap<>(resultMap);
    Map.Entry<LocalDateTime, Integer> next = sorted.ceilingEntry(targetTime);
    
    OptionalInt match;
    if (next != null) {
        match = OptionalInt.of(next.getValue());
    } else {
        match = OptionalInt.empty();
    }
    

    我不确定这是否是你想要的确切逻辑,但你可以研究javadoc ceilingEntry , floorEntry , higherEntry lowerEntry 然后选择适合你需要的。