精华内容
下载资源
问答
  • 计算属性computed : ... 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed 如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属

    计算属性computed :

    • 支持缓存,只有依赖数据发生改变,才会重新进行计算;
    • 不支持异步,当computed内有异步操作时无效,无法监听数据的变化;
    • computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值
    • 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
    • 如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。

    监听属性watch :

    • 不支持缓存,数据变,直接会触发相应的操作;
    • 支持异步;
    • 监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
    • 当一个属性发生变化时,需要执行对应的操作,一对多;
    • 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数,
        immediate:组件加载立即触发回调函数执行,
        deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到。
        在这里插入图片描述
    展开全文
  • 计算属性 vue的模板里可以使用表达式,但是它的设计初衷是用于简单计算,在模板中放入太多逻辑会让模板过重且难以维护。例如: <div id="example"> {{ message.split('').reverse().join('') }} </div>...

    计算属性

    vue的模板里可以使用表达式,但是它的设计初衷是用于简单计算,在模板中放入太多逻辑会让模板过重且难以维护。例如:

    <div id="example">
      {{ message.split('').reverse().join('') }}
    </div>

    这里很难一眼看出是要显示什么,而且要多次使用的话也很麻烦,因此对于复杂逻辑应使用计算属性



    错误示例

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!-- 开发环境版本,包含了有帮助的命令行警告 -->
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <p>{{ message.split('').reverse().join('') }}</p>
    </div>
    <script>
        let app = new Vue({
            el:"#app",  //关联dom对象
            data:{
                message:'I have a dream'   //模板使用的数据
            },
        })
    
    </script>
    </body>
    </html>
    



    正确写法

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!-- 开发环境版本,包含了有帮助的命令行警告 -->
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <!--   直接使用方法名就行,不用加括号   -->
        <p>{{ reversedMessage }}</p>
    </div>
    <script>
        //建议vue的变量命与作用的标签id一致
        let app = new Vue({
            el: "#app",  //关联dom对象
            data: {
                message: 'I have a dream'   //模板使用的数据
            },
            //定义计算属性
            computed: {
                // 在computed里定义方法,使用的时候直接写方法名
                reversedMessage: function () {
                    // `this` 指向 app 实例,data里面的数据可以直接获取到htis.message
                    return this.message.split('').reverse().join('')
                }
            }
        })
    
    </script>
    </body>
    </html>
    


    计算属性与方法的不同

    上述例子中也可以通过调用方法来达到同样的目的

    在组件中定义方法

    // 在组件中
    methods: {
      reversedMessage: function () {
        return this.message.split('').reverse().join('')
      }
    }

    调用方法

    <p>Reversed message: "{{ reversedMessage() }}"</p>
    

    就得到的结果而言,两种方式是完全一致的。但是不同的是,计算属性是基于它们的依赖进行缓存的,也就是说,计算属性只有在它的相关依赖发生改变时才会重新求值,对于上述的例子,只要message不发生改变,多次访问reversedMessage计算属性会立即返回结果而不必再次执行函数



    下面我们来验证这个结论

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="js/vue.js"></script>
    </head>
    <body>
    
    
    <div id="app">
        <p>使用计算属性</p>
        <p>{{reversedMessage}}</p>
    
        <hr>
    
    
        <p>使用方法</p>
        <p>{{reversedMessageMethod()}}</p>
    
    </div>
    
    <script>
        //建议vue的变量命与作用的标签id一致
        let app = new Vue({
            el:"#app",
            data:{
                message:"I have a dream",
            },
            //计算属性
            computed:{
                reversedMessage:function () {
                    console.log("in computed");
                    return this.message.split("").reverse().join("")
                }
            },
    
            methods:{
                reversedMessageMethod:function () {
                    console.log("in method");
                    return this.message.split("").reverse().join("")
                }
            }
    
        })
    </script>
    
    
    </body>
    </html>



    打开html,右键检查-console

    1542801-20190427104652371-1229020291.png


    小结

    • 模板内表达式包含复杂逻辑时,应使用计算属性
    • 只要计算属性使用的数据不发生变化,计算属性就不会执行,而是直接使用缓存

    转载于:https://www.cnblogs.com/zzliu/p/10778008.html

    展开全文
  • 此篇主要手写 Vue2.0 源码-计算属性 适用人群: 1.想要深入理解 vue 源码更好的进行日常业务开发 2.想要在简历写上精通 vue 框架源码(再也不怕面试官的连环夺问 哈哈) 3.没时间去看官方源码或者初看源码觉得...

    前言

    此篇主要手写 Vue2.0 源码-计算属性

    适用人群:

    1.想要深入理解 vue 源码更好的进行日常业务开发

    2.想要在简历写上精通 vue 框架源码(再也不怕面试官的连环夺命问 哈哈)

    3.没时间去看官方源码或者初看源码觉得难以理解的同学

    正文

    <script>
      // Vue实例化
      let vm = new Vue({
        el: "#app",
        data() {
          return {
            aa: 1,
            bb: 2,
            cc: 3,
          };
        },
        // render(h) {
        //   return h('div',{id:'a'},'hello')
        // },
        template: `<div id="a">hello 这是我自己写的Vue{{computedName}}{{cc}}</div>`,
        computed: {
          computedName() {
            return this.aa + this.bb;
          },
        },
      });
      // 当我们每一次改变数据的时候  渲染watcher都会执行一次 这个是影响性能的
      setTimeout(() => {
        vm.cc = 4;
      }, 2000);
      console.log(vm);
    </script>
    

    上述例子 就是计算属性的基础用法 我们在两秒之后改变了模板里面的 cc 但是计算属性依赖的 aa 和 bb 都没变化 所以计算属性不会重新计算 还是保留的上次计算结果

    1.计算属性的初始化

    // src/state.js
    
    function initComputed(vm) {
      const computed = vm.$options.computed;
    
      const watchers = (vm._computedWatchers = {}); //用来存放计算watcher
    
      for (let k in computed) {
        const userDef = computed[k]; //获取用户定义的计算属性
        const getter = typeof userDef === "function" ? userDef : userDef.get; //创建计算属性watcher使用
        // 创建计算watcher  lazy设置为true
        watchers[k] = new Watcher(vm, getter, () => {}, { lazy: true });
        defineComputed(vm, k, userDef);
      }
    }
    

    计算属性可以写成一个函数也可以写成一个对象 对象的形式 get 属性就代表的是计算属性依赖的值 set 代表修改计算属性的依赖项的值 我们主要关心 get 属性 然后类似侦听属性 我们把 lazy:true 传给构造函数 Watcher 用来创建计算属性 Watcher 那么 defineComputed 是什么意思呢

    思考? 计算属性是可以缓存计算结果的 我们应该怎么做?

    2.对计算属性进行属性劫持

    //  src/state.js
    
    // 定义普通对象用来劫持计算属性
    const sharedPropertyDefinition = {
      enumerable: true,
      configurable: true,
      get: () => {},
      set: () => {},
    };
    
    // 重新定义计算属性  对get和set劫持
    function defineComputed(target, key, userDef) {
      if (typeof userDef === "function") {
        // 如果是一个函数  需要手动赋值到get上
        sharedPropertyDefinition.get = createComputedGetter(key);
      } else {
        sharedPropertyDefinition.get = createComputedGetter(key);
        sharedPropertyDefinition.set = userDef.set;
      }
      //   利用Object.defineProperty来对计算属性的get和set进行劫持
      Object.defineProperty(target, key, sharedPropertyDefinition);
    }
    
    // 重写计算属性的get方法 来判断是否需要进行重新计算
    function createComputedGetter(key) {
      return function () {
        const watcher = this._computedWatchers[key]; //获取对应的计算属性watcher
        if (watcher) {
          if (watcher.dirty) {
            watcher.evaluate(); //计算属性取值的时候 如果是脏的  需要重新求值
          }
          return watcher.value;
        }
      };
    }
    

    defineComputed 方法主要是重新定义计算属性 其实最主要的是劫持 get 方法 也就是计算属性依赖的值 为啥要劫持呢 因为我们需要根据依赖值是否发生变化来判断计算属性是否需要重新计算

    createComputedGetter 方法就是判断计算属性依赖的值是否变化的核心了 我们在计算属性创建的 Watcher 增加 dirty 标志位 如果标志变为 true 代表需要调用 watcher.evaluate 来进行重新计算了

    3.Watcher 改造

    // src/observer/watcher.js
    
    // import { pushTarget, popTarget } from "./dep";
    // import { queueWatcher } from "./scheduler";
    // import {isObject} from '../util/index'
    // // 全局变量id  每次new Watcher都会自增
    // let id = 0;
    
    export default class Watcher {
      constructor(vm, exprOrFn, cb, options) {
        // this.vm = vm;
        // this.exprOrFn = exprOrFn;
        // this.cb = cb; //回调函数 比如在watcher更新之前可以执行beforeUpdate方法
        // this.options = options; //额外的选项 true代表渲染watcher
        // this.id = id++; // watcher的唯一标识
        // this.deps = []; //存放dep的容器
        // this.depsId = new Set(); //用来去重dep
        // this.user = options.user; //标识用户watcher
        this.lazy = options.lazy; //标识计算属性watcher
        this.dirty = this.lazy; //dirty可变  表示计算watcher是否需要重新计算 默认值是true
    
        // 如果表达式是一个函数
        // if (typeof exprOrFn === "function") {
        //   this.getter = exprOrFn;
        // } else {
        //   this.getter = function () {
        //     //用户watcher传过来的可能是一个字符串   类似a.a.a.a.b
        //     let path = exprOrFn.split(".");
        //     let obj = vm;
        //     for (let i = 0; i < path.length; i++) {
        //       obj = obj[path[i]]; //vm.a.a.a.a.b
        //     }
        //     return obj;
        //   };
        // }
        // 非计算属性实例化就会默认调用get方法 进行取值  保留结果 计算属性实例化的时候不会去调用get
        this.value = this.lazy ? undefined : this.get();
      }
      get() {
        pushTarget(this); // 在调用方法之前先把当前watcher实例推到全局Dep.target上
        const res = this.getter.call(this.vm); //计算属性在这里执行用户定义的get函数 访问计算属性的依赖项 从而把自身计算Watcher添加到依赖项dep里面收集起来
        popTarget(); // 在调用方法之后把当前watcher实例从全局Dep.target移除
        return res;
      }
      //   把dep放到deps里面 同时保证同一个dep只被保存到watcher一次  同样的  同一个watcher也只会保存在dep一次
      //   addDep(dep) {
      //     let id = dep.id;
      //     if (!this.depsId.has(id)) {
      //       this.depsId.add(id);
      //       this.deps.push(dep);
      //       //   直接调用dep的addSub方法  把自己--watcher实例添加到dep的subs容器里面
      //       dep.addSub(this);
      //     }
      //   }
      //   这里简单的就执行以下get方法  之后涉及到计算属性就不一样了
      update() {
        // 计算属性依赖的值发生变化 只需要把dirty置为true  下次访问到了重新计算
        if (this.lazy) {
          this.dirty = true;
        } else {
          // 每次watcher进行更新的时候  可以让他们先缓存起来  之后再一起调用
          // 异步队列机制
          queueWatcher(this);
        }
      }
      //   计算属性重新进行计算 并且计算完成把dirty置为false
      evaluate() {
        this.value = this.get();
        this.dirty = false;
      }
      depend() {
        // 计算属性的watcher存储了依赖项的dep
        let i = this.deps.length;
        while (i--) {
          this.deps[i].depend(); //调用依赖项的dep去收集渲染watcher
        }
      }
      //   run() {
      //     const newVal = this.get(); //新值
      //     const oldVal = this.value; //老值
      //     this.value = newVal; //跟着之后  老值就成为了现在的值
      //     if (this.user) {
      //       if(newVal!==oldVal||isObject(newVal)){
      //         this.cb.call(this.vm, newVal, oldVal);
      //       }
      //     } else {
      //       // 渲染watcher
      //       this.cb.call(this.vm);
      //     }
      //   }
    }
    

    我们主要看没被注释的代码 这里主要改造有四点

    1.实例化的时候如果是计算属性 不会去调用 get 方法访问值进行依赖收集

    2.update 方法只是把计算 watcher 的 dirty 标识为 true 只有当下次访问到了计算属性的时候才会重新计算

    3.新增 evaluate 方法专门用于计算属性重新计算

    4.新增 depend 方法 让计算属性的依赖值收集外层 watcher--这个方法非常重要 我们接下来分析

    4.外层 Watcher 的依赖收集

    // src/state.js
    
    function createComputedGetter(key) {
    //   return function () {
    //     const watcher = this._computedWatchers[key]; //获取对应的计算属性watcher
    //     if (watcher) {
    //       if (watcher.dirty) {
    //         watcher.evaluate(); //计算属性取值的时候 如果是脏的  需要重新求值
            if (Dep.target) {
        // 如果Dep还存在target 这个时候一般为渲染watcher 计算属性依赖的数据也需要收集
              watcher.depend()
            }
    //       }
    //       return watcher.value;
    //     }
    //   };
    // }
    
    

    这里就体现了 watcher.depend 方法的重要性了 我们试想一下 当我们计算属性依赖的值发生了改变 这时候 watcher 的 dirty 为 true 下次访问计算属性 他确实也重新计算了 但是 我们从头到尾都没有触发视图更新 也就是数据改变了 视图没有重新渲染

    这是为什么呢?

    因为模板里面只有计算属性 而计算属性的依赖值的 dep 里面只收集了计算 watcher 的依赖 自身变化也只是通知了计算 watcher 调用 update 把 dirty 置为 true 所以我们要想个办法把计算属性的依赖项也添加渲染 watcher 的依赖 让自身变化之后首先通知计算 watcher 进行重新计算 然后通知渲染 watcher 进行视图更新

    怎么做呢?我们来看看下面的代码就清楚了

    // src/observer/dep.js
    
    // 默认Dep.target为null
    Dep.target = null;
    // 栈结构用来存watcher
    const targetStack = [];
    
    export function pushTarget(watcher) {
      targetStack.push(watcher);
      Dep.target = watcher; // Dep.target指向当前watcher
    }
    export function popTarget() {
      targetStack.pop(); // 当前watcher出栈 拿到上一个watcher
      Dep.target = targetStack[targetStack.length - 1];
    }
    

    可见最初设计存放 watcher 的容器就是一个栈结构 因为整个 Vue 生命周期的过程中会存在很多的 watcher 比如渲染 watcher 计算 watcher 侦听 watcher 等 而每个 watcher 在调用了自身的 get 方法前后会分别调用 pushTarget 入栈和 popTarget 出栈 这样子当计算属性重新计算之后就立马会出栈 那么外层的 watcher 就会成为新的 Dep.target 我们使用 watcher.depend 方法让计算属性依赖的值收集一遍外层的渲染 watcher 这样子当计算属性依赖的值改变了既可以重新计算又可以刷新视图

    5.计算属性的思维导图

    小结

    至此 Vue 的 计算属性原理已经完结 和侦听属性还是有很大区别的 计算属性一般用在需要对依赖项进行计算并且可以缓存下来 当依赖项变化会自动执行计算属性的逻辑 一般用在模板里面较多 而侦听属性用法是对某个响应式的值进行观察(也可以观察计算属性的值) 一旦变化之后就可以执行自己定义的方法 大家可以看着思维导图自己动手写一遍核心代码哈 遇到不懂或者有争议的地方欢迎评论留言

    链接:https://pan.baidu.com/s/1_4PIUb-Yl68aTW9Bw95iJA 
    提取码:tnav 

    展开全文
  • 使用Java计算生辰八字五行属性

    千次阅读 2020-03-20 22:43:12
    使用Java算出自己的八字和五行五行八字基本要素天干地支表天干地支对应编号计算公元后某年的干支干支纪月法干支纪日法十二时辰表十二时辰纪日对照表五行干支对照表五行八字Java实现代码 源码地址:...


    源码地址:https://github.com/luguangdong/java-base/blob/master/src/com/luxiu/java/base/wuxing/WuXingApp2.java

    五行八字基本要素

    天干地支表

    子鼠 甲子 丙子 戊子 庚子 壬子
    丑牛 乙丑 丁丑 己丑 辛丑 癸丑
    寅虎 甲寅 丙寅 戊寅 庚寅 壬寅
    卯兔 乙卯 丁卯 己卯 辛卯 癸卯
    辰龙 甲辰 丙辰 戊辰 庚辰 壬辰
    巳蛇 乙巳 丁巳 己巳 辛巳 癸巳
    午马 甲午 丙午 戊午 庚午 壬午
    未羊 乙未 丁未 己未 辛未 癸未
    申猴 甲申 丙申 戊申 庚申 壬申
    酉鸡 乙酉 丁酉 己酉 辛酉 癸酉
    戌狗 甲戌 丙戌 戊戌 庚戌 壬戌
    亥猪 乙亥 丁亥 己亥 辛亥 癸亥
    说明: 天干地支简称干支,干支纪年是我国传统的纪年方法即为天干地支纪年法
    
    • 十天干分别为:甲乙 丙丁 戊己 庚辛 壬癸
    • 十二地支分别为:子丑 寅卯 辰巳 午未 申酉 戌亥
    • 干和支组合后用于纪年,将十天干和十二地支按顺序搭配组合成干支,用于纪年。按此排法,当天干 10 个符号排了六轮与地支 12 个符号排了五轮以后,可构成 60 干支。续排下去又将恢复原状,周而复始,即:“六十年为一个甲子”

    天干地支对应编号

    • 甲子 00,乙丑 01,丙寅 02,丁卯 03,戊辰 04,己巳 05,庚午 06,辛未 07,壬申 08,癸酉 09
    • 甲戌 10,乙亥 11,丙子 12,丁丑 13,戊寅 14,己卯 15,庚辰 16,辛巳 17,壬午 18,癸未 19
    • 甲申 20,乙酉 21,丙戌 22,丁亥 23,戊子 24,己丑 25,庚寅 26,辛卯 27,壬辰 28,癸巳 29
    • 甲午 30,乙未 31,丙申 32,丁酉 33,戊戌 34,己亥 35,庚子 36,辛丑 37,壬寅 38,癸卯 39
    • 甲辰 40,乙巳 41,丙午 42,丁未 43,戊申 44,己酉 45,庚戌 46,辛亥 47,壬子 48,癸丑 49
    • 甲寅 50,乙卯 51,丙辰 52,丁巳 53,戊午 54,己未 55,庚申 56,辛酉 57,壬戌 58,癸亥 59

    计算公元后某年的干支

    假设公元后某年为 X 则先用 X 除以 60 得出余数再减去 4,根据所得结果查表中对应的编号即可算出该年的干支

    比如:2020 除以 60 余 40 减去 4 等于 36,对应干支为 庚子年,当 X 除以 60 的余数小于 4 时,需借干支纪年的一个周期 60 再减 4,例如 1983 除以 60 余数为 3,直接减 4 不够减,加上 60 之后再减 4 等于 59,1983 年为 癸亥年

    干支纪月法

    若遇甲或己的年份 ,正月是丙寅;遇上乙或庚之年,正月为戊寅;遇上丙或辛之年,正月为庚寅;遇上丁或壬之年,正月为壬寅;遇上戊或癸之年,正月为甲寅。依照正月之干支,其余月份按干支推算即可
    
    年份 正月 二月 三月 四月 五月 六月 七月 八月 九月 十月 冬月 腊月
    甲、己 丙寅 丁卯 戊辰 己巳 庚午 辛未 壬申 癸酉 甲戌 乙亥 丙子 丁丑
    乙、庚 戊寅 己卯 庚辰 辛巳 壬午 癸未 甲申 乙酉 丙戌 丁亥 戊子 己丑
    丙、辛 庚寅 辛卯 壬辰 癸巳 甲午 乙未 丙申 丁酉 戊戌 己亥 庚子 辛丑
    丁、壬 壬寅 癸卯 甲辰 乙巳 丙午 丁未 戊申 己酉 庚戌 辛亥 壬子 癸丑
    戊、癸 甲寅 乙卯 丙辰 丁巳 戊午 己未 庚申 辛酉 壬戌 癸亥 甲子 乙丑

    干支纪日法

    从已知日期计算干支纪日的公式为:

    • 天干 = (4 * C + [C / 4] + 5 * y + [y / 4] + [3 * (M + 1) / 5] + d - 3) % 10

    • 地支 = (8 * C + [C / 4] + 5 * y + [y / 4] + [3 * (M + 1) / 5] + d + 7 + i) % 12

        	注意: [] 里的除法取整即可
      

    说明如下:

    • c 为年份前两位,比如 2019 年则 c 为 20
    • y 为年份后两位,比如 2019 年则 y 为 19
    • M 为月份,1 月和 2 月按上一年的 13 月和 14 月来算
    • d 为日数
    • i
      • 奇数月为 0
      • 偶数月为 6

    比如计算 2020 年 2 月 9 日的干支日如下:

    • 天干 = (4 * 20 + 20 / 4 + 5 * 19 + 19 / 4 + 3 * (14 + 1) / 5 + 9 - 3) % 10 = 9 即 壬
    • 地支 = (8 * 20 + 20 / 4 + 5 * 19 + 19 / 4 + 3 * (14 + 1) / 5 + 9 + 7 + 6) % 12 = 7 即 午

    十二时辰表

    时辰 时间
    子时 23 - 01
    丑时 01 - 03
    寅时 03 - 05
    卯时 05 - 07
    辰时 07 - 09
    巳时 09 - 11
    午时 11 - 13
    未时 13 - 15
    申时 15 - 17
    酉时 17 - 19
    戌时 19 - 21
    亥时 21 - 23
    注意: 根据上表可以得出生辰八字的第八个字,比如早上 9 点出生即第八个字为 巳
    

    十二时辰纪日对照表

    想要得到第七个字,需要使用以下对照表;比如 2020 年(庚子) 2 月(戊寅) 9 日(壬午)晚上 23 点(子时),找到 对应的字即下表中的 庚子

    时/日 甲、己 乙、庚 丙、辛 丁、壬 戊、癸
    甲、子 丙 、子 戊、子 庚、子 壬、子
    乙、丑 丁、丑 己、丑 辛、丑 癸、丑
    丙、寅 戊、寅 庚、寅 壬、寅 甲、寅
    丁、卯 己、卯 辛、卯 癸、卯 乙、卯
    戊、辰 庚、辰 壬、辰 甲、辰 丙、辰
    己、巳 辛、巳 癸、巳 乙、巳 丁、巳
    庚、午 壬、午 甲、午 丙、午 戊、午
    辛、未 癸、未 乙、未 丁、未 己、未
    壬、申 甲、申 丙、申 戊、申 庚、申
    癸、酉 乙、酉 丁、酉 己、酉 辛、酉
    甲、戌 丙、戌 戊、戌 庚、戌 壬、戌
    乙、亥 丁、亥 己、亥 辛、亥 癸、亥

    生辰八字 = 年(庚子) + 月(戊寅) + 日(壬午) + 时(庚子)

    五行干支对照表

    五行 天干 地支
    甲、乙 寅、卯
    丙、丁 巳、午
    戊、己 辰、丑、戌、未
    庚、辛 申、酉
    壬、癸 亥、子

    按照上面的生辰八字得出五行(2 个金,3 个水,1 个土,1 个木,1 个火;此子五行不缺)

    庚子 戊寅 壬午 庚子
    金水 土木 水火 金水

    五行八字Java实现代码

    package com.luxiu.java.base.wuxing;
    
    /**
     * <p>
     * Description: 测试八字与五行版本1
     * </p>
     *
     * @author luguangdong
     * @version 1.0
     * @ClassName WuXingApp
     * @date 2020/3/20 9:51
     * @company 
     */
    public class WuXingApp {
        private static final String[] TG = {"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"};
        private static final String[] DZ = {"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};
    
        public static void main(String[] args) {
            // 公元后某年
            int year = 2020;
            // 农历某月
            int nMonth = 1;
            // 阳历某月
            int yMonth = 2;
            // 阳历某日
            int day = 10;
            // 时间
            int time = 15;
    
            // 获取干支年
            String gzYear = getYear(year);
            System.out.println(year + " 年为 \"" + gzYear + "\" 年");
    
            // 获取干支月
            String gzMonth = getMonth(gzYear, nMonth);
            System.out.println(year + " 年农历 " + nMonth + " 月为 \"" + gzMonth + "\" 月");
    
            // 获取干支日
            String gzDay = getDay(year, yMonth, day);
            System.out.println(year + " 年阳历 " + yMonth + " 月 " + day + " 日为 \"" + gzDay + "\" 日");
    
            // 获取干支时
            String gzTime = getTime(gzDay, time);
            System.out.println(year + " 年阳历 " + yMonth + " 月 " + day + " 日 " + time + " 时为 \"" + gzTime + "\" 时");
    
            // 生辰八字
            System.out.println("您的生辰八字为:" + gzYear + gzMonth + gzDay + gzTime);
    
            // 生辰八字算五行
            wuxing(gzYear, gzMonth, gzDay, gzTime);
        }
    
        /**
         * 获取干支年 <br />
         * 根据公元后某年换算出干支年 <br />
         *
         * <p>
         * 说明:假设公元后某年为 X 则先用 X 除以 60 得出余数再减去 4,根据所得结果查表中对应的编号即可算出该年的干支 <br />
         * 如果减 4 不够减则加上 60 之后再减即可
         * </p>
         *
         * @param year {@code int} 公元后的某一年
         * @return {@code String} 干支年
         */
        public static String getYear(int year) {
            // 假设公元后某年为 X 则先用 X 除以 60 得出余数
            int gzNum = year % 60;
    
            // 用余数减 4 不够减则加上 60 之后再减得出编号
            if (gzNum - 4 < 0) {
                gzNum = gzNum + 60 - 4;
            } else {
                gzNum = gzNum - 4;
            }
    
            // 遍历天干地支
            for (int i = 0; i < 60; i++) {
                int itg = i % TG.length; // 取余数防止数组越界
                int idz = i % DZ.length; // 同上
                if (gzNum == i) {
                    // 根据天干地支的索引进行匹配
                    return TG[itg] + DZ[idz];
                }
            }
    
            return null;
        }
    
        /**
         * 获取干支月 <br />
         * 根据干支年换算出干支月 <br />
         *
         * <p>
         * 说明:若遇甲或己的年份 ,正月是丙寅;遇上乙或庚之年,正月为戊寅;遇上丙或辛之年,正月为庚寅;遇上丁或壬之年,正月为壬寅;遇上戊或癸之年,正月为甲寅
         * </p>
         *
         * @param gzYear {@code String} 干支年
         * @param month  {@code int} 农历的月份
         * @return {@code String} 干支月
         */
        public static String getMonth(String gzYear, int month) {
            String stg = gzYear.substring(0, 1);
    
            int itgFlag = 0;
            // 如果干支年的天干位为 “甲” 或 “己”,则从 TG 数组下标的第 2 位开始
            if ("甲".equals(stg) || "己".equals(stg)) {
                itgFlag = 2;
            } else if ("乙".equals(stg) || "庚".equals(stg)) {
                itgFlag = 4;
            } else if ("丙".equals(stg) || "辛".equals(stg)) {
                itgFlag = 6;
            } else if ("丁".equals(stg) || "壬".equals(stg)) {
                itgFlag = 8;
            }
    
            for (int i = 0; i < 12; i++) {
                int itg = (i + itgFlag) % TG.length;
                int idz = (i + 2) % DZ.length;
    
                if (i == month - 1) {
                    return TG[itg] + DZ[idz];
                }
            }
    
            return null;
        }
    
        /**
         * 获取干支日 <br />
         * 根据阳历年月日换算出干支日 <br />
         * 天干 = (4 * c + c / 4 + 5 * y + y / 4 + 3 * (m + 1) / 5 + d - 3) % 10 <br />
         * 地支 = (8 * c + c / 4 + 5 * y + y / 4 + 3 * (m + 1) / 5 + d + 7 + i) % 12 <br />
         *
         * <ul>
         *     <li>c 为年份前两位,比如 2019 年则 c 为 20</li>
         *     <li>y 为年份后两位,比如 2019 年则 y 为 19</li>
         *     <li>m 为月份,1 月和 2 月按上一年的 13 月和 14 月来算</li>
         *     <li>d 为日数</li>
         *     <li>奇数月 i 为 0</li>
         *     <li>偶数月 i 为 6</li>
         * </ul>
         *
         * @param year  {@code int} 阳历年
         * @param month {@code int} 阳历月
         * @param day   {@code int} 阳历日
         * @return {@code String} 干支日
         */
        public static String getDay(int year, int month, int day) {
            String yearStr = String.valueOf(year);
            int c = Integer.parseInt(yearStr.substring(0, 2));
            int y = Integer.parseInt(yearStr.substring(2));
            // 嵌套的三元表达式,1 月和 2 月按上一年的 13 月和 14 月来算
            int m = month == 1 ? 13 : month == 2 ? 14 : month;
            if (m == 13 || m == 14) {
                y--;
            }
            int d = day;
            // 三元表达式,月份除以 2 余 0 则为偶数否则为奇数
            int i = m % 2 != 0 ? 0 : 6;
    
            int itg = (4 * c + c / 4 + 5 * y + y / 4 + 3 * m / 5 + d - 3) % 10;
            int idz = (8 * c + c / 4 + 5 * y + y / 4 + 3 * m / 5 + d + 7 + i) % 12;
    
            return TG[itg] + DZ[idz];
        }
    
        /**
         * 获取干支时 <br />
         *
         * <p>
         * 说明:根据十二时辰只能得出支,想要得到干,需要配合干支日换算
         * </p>
         *
         * @param gzDay {@code String} 干支日
         * @param time  {@code int} 24 小时制的时间
         * @return {@code String} 干支时
         */
        public static String getTime(String gzDay, int time) {
            // 取出干支日的第一个字
            gzDay = gzDay.substring(0, 1);
    
            // 换算出时间对应地支的下标位置
            int idz = 0;
            if (time >= 23 || time < 1) {
                idz = 0;
            } else if (time >= 1 && time < 3) {
                idz = 1;
            } else if (time >= 3 && time < 5) {
                idz = 2;
            } else if (time >= 5 && time < 7) {
                idz = 3;
            } else if (time >= 7 && time < 9) {
                idz = 4;
            } else if (time >= 9 && time < 11) {
                idz = 5;
            } else if (time >= 11 && time < 13) {
                idz = 6;
            } else if (time >= 13 && time < 15) {
                idz = 7;
            } else if (time >= 15 && time < 17) {
                idz = 8;
            } else if (time >= 17 && time < 19) {
                idz = 9;
            } else if (time >= 19 && time < 21) {
                idz = 10;
            } else if (time >= 21 && time < 23) {
                idz = 11;
            }
    
            int itgFlag = 8;
            // 如果干支年的天干位为 “甲” 或 “己”,则从 TG 数组下标的第 0 位开始
            if ("甲".equals(gzDay) || "己".equals(gzDay)) {
                itgFlag = 0;
            } else if ("乙".equals(gzDay) || "庚".equals(gzDay)) {
                itgFlag = 2;
            } else if ("丙".equals(gzDay) || "辛".equals(gzDay)) {
                itgFlag = 4;
            } else if ("丁".equals(gzDay) || "壬".equals(gzDay)) {
                itgFlag = 6;
            }
    
            return TG[(idz + itgFlag) % 10] + DZ[idz];
        }
    
        /**
         * 通过八字算五行
         *
         * @param gzYear  {@code String} 干支年
         * @param gzMonth {@code String} 干支月
         * @param gzDay   {@code String} 干支日
         * @param gzTime  {@code String} 干支时
         */
        public static void wuxing(String gzYear, String gzMonth, String gzDay, String gzTime) {
            // 天干年
            String gYear = gzYear.substring(0, 1);
            if ("甲".equals(gYear) || "乙".equals(gYear)) {
                gYear = "木";
            }
            if ("丙".equals(gYear) || "丁".equals(gYear)) {
                gYear = "火";
            }
            if ("戊".equals(gYear) || "己".equals(gYear)) {
                gYear = "土";
            }
            if ("庚".equals(gYear) || "辛".equals(gYear)) {
                gYear = "金";
            }
            if ("壬".equals(gYear) || "癸".equals(gYear)) {
                gYear = "水";
            }
    
            // 天干月
            String gMonth = gzMonth.substring(0, 1);
            if ("甲".equals(gMonth) || "乙".equals(gMonth)) {
                gMonth = "木";
            }
            if ("丙".equals(gMonth) || "丁".equals(gMonth)) {
                gMonth = "火";
            }
            if ("戊".equals(gMonth) || "己".equals(gMonth)) {
                gMonth = "土";
            }
            if ("庚".equals(gMonth) || "辛".equals(gMonth)) {
                gMonth = "金";
            }
            if ("壬".equals(gMonth) || "癸".equals(gMonth)) {
                gMonth = "水";
            }
    
            // 天干日
            String gDay = gzDay.substring(0, 1);
            if ("甲".equals(gDay) || "乙".equals(gDay)) {
                gDay = "木";
            }
            if ("丙".equals(gDay) || "丁".equals(gDay)) {
                gDay = "火";
            }
            if ("戊".equals(gDay) || "己".equals(gDay)) {
                gDay = "土";
            }
            if ("庚".equals(gDay) || "辛".equals(gDay)) {
                gDay = "金";
            }
            if ("壬".equals(gDay) || "癸".equals(gDay)) {
                gDay = "水";
            }
    
            // 天干时
            String gTime = gzTime.substring(0, 1);
            if ("甲".equals(gTime) || "乙".equals(gTime)) {
                gTime = "木";
            }
            if ("丙".equals(gTime) || "丁".equals(gTime)) {
                gTime = "火";
            }
            if ("戊".equals(gTime) || "己".equals(gTime)) {
                gTime = "土";
            }
            if ("庚".equals(gTime) || "辛".equals(gTime)) {
                gTime = "金";
            }
            if ("壬".equals(gTime) || "癸".equals(gTime)) {
                gTime = "水";
            }
    
            // 地支年
            String zYear = gzYear.substring(1);
            if ("寅".equals(zYear) || "卯".equals(zYear)) {
                zYear = "木";
            }
            if ("巳".equals(zYear) || "午".equals(zYear)) {
                zYear = "火";
            }
            if ("辰".equals(zYear) || "丑".equals(zYear) || "戌".equals(zYear) || "未".equals(zYear)) {
                zYear = "土";
            }
            if ("申".equals(zYear) || "酉".equals(zYear)) {
                zYear = "金";
            }
            if ("亥".equals(zYear) || "子".equals(zYear)) {
                zYear = "水";
            }
    
            // 地支月
            String zMonth = gzMonth.substring(1);
            if ("寅".equals(zMonth) || "卯".equals(zMonth)) {
                zMonth = "木";
            }
            if ("巳".equals(zMonth) || "午".equals(zMonth)) {
                zMonth = "火";
            }
            if ("辰".equals(zMonth) || "丑".equals(zMonth) || "戌".equals(zMonth) || "未".equals(zMonth)) {
                zMonth = "土";
            }
            if ("申".equals(zMonth) || "酉".equals(zMonth)) {
                zMonth = "金";
            }
            if ("亥".equals(zMonth) || "子".equals(zMonth)) {
                zMonth = "水";
            }
    
            // 地支日
            String zDay = gzDay.substring(1);
            if ("寅".equals(zDay) || "卯".equals(zDay)) {
                zDay = "木";
            }
            if ("巳".equals(zDay) || "午".equals(zDay)) {
                zDay = "火";
            }
            if ("辰".equals(zDay) || "丑".equals(zDay) || "戌".equals(zDay) || "未".equals(zDay)) {
                zDay = "土";
            }
            if ("申".equals(zDay) || "酉".equals(zDay)) {
                zDay = "金";
            }
            if ("亥".equals(zDay) || "子".equals(zDay)) {
                zDay = "水";
            }
    
            // 地支时
            String zTime = gzTime.substring(1);
            if ("寅".equals(zTime) || "卯".equals(zTime)) {
                zTime = "木";
            }
            if ("巳".equals(zTime) || "午".equals(zTime)) {
                zTime = "火";
            }
            if ("辰".equals(zTime) || "丑".equals(zTime) || "戌".equals(zTime) || "未".equals(zTime)) {
                zTime = "土";
            }
            if ("申".equals(zTime) || "酉".equals(zTime)) {
                zTime = "金";
            }
            if ("亥".equals(zTime) || "子".equals(zTime)) {
                zTime = "水";
            }
    
            // 输出五行
            String wuxing = gYear + zYear + gMonth + zMonth + gDay + zDay + gTime + zTime;
            System.out.println("您的八字五行为:" + wuxing);
    
            // 算出五行缺啥
            String que = "您的五行缺:";
            if (!wuxing.contains("金")) {
                que += "金";
            }
            if (!wuxing.contains("木")) {
                que += "木";
            }
            if (!wuxing.contains("水")) {
                que += "水";
            }
            if (!wuxing.contains("火")) {
                que += "火";
            }
            if (!wuxing.contains("土")) {
                que += "土";
            }
            System.out.println(que.equals("您的五行缺:") ? "恭喜,您的五行不缺" : que);
        }
    }
    
    
    展开全文
  • 计算生辰八字五行属性的算法

    万次阅读 热门讨论 2013-01-26 14:02:13
    计算生辰八字五行属性的算法 潘爱民 2013/1/26   缘起:几年前,小儿出生的几天之内,我需要为他起名字。人生难得接一两回这样的任务,更是格外珍惜。我调研了几种起名字的思路,最终确定按照五行阴阳平衡的...
  • 本篇 分享总结的Vue中的生命周期函数的使用方法,及计算属性,方法与监听,和一些数组的处理方法 都写在了一个文件中了。但是有详细的标注 <!DOCTYPE html> <html lang="en"> <head> <meta...
  • 2004-01-09 10:04:00
    ,技术仍然重要,但文化属性已经显现。   想像一下如果未来人们用 IT 资源真的像用电或用自来水一样,那时 IT 技术在人们的眼中会是什么样子? IT 企业在人们眼中会是什么样子? IT 业内人士在人们眼中会是...
  • 运算符、属性属性观察器、方法、下脚标本、继承、构造器
  • 插入在属性访问时运行的代码1.__getattr__ 和 __setattr__ 方法,把未定义的属性获取和所有的属性赋值指向通用 的处理器方法。2.__getattribute__ 方法,把所有属性获取都指向Python 2.6的新式类和Python 3.0的 所有...
  • 整理PivotGridControl一些属性

    千次阅读 2019-02-16 14:28:36
    通过CreateSummaryDataSource方法创建数据源时,获取或设置对应于数据字段名列的规则 PivotGridControl.OptionsDataField.RowHeaderWidth  获取或设置数据字段标头的宽度,当它们作为行标头显示时。 ...
  • matlab plot 属性设置

    2016-12-22 09:56:44
     root 的 ScreenSize 属性:只读属性,默认单位为像素( pixel ),由屏幕的左下角坐标、宽度、高度四个参数确定。  >> ss = get(0,'ScreenSize'),返回行向量 ss = [ left, bottom, width, height ] ...
  • Android CardView属性和使用总结

    千次阅读 2018-08-06 18:39:31
    CardView的使用: 如果不知道要依赖的cardview的版本,可以通过以下操作添加依赖: 1、鼠标放在要添加依赖的module上,右键选择Open Module Settings,如图1...CardView属性介绍: Google官方对CardView的一句话...
  • 计算机各种编码

    千次阅读 2015-04-30 10:13:17
    网页里的form编码其实不完全取决于网页编码,form标记中有一个accept-charset属性,在非ie浏览器种,如果将其赋值(比如 accept-charset="UTF-8"),则表单会按照这个值表示的编码方式进行提交。 在ie下,我的兼容...
  • Winform(C#)Flash控件 属性 方法 事件

    千次阅读 2015-08-25 11:42:21
    属性: 1.AlignMode (读写) 语法:AlignModeAs Long 说明:对齐方式(与SAlign 属性联动)。当控件的长宽比例与影片不一致且 WMode 不为 ExactFit 时,影片(没有被放大的)在控件中显示的位置可用该属性调整。...
  • 一,修改表 PostgreSQL 提供了一族命令用于...重名字段, 重命名表。 这些操作可以用:ALTER TABLE命令执行的。 1,增加字段 要增加一个字段,使用这条命令: ALTER TABLE products ADD COLUMN description text;
  • VCL组件属性和方法详解

    千次阅读 2010-05-06 21:49:00
    一、TApplication 继承关系:TObject → TPersistent → TComponent TApplication组件的属性:ActiveAllowTestingDialogHandleExeNameHand
  • 学计算机的方向

    千次阅读 2015-11-07 20:59:59
    2.计算机是具有学术性和工具性的双重属性学课。架设一做计算级专业与你本专业的桥梁,那对两个专业都是做出了贡献,如果你真的很牛,把计算机学的很深很好,那么你真的值得尊敬。  3.再次记住做网页,做图片,做...
  • 如何尽快发表高水平的计算机学术论文

    千次阅读 多人点赞 2019-10-16 19:10:01
    会议、细分领域、作者、发表年份、引用量等属性来细挑出真正重要的paper来读 。 至于写paper本身就是玩命想玩命读玩命做实验,而且要经常根据实验结果改换研究方法、甚至是研究问题本身的重心。当然,最重要的其实...
  • 计算机常用命令大全

    千次阅读 2018-07-25 16:21:22
    regedit.exe 注册表 gpedit.msc 组策略 services.msc 服务命令 c:\&gt;ntsd -c q -p PID 关进程 tasklist 查进程 net user 查找用户 net user '用户名' '密码' 更改用户密码 net ...
  • 到底是谁革了手机的?!

    千次阅读 2011-09-11 17:59:09
    做产品工作,最重要的是搞清楚产品的本质、核心属性。往往由于对事物本质与核心属性理解的不同,不觉中就悄然改变了产品的定义。手机现在就是这么一个状况,“乱花渐入迷人...手机被革了!  手机,“手持无线电话机
  • VCL组件的属性和方法详解(1)

    千次阅读 2010-05-07 16:24:00
    一、TApplication 继承关系:TObject → TPersistent → TComponent TApplication组件的属性:...
  • qt入门之常用窗口在qt中对应的名称
  • 表空间创建格式及属性说明

    千次阅读 2012-08-20 17:40:05
    如果minextents>1,盘区大小以next和pctincrease为基础计算。】 8、[BLOCKSIZE integer [k]]  这个参数可以设定一个不标准的块的大小。如果要设置这个参数,必须设置db_block_size,至少一个db_nk_block_size, ...
  • 每日一面系列之HashMap夺连环问

    千次阅读 2020-06-29 17:28:02
    集合框架必问之HashMap连环夺问,看看你能答上来多少!
  • Internet属性 dxdiag 检查DirectX信息 intl.cpl 区域 eudcedit 造字程序 iexpress 木马捆绑工具 eventvwr 事件查看器 joy.cpl 游戏控制器 explorer ...
  • Linux中显示系统中USB信息的lsusb

    千次阅读 2018-05-24 09:03:18
    在Linux上,我们可以使用lsusb来列出USB设备和它的属性。什么是lsusb在它的手册上,lsusb定义成:显示系统中以及连接到系统的USB总线信息的工具。如何运行lsusb? 要运行lsusb,你可以直接在控制台输入lsusb。$ lsusb...
  • /*存储属性************************************************************/ //一个存储属性就是存储在特定类或结构体的实例里的一个常量或变量。 //下面的例子定义了一个名为 FixedLengthRange 的结构体,它...
  • 数据库复习题选择题+判断题+填空题(考试续必备 一些选择题 1、从计算机数据管理的角度看,信息就是数据,数据就是信息。(B ) A、对 B、错 (描述事物的符号记录称为数据 数据库的数据项之间无联系,...
  • 计算机概念

    千次阅读 2011-09-30 11:02:40
    有一条公式可以计算,即数据带宽=(总线频率×数据带宽)/8,数据传输最大带宽取决于所有同时传输的数据的宽度和传输频率。比方,现在的支持64位的至强Nocona,前端总线是800MHz,按照公式,它的数据传输最大带宽是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,186
精华内容 6,074
关键字:

命的属性如何计算