【问题标题】:Does anyone know of a library that will manipulate data based on time intervals?有谁知道将根据时间间隔操作数据的库?
【发布时间】:2011-07-30 21:50:43
【问题描述】:

有人知道可以根据时间间隔操作/组织数据的库吗?

例如:

  • 我有一个按日期/时间映射到对象的数据集合[可以是任何东西,不相关数据的列表、字符串、数字等]
  • 我希望 Collection 足够通用,以便它可以处理区间搜索、组织、合并、交叉点、差异和区间变化 [即集合会将 15 分钟的间隔重新组织为 1 天的间隔]

我正在考虑写其中一个,但我不想重新发明轮子。

另外,最后一个规定是我希望它使用 Java。

例如:

您有以下数据:

  • 1/1/11 1:01 - “Bob 进入房间”
  • 1/1/11 12:01 - “杰瑞进入房间”
  • 1/1/11 1:31 - “Sally 进入房间”
  • 1/1/11 1:51 - “豪尔赫进入房间”
  • 1/1/11 2:01 - “呆伯特进入房间”
  • 1/2/11 1:01 - “Bob 进入房间”
  • 1/3/11 12:01 - “杰瑞进入房间”
  • 1/2/11 1:31 - “Sally 进入房间”
  • 1/2/11 1:51 - “Jorge 进入房间”

