zoukankan      html  css  js  c++  java
  • time.c 的Java实现(从timestamp计算年月日时分秒等数值)

    time.c的Java实现

    public class GMT {
        public static final int EPOCH_YEAR = 1970;
        public static final int[][] MONTH_DAYS = {
                {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
                {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
        };
        public static final long MSECS_DAY = 1000*3600*24L;
    
        private long timestamp;
        private int mil;
        private int sec;
        private int min;
        private int hour;
        private int wday;
        private int mday;
        private int yday;
        private int mon;
        private int year;
    
        public GMT(long timestamp, long shift) {
            this.timestamp = timestamp + shift;
            long dayclock = (this.timestamp % MSECS_DAY) / 1000L;
            long dayno = this.timestamp / MSECS_DAY;
    
            mil = (int) (this.timestamp % 1000L);
            sec = (int) (dayclock % 60);
            min = (int) ((dayclock % 3600) / 60);
            hour = (int) (dayclock / 3600);
            wday = (int) ((dayno + 4) % 7);
            while (dayno >= yearDays(EPOCH_YEAR + year)) {
                dayno -= yearDays(EPOCH_YEAR + year);
                year++;
            }
            year = EPOCH_YEAR + year;
            yday = (int)dayno;
            int[] monthDays = leapYear(year) ? MONTH_DAYS[1] : MONTH_DAYS[0];
            while (dayno >= monthDays[mon]) {
                dayno -= monthDays[mon];
                mon++;
            }
            mon++;
            mday = (int)dayno + 1;
        }
    
        public long toLongInteger() {
            return year     * 10000000000000L
                    + mon   * 100000000000L
                    + mday  * 1000000000L
                    + hour  * 10000000L
                    + min   * 100000L
                    + sec   * 1000L
                    + mil;
        }
    
        private static int yearDays(int year) {
            return leapYear(year) ? 366 : 365;
        }
    
        private static boolean leapYear(int year) {
            return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
        }
    
        public int getMil() { return mil; }
        public void setMil(int mil) { this.mil = mil; }
        public int getSec() { return sec; }
        public void setSec(int sec) { this.sec = sec; }
        public int getMin() { return min; }
        public void setMin(int min) { this.min = min; }
        public int getHour() { return hour; }
        public void setHour(int hour) { this.hour = hour; }
        public int getWday() { return wday; }
        public void setWday(int wday) { this.wday = wday; }
        public int getMday() { return mday; }
        public void setMday(int mday) { this.mday = mday; }
        public int getYday() { return yday; }
        public void setYday(int yday) { this.yday = yday; }
        public int getMon() { return mon; }
        public void setMon(int mon) { this.mon = mon; }
        public int getYear() { return year; }
        public void setYear(int year) { this.year = year; }
    
        public static void main(String[] args) {
            long start = System.currentTimeMillis();
            int total = 500000;
            for (int i = 0; i < total; i ++) {
                GMT gmt = new GMT(System.currentTimeMillis(), 1000L*3600*8);
                System.out.println(gmt.toLongInteger());
            }
            long duration = System.currentTimeMillis() - start;
            System.out.println("Total: " + duration + "ms, " + total/duration + "/ms");
        }
    }

    可以作为Snowflake ID generator的前缀生成器, 好处是易于业务手工识别, 缺点是速度较慢, 与直接使用二进制的机制差一个数量级(sf默认实现是20k/ms, 这个只有2k/ms).

    在带I/O的情况下, 能达到150/ms的生成速度, 比使用SimpleDateFormat的效率高很多, 还是可以使用的, 如果使用SimpleDateFormat的话, 只有30/ms的速度.

    Update:

    用这个改造出来的...TimeflakeId是类似于这样的

    public class TimeflakeId {
        private final static int SEQUENCE_MASK = 999;
        private final RecyclableAtomicInteger atomic = new RecyclableAtomicInteger();
        private long lastTimestamp = -1L;
        private long lastTsFormatted = -1L;
    
        public long nextId() {
            long timestamp = millisecond();
            if (timestamp < lastTimestamp) {
                throw new IllegalArgumentException(
                        String.format("Wait for %d milliseconds", lastTimestamp - timestamp));
            }
    
            if (lastTimestamp == timestamp) {
                int sequence = atomic.incrementAndRecycle(SEQUENCE_MASK);
                if (sequence == 0) {
                    timestamp = waitTilNextMillis(lastTimestamp);
                    lastTimestamp = timestamp;
                    lastTsFormatted = getFormattedTimestamp();
                }
                return lastTsFormatted * 1000 + sequence;
            } else {
                atomic.set(0);
                lastTimestamp = timestamp;
                lastTsFormatted = getFormattedTimestamp();
                return lastTsFormatted * 1000;
            }
        }
    
        private long waitTilNextMillis(final long lastTimestamp) {
            long timestamp;
            for (;;) {
                timestamp = this.millisecond();
                if (timestamp > lastTimestamp) {
                    return timestamp;
                }
            }
        }
    
        private long millisecond() {
            return System.currentTimeMillis();
        }
    
        public static final int EPOCH_YEAR = 1970;
        public static final long[][] MONTH_DAYS = {
                {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
                {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
        };
        public static final long MSECS_DAY = 1000*3600*24L;
    
        private long getFormattedTimestamp() {
            long ts = lastTimestamp + 1000L*3600*8;
            long dayclock = (ts % MSECS_DAY) / 1000L;
            long dayno = ts / MSECS_DAY;
    
            long mil = ts % 1000L;
            long sec = dayclock % 60;
            long min = (dayclock % 3600) / 60;
            long hour = dayclock / 3600;
            long year = 0;
            while (dayno >= yearDays(EPOCH_YEAR + year)) {
                dayno -= yearDays(EPOCH_YEAR + year);
                year++;
            }
            long[] monthDays = leapYear(EPOCH_YEAR + year) ? MONTH_DAYS[1] : MONTH_DAYS[0];
            int mon = 0;
            while (dayno >= monthDays[mon]) {
                dayno -= monthDays[mon];
                mon++;
            }
            mon++;
            long mday = dayno + 1;
    
            return ((year > 30)? year - 30 : year + 70)     * 10000000000000L
                    + mon   * 100000000000L
                    + mday  * 1000000000L
                    + hour  * 10000000L
                    + min   * 100000L
                    + sec   * 1000L
                    + mil;
        }
    
        private static int yearDays(long year) {
            return leapYear(year) ? 366 : 365;
        }
    
        private static boolean leapYear(long year) {
            return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
        }
    
        public static void main(String[] args) {
            TimeflakeId worker = new TimeflakeId();
            long start = System.currentTimeMillis();
            int total = 50000;
            for (int i = 0; i < total; i ++) {
                //System.out.println(worker.nextId());
                worker.nextId();
            }
            long duration = System.currentTimeMillis() - start;
            System.out.println("Total: " + duration + "ms, " + total/duration + "/ms");
        }
    }

    RecyclableAtomicInteger 的实现

    public class RecyclableAtomicInteger extends AtomicInteger
    {
        /**
         * Atomically increments by one the current value, or return
         * to zero if the value exceeds threshold
         *
         * @return the updated value
         */
        public final int incrementAndRecycle(int threshold) {
            for (;;) {
                int current = get();
                int next = (current + 1) % threshold;
                if (compareAndSet(current, next))
                    return next;
            }
        }
    }
  • 相关阅读:
    记处理PostgreSQL连接太多的问题
    记服务器迁移上云出现故障
    PostgreSQL-迁移同步序列
    为什么你的pgbouncer连接这么慢
    TS基础知识储备
    前端实在好用的工具类库 【后续持续添加若有请留言添加积累供大家使用】
    Vue 3 + Typescript + Vite2.0 搭建移动端 代码规范以及注意的点
    flutter2.0 环境搭建(window环境下Mac自行查看官网即可)
    vite2.0+vue3+ts前端最新热门技术项目搭建
    React官方状态管理库—— Recoil
  • 原文地址:https://www.cnblogs.com/milton/p/5548231.html
Copyright © 2011-2022 走看看