此处所述的所有条目 [作为 2 值数据] 将进入集合 [即]:add(Date, object) 但是在初始化时将设置间隔。 [IE。 15分钟] 因此,如果间隔为 15 分钟 [并查询特定时间。它会产生:

  • 1/1/11 12:00-12:15
    • “杰瑞进了房间”
  • 2011 年 1 月 1 日 1:00-1:15
    - “鲍勃进了房间”
  • 1/1/11 1:15-1:30
  • 2011 年 1 月 1 日 1:30-1:45

    • 1/1/11 1:31 - “莎莉进入房间” ....

    如果您尝试查询 1/1/11 12:09,您将获得 1/1/11 12:00-12:15 的结果。 是的,我知道有一些极端情况,但这是一个例子。

【问题讨论】:

  • 很难理解你在问什么。编写几个测试用例来展示它应该如何工作怎么样?
  • 修改间隔不会有问题吗?我正在考虑扩展哈希图,根据间隔制作哈希,但是当间隔改变时会失败。 q

标签: java time recommendation-engine


【解决方案1】:

这是 TreeMap 包装器的草图,它基本上可以按照您的示例显示:

public class CalendarMap<V> {

    private TreeMap<Calendar, V> map = new TreeMap<Calendar, V>();

    public void put(Calendar d, V v){
        map.put(d, v);
    }

    public void query(Calendar d, int intervalUnit, int intervalValue){
         DateFormat df = new SimpleDateFormat("MMM dd, yyyy");
         DateFormat tf = new SimpleDateFormat("HH:mm");

        // snap closest prior unit
        d.set(intervalUnit, (d.get(intervalUnit) / intervalValue)* intervalValue);
        Calendar next = new GregorianCalendar();
        next.setTime(d.getTime());
        next.add(intervalUnit, intervalValue);

        Calendar lastHit = null; // last hit

        while(d.before(map.lastKey())){
            SortedMap<Calendar, V> hits = map.subMap(d, true, next, false);
            if(!hits.isEmpty()){
                if(lastHit != null){
                    System.out.println(df.format(lastHit.getTime()) + " " + tf.format(lastHit.getTime()) + " - " + 
                            df.format(d.getTime()) + " " + tf.format(d.getTime()) + ": N/A");
                    lastHit = null;
                }
                System.out.println(df.format(d.getTime()) + " " + tf.format(d.getTime()) + "-" + tf.format(next.getTime()) + ":");
                for(Entry<Calendar, V> entry : hits.entrySet()){
                    System.out.println("  " + tf.format(entry.getKey().getTime()) + " - " + entry.getValue());
                }
            }else if(lastHit == null){
                lastHit = new GregorianCalendar();
                lastHit.setTime(d.getTime());
            }
            d.add(intervalUnit, intervalValue);
            next.add(intervalUnit, intervalValue);
        }
    }

    public static void main(String[] args){
        CalendarMap<String> map = new CalendarMap<String>();
        map.put(new GregorianCalendar(2011, 1, 1, 13, 1), "Bob entered the room");
        map.put(new GregorianCalendar(2011, 1, 1, 12, 1), "Jerry entered the room");
        map.put(new GregorianCalendar(2011, 1, 1, 13, 31), "Sally entered the room");
        map.put(new GregorianCalendar(2011, 1, 1, 14, 1), "Dilbert entered the room");
        map.put(new GregorianCalendar(2011, 1, 2, 13, 1), "Bob entered the room");
        map.put(new GregorianCalendar(2011, 1, 3, 12, 1), "Jerry entered the room");
        map.put(new GregorianCalendar(2011, 1, 2, 13, 31), "Sally entered the room");
        map.put(new GregorianCalendar(2011, 1, 2, 13, 51), "Jorge entered the room");

        map.query(new GregorianCalendar(2011, 1, 1, 12, 9), Calendar.MINUTE, 15);
    }

}

这会产生:

2011年2月1日12:00-12:15: 12:01 - 杰瑞进入房间 2011 年 2 月 1 日 12:15 - 2011 年 2 月 1 日 13:00:不适用 2011年2月1日13:00-13:15: 13:01 - Bob 进入房间 2011 年 2 月 1 日 13:15 - 2011 年 2 月 1 日 13:30:不适用 2011年2月1日13:30-13:45: 13:31 - 莎莉进入房间 2011 年 2 月 1 日 13:45 - 2011 年 2 月 1 日 14:00:不适用 2011年2月1日14:00-14:15: 14:01 - 呆伯特进入房间 2011 年 2 月 1 日 14:15 - 2011 年 2 月 2 日 13:00:不适用 2011年2月2日13:00-13:15: 13:01 - Bob 进入房间 2011 年 2 月 2 日 13:15 - 2011 年 2 月 2 日 13:30:不适用 2011年2月2日13:30-13:45: 13:31 - 莎莉进入房间 2011年2月2日13:45-14:00: 13:51 - 豪尔赫进入房间 2011 年 2 月 2 日 14:00 - 2011 年 2 月 3 日 12:00:不适用 2011年2月3日12:00-12:15: 12:01 - 杰瑞进入房间

假设你执行这个:

map.query(new GregorianCalendar(2011, 1, 1, 12, 9), Calendar.HOUR, 1);

那么输出是:

2011年2月1日12:09-13:09: 13:01 - Bob 进入房间 2011年2月1日13:09-14:09: 13:31 - 莎莉进入房间 14:01 - 呆伯特进入房间 2011 年 2 月 1 日 14:09 - 2011 年 2 月 2 日 12:09:不适用 2011年2月2日12:09-13:09: 13:01 - Bob 进入房间 2011年2月2日13:09-14:09: 13:31 - 莎莉进入房间 13:51 - 豪尔赫进入房间 2011 年 2 月 2 日 14:09 - 2011 年 2 月 3 日 11:09:不适用 2011年2月3日11:09-12:09: 12:01 - 杰瑞进入房间

【讨论】:

  • 那么区间值单位是一个数值,代表日、月、时、秒等?间隔值是 15 [for 15s]?这看起来接近我正在寻找的东西。另外,自从您使用日历以来,我会投票更多:P 但我只能这样做一次。如果我要手动执行,我的方法会更长一些。谢谢!我学到了一些东西。 :)
  • @monsky: Calendar.MINUTE 定义了一个int,意思是“分钟”,是intervalUnit 的内容和许多函数的参数。 intervalValue 是单位数,因此对于值为 15Calendar.MINUTE,这意味着“15 分钟。我修复了代码中的一些错误,并为您提供了与上面的实际匹配的输出。
  • @monsky:另外,查询函数现在采用间隔,因此您可以根据需要查询不同的间隔(请参阅更新的示例输出)
  • @monsky:我对此的最后一次编辑...更新以改进死间隔处理,当有几个间隔没有我折叠它们时。
  • 谢谢!!!如果我们在酒吧见面,我会请你喝啤酒。真是太棒了!我没想到这么多。
猜你喜欢
  • 2016-11-19
  • 2022-01-10
  • 2021-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-13
  • 2014-11-20
  • 2018-04-20
相关资源
最近更新 更多